Link to home
Start Free TrialLog in
Avatar of Tom Knowlton
Tom KnowltonFlag for United States of America

asked on

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++);
}
Avatar of Zoppo
Zoppo
Flag of Germany image

Hi knowlton,

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

ZOPPo
Avatar of GlennDean
GlennDean

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.
Avatar of Tom Knowlton

ASKER

Test
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.

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!
ASKER CERTIFIED SOLUTION
Avatar of GlennDean
GlennDean

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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
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.  
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
I don't remember accepting this answer, but "okay".
Did you get PoloyLine to work?
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