3

我试图使用 gdi 创建球动画,但我无法让它工作。我用这个创造了一个球

   Graphics graphics(hdc);

笔笔(颜色(255, 0, 0, 255));graphics.DrawEllipse(&pen, sf, 0, 10, 10); 我有 while 循环,它循环并将 1 添加到 sf 值,基本上就像这个 sf++;比我尝试重新绘制窗口(它不起作用)所以最终会出现不止一个圆圈;/这是循环(循环是 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);
    }

提前感谢拉米

4

4 回答 4

5

为了实现动画,我建议你使用计时器。例如:

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

现在窗口将每秒(1000 毫秒)接收 WM_TIMER 消息。你应该处理它们:

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

那么你需要处理 WM_PAINT 消息来进行绘图

int OnPaint(HWND window, WPARAM wParam, LPARAM lParam)
{
   PAINTSTRUCT ps;
   HDC dc = BeginPaint(&ps);
   Graphics graphics(hdc);
   graphics.Draw...
   EndPaint(&ps);
   return 0;
}
于 2010-08-10T07:28:13.890 回答
2

您确实意识到您正在以 (sd == 1) 为条件的循环中递增 sf,对吗?这当然会无限循环或永远不会输入,因为 sd 的值没有以任何方式改变。你在这里使用过调试器吗?你为什么需要这样的循环呢?您不应该在循环中调用 OnPaint。

如果您想要多个圆圈,只需在从函数返回之前将它们全部绘制出来。维护将用于在 OnPaint 处理程序中绘制圆圈的数据集合。

于 2010-08-10T04:42:35.850 回答
0

InvalidateRect 发送 WM_ERASEBKGND 消息,如果您在创建窗口时没有定义 WNDCLASS 结构的 hbrBackground(刷子重绘背景)成员,除非您自己处理 WM_ERASEBKGND 消息,否则它不会重绘背景。

如果这不是问题,那么可能是因为您直接调用 UpdateWindow 而不是轮询和处理消息,WM_ERASEBKGND 消息永远不会得到处理。在绘制新圆圈之前,尝试用背景颜色覆盖前一个圆圈。

或者使用 WM_ERASEBKGRND 作为消息调用 SendMessage。

于 2010-08-10T05:38:14.760 回答
0

我在 msdn 上找到了一个示例,它显示了如何在纯 win32 中绘制内容。

您不应该在 WM_PAINT 中调用 Invalidate 或 Updatewindow,因为 UpdateWindow 会发送一个新的 WM_PAINT 事件,并且在下一个wm_paint 事件之前会累积无效。

您应该将您的代码分为两个功能,一个用于执行移动,另一个用于在当前位置绘制您的圆圈。

您的 Mover 函数可以从任何地方调用(也许在计时器处理函数中?)并且应该以

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

为了标记您的客户区进行重绘并通知您的窗口重绘自身。

你的 Draw() 函数应该读取你的移动函数设置的位置,然后在这个位置周围画一个圆圈。

(旁注:如果您想最小化闪烁并获得流畅的动画,请在启动并运行基本动画后查看双缓冲)

更新

您在更新函数中缺少 UpdateWindow 命令您的 OnPaint-Function 仅在您的应用程序收到 WM_PAINT 消息时调用,因此您需要发送这些消息。

UpdateWindow用于此目的

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); 
} 
于 2010-08-10T06:12:48.810 回答