Question

im trying to create ball animation using gdi but i can't get it working. i created a ball using this

   Graphics graphics(hdc);

Pen pen(Color(255, 0, 0, 255)); graphics.DrawEllipse(&pen, sf , 0, 10, 10); i have while loop that loops and adds 1 to sf value basicly like this sf++; than i try to repaint the window(it doesn't work) so ill end up with more than one circle ;/ here is the loop( the loop is int WM_PAINT)

while(sd==1)//sd equals 1
    {
        sf++;
        onPaint(hdc);
        InvalidateRect (hWnd, NULL, TRUE);// this should repaint the window but it doesn't
        UpdateWindow(hWnd);
    }

thanks in advance Rami

Was it helpful?

Solution

In order to achieve animation I would suggest you use a timer. For example:

int OnCreate(HWND window, WPARAM wParam, LPARAM lParam)
{
   SetTimer(window, TIMER_ID, 1000, 0);
   return 0;
}

now window will receive WM_TIMER messages every second (1000ms). You should handle them:

int OnTimer(HWND window, WPARAM wParam, LPARAM lParam)
{
   if(TIMER_ID == wParam)
   {
      /*do stuff*/
      InvalidateRect(window, NULL, TRUE);//force window to repaint
   }
   return 0;
}

then you need to handle WM_PAINT message to do the drawing

int OnPaint(HWND window, WPARAM wParam, LPARAM lParam)
{
   PAINTSTRUCT ps;
   HDC dc = BeginPaint(&ps);
   Graphics graphics(hdc);
   graphics.Draw...
   EndPaint(&ps);
   return 0;
}

OTHER TIPS

You do realize that you are incrementing sf in a loop with a conditional of (sd == 1), right? That will of course just loop infinitely or never be entered because the value of sd is not being changed in any way. Have you used the debugger at all here? Why would you need such a loop anyway? You should not be calling OnPaint in a loop.

If you want more than one circle, just draw them all before returning from the function. Maintain a collection of data that will be used to draw the circles in the OnPaint handler.

InvalidateRect sends a WM_ERASEBKGND message, and if you don't have a hbrBackground (brush to repaint the background) member of the WNDCLASS structure defined when you create the window it won't redraw the background unless you handle the WM_ERASEBKGND message yourself.

If that isn't the problem, then maybe because you are calling UpdateWindow directly instead of polling and handling messages, the WM_ERASEBKGND message never gets handled. Try overwriting the previous circle with the background colour before drawing the new one.

Or call SendMessage with WM_ERASEBKGRND as the message.

I found an example on msdn which shows how to draw stuff in pure win32.

You should not call Invalidate or Updatewindow in WM_PAINT, as UpdateWindow sends a new WM_PAINT-event, and invalidates get accumulated until the next wm_paint event.

You should divide your Code into two functions, one to perform the movement and the other to draw your circle at the current location.

Your Mover-function can be called from anywhere (perhaps in a timer handler function?) and should end with

InvalidateRect (hWnd, NULL, TRUE);
UpdateWindow(hWnd);

In order to mark your client area for redrawal and notify your window to redraw itself.

Your Draw()-function should read the position set with your mover function, and just a draw a circle around this location.

(Sidenote: If you want to minimize flicker and get smooth animation, have a look at double buffering once you get your basic animation up and running)

UPDATE

You were missing the UpdateWindow command in your Update-function Your OnPaint-Function is only called when a WM_PAINT-message is received by your application, so you need to send those.

UpdateWindow serves this purpose

VOID update(HDC hdc,HWND hWnd) 
{ 
    sf++; 
    FillRect(hdc,rect,(HBRUSH)(COLOR_WINDOW+1)); 
    InvalidateRect (hWnd, NULL, TRUE); 
    UpdateWindow(hWND);//<- This Line sends a wm_paint-message to your window in order to make it redraw itself
} 
//i didn't do any changes to the onPaint functon but here is the code for it 
VOID onPaint(HDC hdc) 
{ 
    Graphics graphics(hdc); 
    Pen pen(Color(255, 0, 0, 255)); 
    graphics.DrawEllipse(&pen, sf , 0, 10, 10); 
} 

//here is the while loop 
while(sd==1) 
{   onPaint(hdc); 
    update(hdc,hWnd); 
} 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top