Animation woes

#include <windows.h>

void DrawPolygonT(HWND &,
                          const int,
                          const int,
                          const int,
                          const int,
                          const int,
                          const int,
                          const int);
void DrawPolygonO(HWND &,
                          const int,
                          const int,
                          const int,
                          const int);
void DrawPolygonM(HWND &hwnd,
                          const int temp_start_x,
                          const int temp_start_y,
                          const int temp_width,
                          const int temp_height);

//void DrawM(HWND &, HDC &, PAINTSTRUCT &);
void WaitPeriod(int DelayFactor);

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("LineDemo") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Program 2 by Thomas Knowlton"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static int  cxClient, cyClient ;
     HDC         hdc ;
       HDC             hdc2;
     PAINTSTRUCT ps ;
       RECT rect;
       int xcounter,
             ycounter;
       const int MAX_X = 100;
       const int MAX_Y = 100;
       const int T_X_POS = 50;
       const int O_X_POS = 200;
       const int M_X_POS = 330;
       const int O_START_X = 150;
       const int O_START_Y = 20;
       const int O_HEIGHT= 140;
       const int O_WIDTH = 80;
       const int T_START_X = 20;
       const int T_START_Y = 20;
       const int T_TOP_WIDTH = 100;
       const int T_SIDEBAR_HEIGHT = 40;
       const int T_DIST_IN = 30;
       const int T_VERTICAL_BAR_HEIGHT = 100;
       const int T_BOTTOM_WIDTH = 40;
       const int M_WIDTH = 40;
       const int M_HEIGHT = 140;

     
     switch (message)
     {
     case WM_SIZE:
          cxClient = LOWORD (lParam) ;
          cyClient = HIWORD (lParam) ;
          return 0 ;
         
     case WM_PAINT:
             hdc = BeginPaint (hwnd, &ps) ;
             for(ycounter = 300; ycounter >= 20; ycounter--)
                   {
                          DrawPolygonT(hwnd,
                              T_X_POS,
                              ycounter,
                              T_TOP_WIDTH,
                              T_SIDEBAR_HEIGHT,
                              T_DIST_IN,
                              T_VERTICAL_BAR_HEIGHT,
                              T_BOTTOM_WIDTH);
                        
                        
                  /* DrawPolygonO(hwnd,
                                hdc,
                                ps,
                                O_X_POS,
                                ycounter,
                                O_WIDTH,
                                O_HEIGHT);
                          DrawPolygonM(hwnd,
                                hdc,
                                ps,
                                M_X_POS,
                                ycounter,
                                M_WIDTH,
                                M_HEIGHT);*/
                         
                          WaitPeriod(1);                                                    
                    }
                 
          EndPaint (hwnd, &ps) ;
          return 0 ;
         
     case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}



void DrawPolygonT(HWND &hwnd,
                          const int temp_start_x,
                          const int temp_start_y,
                          const int temp_t_top_width,
                          const int temp_sidebar_height,
                          const int temp_dist_in,
                          const int temp_vert_bar_height,
                          const int temp_bottom_width)
{

      HDC hdc;
      const int T_RED = 100;
      const int T_GREEN = 200;
      const int T_BLUE = 200;
      const int START_X = temp_start_x;
      const int START_Y = temp_start_y;
      const int T_TOP_WIDTH = temp_t_top_width;
      const int T_TOP_WAYPOINT = START_X + T_TOP_WIDTH;
      const int SIDEBAR_HEIGHT = temp_sidebar_height;
      const int DIST_IN = temp_dist_in;
      const int RIGHT_DIST_IN = T_TOP_WAYPOINT - DIST_IN;
      const int VERTICAL_BAR_HEIGHT = temp_vert_bar_height;
      const int BOTTOM_WIDTH = temp_bottom_width;
      const int NUM_POINTS = 9;

      POINT apt[NUM_POINTS];

      apt[0].x = START_X;
      apt[0].y = START_Y;

      apt[1].x = T_TOP_WAYPOINT;
      apt[1].y = START_Y;

      apt[2].x = T_TOP_WAYPOINT;
      apt[2].y = START_Y + SIDEBAR_HEIGHT;

      apt[3].x = RIGHT_DIST_IN;
      apt[3].y = START_Y + SIDEBAR_HEIGHT;

      apt[4].x = RIGHT_DIST_IN;
      apt[4].y = START_Y + SIDEBAR_HEIGHT + VERTICAL_BAR_HEIGHT;
      
      apt[5].x = RIGHT_DIST_IN - BOTTOM_WIDTH;
      apt[5].y = START_Y + SIDEBAR_HEIGHT + VERTICAL_BAR_HEIGHT;
      
      apt[6].x = RIGHT_DIST_IN - BOTTOM_WIDTH;
      apt[6].y = START_Y + SIDEBAR_HEIGHT;

      apt[7].x = START_X;
      apt[7].y = START_Y + SIDEBAR_HEIGHT;
      
      apt[8].x = START_X;
      apt[8].y = START_Y;

      hdc = GetDC(hwnd);
      SelectObject(hdc,CreateHatchBrush(HS_DIAGCROSS,RGB(T_RED, T_GREEN, T_BLUE)));
      Polygon(hdc, apt, NUM_POINTS);
      DeleteObject(GetStockObject(BLACK_PEN));
      ReleaseDC(hwnd, hdc);      
}


