c++ GDI 动画不工作

发布于 2024-09-14 03:40:27 字数 516 浏览 11 评论 0原文

我正在尝试使用 gdi 创建球动画,但我无法让它工作。 我用这支钢笔创建了一个球

   Graphics graphics(hdc);

(Color(255, 0, 0, 255)); Graphics.DrawEllipse(&pen, sf , 0, 10, 10); 我有 while 循环,它循环并向 sf 值加 1 ,基本上像这样 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);
    }

提前致谢 拉米

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

王权女流氓 2024-09-21 03:40:27

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

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

现在窗口每秒(1000ms)就会收到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;
}

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;
}
神爱温柔 2024-09-21 03:40:27

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

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

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.

清风不识月 2024-09-21 03:40:27

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

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

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

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.

两相知 2024-09-21 03:40:27

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

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

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

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

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

In order to mark your client Area for redrawal and notification your window to redraw myself 结尾。

您的 Draw() 函数应该读取使用移动器函数设置的位置,然后围绕该位置绘制一个圆圈。

(旁注:如果您想最大程度地减少闪烁并获得流畅的动画,请在启动并运行基本动画后查看双缓冲

更新

您错过了 UpdateWindow更新功能中的命令
仅当应用程序收到 WM_PAINT 消息时才会调用 OnPaint 函数,因此您需要发送这些消息。

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); 
} 

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); 
} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文