views:

87

answers:

4

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

+2  A: 

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.

Ed Swangren
i know it will loop for ever... this is for testing only.. all i want to do is this make one circle everytime the while loop loops the circle location changes but it doesn't it creates more than one circle with different location. like this i create a circle and the x value is 1, while loop loops and than the circle x is now 2 but it creates new circle with x vlaue 2
Ramiz Toma
i don't want more than one cirlce i only want one circle that will change its place like if the cicle i created with x = 5px,y=10. than it will loop than it will change the x to x=6px the older cicler should be gone and the new circle with x=6 should be created
Ramiz Toma
A: 

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.

DominicMcDonnell
i have defind this brush hbrBackground = (HBRUSH)(COLOR_WINDOW+1);even if i delete the update it won't help
Ramiz Toma
Deleting the UpdateWindow won't do anything as you are in a tight loop, and the only reason that it is displaying is that you are calling UpdateWindow, which calls your message handler directly. As I said, call SendMessage (which also calls your message handler directly) with WM_ERASEBKGND as the message. InvalidateRect only posts messages and expects you to poll the message queue to handle them.
DominicMcDonnell
ok so ill have the WM_ERASEBKGND but what should i have inside it like thiscase WM_ERASEBKGND://what should i put herebreak;and should i change anything in the loophere is the full code http://pastesite.com/18047
Ramiz Toma
A: 

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); 
} 
sum1stolemyname
oki greated one new functionVOID update(HDC hdc,HWND hWnd){ sf++; FillRect(hdc,rect,(HBRUSH)(COLOR_WINDOW+1)); InvalidateRect (hWnd, NULL, TRUE);}i didn't do any changes to the onPaint functon but here is the code for itVOID onPaint(HDC hdc){ Graphics graphics(hdc); Pen pen(Color(255, 0, 0, 255)); graphics.DrawEllipse(}here is the while loop while(sd==1) { onPaint(hdc); update(hdc,hWnd); }now i got thisit created one circle and that is itany idea ?
Ramiz Toma
+2  A: 

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;
}
Tassos
umm.. it paint one circle and that is ityou can see the full code over herehttp://pastesite.com/18049
Ramiz Toma
@Ramiz you should call OnCreate on WM_CREATE message, in WndProc:--edit: sorry ignore the comment, I didn't notice that you call the OnCreate.
Tassos
ok well now it creates a cirlce with x=1 than it creates circle with x=2 ............ it never deletes the old circle
Ramiz Toma
you should clear the background first ie: graphics.Clear(Color::White)
Tassos
You should pass TRUE as the last parameter in InvalidateRect (I should have done it, sorry). I'll edit the answer.
Tassos
let just say you are genius
Ramiz Toma
can you help me with double buffer?
Ramiz Toma
Make a global variable Bitmap as big as your window.In OnTimer draw in that bitmap.In OnPaint call graphics.DrawImage(bitmap, client_rect);to avoid flicker you should also pass a NULL_BRUSH in wcex.hbrBackground and/or call InvalidateRect with FALSE.
Tassos