void DrawPolygonO(HWND &hwnd,
                          const int temp_start_x,
                          const int temp_start_y,
                          const int temp_width,
                          const int temp_height)
{

      HBRUSH hBrush;
      HDC hdc;
      const int RED = 200;
      const int GREEN = 100;
      const int BLUE = 100;
      const int START_X = temp_start_x;
      const int START_Y = temp_start_y;
      const int WIDTH = temp_width;
      const int HEIGHT= temp_height;
      const int TOP_WAYPOINT = START_X + WIDTH;
      const int NUM_POINTS = 5;

      POINT apt[NUM_POINTS];

      apt[0].x = START_X;
      apt[0].y = START_Y;

      apt[1].x = TOP_WAYPOINT;
      apt[1].y = START_Y;

      apt[2].x = TOP_WAYPOINT;
      apt[2].y = START_Y + HEIGHT;

      apt[3].x = START_X;
      apt[3].y = START_Y + HEIGHT;

      apt[4].x = START_X;
      apt[4].y = START_Y;
      
      
      hBrush = CreateHatchBrush(HS_HORIZONTAL,RGB(RED, GREEN, BLUE));
      SelectObject(hdc,hBrush);
      Polygon(hdc, apt, NUM_POINTS);
      DeleteObject(hBrush);
      //Create "inner O" by drawing a rectangle inside the "Outer O"
      //Use a WHITE_BRUSH to erase the hatch lines!
      SelectObject(hdc, GetStockObject(WHITE_BRUSH));
      Rectangle(hdc,
            START_X + 20,
            START_Y + 20,
            TOP_WAYPOINT - 20,
            START_Y + HEIGHT - 20);
      ReleaseDC(hwnd, hdc);
}


void DrawPolygonM(HWND &hwnd,
                          const int temp_start_x,
                          const int temp_start_y,
                          const int temp_width,
                          const int temp_height)
{

      HBRUSH hBrush;
      HDC hdc;
      const int RED                  = 200;
      const int GREEN                  = 100;
      const int BLUE                  = 200;
      const int START_X            = temp_start_x;
      const int START_Y            = temp_start_y;
      const int WIDTH                  = temp_width;
      const int HEIGHT            = temp_height;
      const int NUM_POINTS      = 13;

      POINT apt[NUM_POINTS];

      apt[0].x = START_X;
      apt[0].y = START_Y;

      apt[1].x = START_X + WIDTH;
      apt[1].y = START_Y;

      apt[2].x = START_X + (2 * WIDTH);
      apt[2].y = START_Y + HEIGHT - (2 * WIDTH);

      apt[3].x = START_X + (3 * WIDTH);
      apt[3].y = START_Y;

      apt[4].x = START_X + (4 * WIDTH);
      apt[4].y = START_Y;

      apt[5].x = START_X + (4 * WIDTH);
      apt[5].y = START_Y + HEIGHT;

      apt[6].x = START_X + (3 * WIDTH);
      apt[6].y = START_Y + HEIGHT;

      apt[7].x = START_X + (3 * WIDTH);
      apt[7].y = START_Y + (2 * WIDTH);

      apt[8].x = START_X + (2 * WIDTH);
      apt[8].y = START_Y + HEIGHT;

      apt[9].x = START_X + WIDTH;
      apt[9].y = START_Y + (2 * WIDTH);
      
      apt[10].x = START_X + WIDTH;
      apt[10].y = START_Y + HEIGHT;
      
      apt[11].x = START_X;
      apt[11].y = START_Y + HEIGHT;
      
      apt[12].x = START_X;
      apt[12].y = START_Y;
            
      hBrush = CreateHatchBrush(HS_HORIZONTAL,RGB(RED, GREEN, BLUE));
      SelectObject(hdc,hBrush);
      Polygon(hdc, apt, NUM_POINTS);
      DeleteObject(hBrush);
      ReleaseDC(hwnd, hdc);
}


void WaitPeriod(int DelayFactor)
{
      
      const int MAX_WAIT = 500;
      int counter1, counter2;
      if (DelayFactor < 1)
            DelayFactor = 1;
      for (counter1 = 0; counter1 < MAX_WAIT * DelayFactor; counter1++)
            for (counter2 = 0; counter2 < MAX_WAIT * DelayFactor; counter2++);
}
LVL 5
Tom KnowltonWeb developerAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ZoppoCommented:
Hi knowlton,

