views:

35

answers:

3

ok i can draw ellipse the problem is this, im trying to draw one ellipse but change its x value to different one. like this i draw one ellipse and the x value is 1 after ten seconds i want it the x value to be 10 but it seems that im creating new ellipse with x value 10. here is my code

while(sd==1)//sd equal 1 
{
    sf++;//sf equals 1
    onPaint(hdc);
    InvalidateRect(hWnd,0,true);
}
//on paint function
VOID onPaint(HDC hdc)
{
   Graphics graphics(hdc);
   Pen      pen(Color(255, 0, 0, 255));
   graphics.DrawEllipse(&pen,sf , 0, 50, 50);
}

well i thought that invalidate rect will clear everything have been painted and repaint it but it didn't work

A: 

You shouldn't try to draw multiple frames of an animation in one shot.

Save your variable sf somewhere, and in OnPaint(), increment sf, draw a single ellipse, and call Invalidate()

The Invalidate will trigger OnPaint() to be called again.

This should work, but will be very flickery :) You can fix the flicker by double-buffering.

Tom Sirgedas
well it draws more then one and sf is golabe varabile
Ramiz Toma
A: 

If you want to make an animation you are better setting a timer.

Using InvalidateRect as a way to generate WM_PAINTs seems overkill, it will do much more thant that. Instead you can draw directly in OnTimer call, since it is outside a WM_PAINT you will need to get a device context with GetDC.

For example if you can have the function DrawFrame(HDC hDC). OnTimer will update the current position and call DrawFrame, OnPaint will call DrawFrame but will not update the position (that way if you want to stop the animation you will have the last frame draw).

The DrawFrame will clear the background (probably with a FillRect), and draw the circle in the new position. If you have a large area this will flicker, to avoid it as Tom suggested you may use a memory DC and a HBITMAP for the double buffer.

Ismael
ok thanks for the details but can you give me an example how to use the getDC and what function should i use to update
Ramiz Toma
It is really easy `HDC hDC = GetDC(hWnd)` check http://msdn.microsoft.com/en-us/library/dd144871(VS.85).aspx. You should update when OnTimer is fired that way you will have a smooth animation.
Ismael
A: 

InvalidateRect marks the window as "invalid", but that doesn't cause an erase and repaint to happen right away. The erasing and painting happen only when your message pump is running (e.g., the loop with GetMessage and DispatchMessage). When the message queue runs dry, GetMessage will synthesize WM_ERASEBKGND and WM_PAINT messages for the invalid windows. When those messages are dispatched to the window procedure, the window gets a chance to draw.

Your onPaint function only draws, it doesn't erase. And since your loop never exits, the message pump never gets to run.

For simple animations, the solution is to SetTimer. In your handler for the WM_TIMER messages, update your variables for single frame, call InvalidateRect, and return (which lets the message pump keep running). The erasing and painting message will happen, then the timer will fire again, and you'll get the next frame.

Adrian McCarthy
Can anyone explain why this post was downvoted? It explains why the InvalidateRect doesn't work the way the questioner expected.
Adrian McCarthy