好吧我可以绘制椭圆问题就是这个,我试图绘制一个椭圆但是将其x值更改为不同的椭圆。像这样我绘制一个椭圆,十秒后x值为1我希望它的x值为10但似乎我正在创建x值为10的新椭圆。这里是我的代码
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);
}
我认为无效的rect会清除所有已绘制的内容并重新绘制但不起作用
答案 0 :(得分:0)
您不应该尝试一次性绘制多个动画帧。
将变量sf
保存在某处,在OnPaint()
中,增加sf
,绘制一个椭圆,然后调用Invalidate()
Invalidate
会再次触发OnPaint()
。
这应该可行,但会非常闪烁:)你可以通过双缓冲来修复闪烁。
答案 1 :(得分:0)
如果你想制作动画,最好设置一个计时器。
使用InvalidateRect作为生成WM_PAINT的方法似乎有点过头了,它会做得更多。相反,您可以直接在OnTimer调用中绘制,因为它位于WM_PAINT之外,您需要使用GetDC获取设备上下文。
例如,如果您可以使用DrawFrame(HDC hDC)功能。 OnTimer将更新当前位置并调用DrawFrame,OnPaint将调用DrawFrame但不会更新位置(如果您想停止动画,那么您将获得最后一帧绘制)。
DrawFrame将清除背景(可能使用FillRect),并在新位置绘制圆圈。如果你有一个大的区域,这将闪烁,以避免它,因为汤姆建议你可以使用内存DC和HBITMAP的双缓冲区。
答案 2 :(得分:-1)
InvalidateRect
将窗口标记为“无效”,但这不会导致擦除和重绘立即发生。擦除和绘画仅在您的消息泵运行时发生(例如,带有GetMessage
和DispatchMessage
的循环)。当邮件队列枯竭时,GetMessage
将为无效窗口合成WM_ERASEBKGND
和WM_PAINT
条消息。当这些消息被分派到窗口过程时,窗口有机会绘制。
您的onPaint
功能仅绘制,不会删除。由于你的循环永远不会退出,因此消息泵永远不会运行。
对于简单的动画,解决方案是SetTimer
。在WM_TIMER
消息的处理程序中,更新单帧的变量,调用InvalidateRect
,然后返回(使消息泵继续运行)。将删除和绘画消息,然后定时器将再次触发,您将获得下一帧。