You should give us a hint what your problem is when posting some hundred lines of code ...

ZOPPo
0
GlennDeanCommented:
One problem I see is in DrawPolyT you're call to DeleteObject is wrong.  You want to save the handle returned by CreateHatchBrush (as you did in your other two functions) and then call DeleteObject on it.
0
Tom KnowltonWeb developerAuthor Commented:
Test
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Tom KnowltonWeb developerAuthor Commented:
My connection went south before I could tell you guys why I posted the code.

I want the 3 block letters to come up from the bottom of the client area.  I am drawing the letters in a slightly new Y position each time, and then I want to ERASE the client area before I draw the letter in a new position (slightly higher than the last postion).  If you do this quickly, it gives the illusion that the letters are "moving" or "animated"

I have already written all the code necessary to DRAW and MOVE the letters, I just need some help getting the screen to refresh or erase properly between draws, taking into account the hdc and stuff.

My understanding is that hdc = GetDC(hwnd) returns the ENTRE client area, not jus the invalid rect.

My brain is turning to mush.  Somebody explain how I can do simple animation.

0
Tom KnowltonWeb developerAuthor Commented:
GlennDean:

Consider the following code excerpt (from DrawPolyT above)


hdc = GetDC(hwnd);                       SelectObject(hdc,CreateHatchBrush(HS_DIAGCROSS,RGB(T_RED, T_GREEN, T_BLUE)));
                      Polygon(hdc, apt, NUM_POINTS);
DeleteObject(GetStockObject(BLACK_PEN));
                      ReleaseDC(hwnd, hdc

What is actually happening here in reality?  What do you see happening after each line executes and why is it wrong?

Help me understand the rationale behind hdc and Selecting / Deleting "objects" in Win32.

Thanks!
0
GlennDeanCommented:
knowlton:
   Two comments:
1.  You're call to DeleteObject is trying to delete a system GDI object, not one you created - never suppose to do that.

2.  I think I may see one major problem you're having.  You're NOT trying to draw a polygon but rather a sequence of lines.  Function Polygon "connects the points" with the currently selected pen and then fills the enclosed area with the currently selected brush (obviously not what you want, which is to draw letters).
   So, to solve the problem you simply want to call Polyline.  Keep in mind that to draw, for ex. the letter Y, you'll have to make two calls to Polyline since you can't draw Y with one call.

On your question on why to Select/Delete GDI objects, it's basically because you don't want to hold on those resources any longer than you have to.  I know I shouldn't say this, but if the pen and hatch brush are the same every single time, just allocate them once.  BUT, if you're pen and hatch brush change all the time, delete them as soon as possible.  You'll be "shocked" at how few GDI objects you can create before things start going south on you.  In one test program, it got to something like only 1400 pens allocated and things went south (I thought it would go bad say in the millions).
   Glenn
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
GlennDeanCommented:
With Polyline you don't need the brush.

Don't forget that even if you allocate the pen once for drawing your letters, you should still

 -Draw, over the previously drawn letters with the currently selected pen, which I'll assume is white
 -Select your pen, saving old pen
 -Figure out where new letters should go
 -Draw letters
 -Select old pen

GetDC returns the client area only.  To get the entire window, call GetWindowDC.
  Glenn
0
GlennDeanCommented:
Just looked at me 'ol notes on GDI and it appears it doesn't do any harm to delete stock pens and brushes.  
  So, the following is O.K.:
HBRUSH hbrush = GetStockBrush(LTGRAY_BRUSH);
HBRUSH holdbrush = SelectBrush(hdc,hbrush);
"Do whatever code"
SelectBrush(hdc,holdbrush);
DeleteBrush(hbrush);

BUT, you can skip the call to DeleteBrush since it's a stock brush.

My assumption in my above comment is bad.  The default pen is black so, to erase the previous stuff, you need to the the stock pen white, select it, then erase what you drew before.  
0
Tom KnowltonWeb developerAuthor Commented:
GlennDean:

I have not had a chance to try PolyLine instead of Polygon.

You have some good advice, I think.  As soon as I get a chance to try it out, I'll come back here and give you the points.

Thanks!

Tom
0
Tom KnowltonWeb developerAuthor Commented:
I don't remember accepting this answer, but "okay".
0
GlennDeanCommented:
Did you get PoloyLine to work?
0
Tom KnowltonWeb developerAuthor Commented:
Glenn:

I still haven't tried it.

Here's what I will do.  If it does not work I will come back and post a comment asking for more help.

Thanks for your help!

Tom
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.