2010-08-10 81 views
2

即时通讯尝试使用gdi创建球动画,但我无法让它工作。 我创建使用此c + + 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); 
    } 

在此先感谢 拉米

回答

5

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

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

现在窗口将每秒接收WM_TIMER消息(1​​000ms)。你应该处理它们:

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; 
} 
+0

嗯..它画一个圆,那就是它 你可以在这里看到完整的代码 http://pastesite.com/18049 – Ramilol 2010-08-10 08:10:54

+0

@Ramiz你应该在WM_CREATE消息,在WndProc上调用OnCreate: - 编辑:对不起忽略评论,我没有注意到你打电话给OnCreate。 – Tassos 2010-08-10 08:48:14

+0

现在好吧,它创建一个x = 1的圆,比创建x = 2的圆............它永远不会删除旧的圆 – Ramilol 2010-08-10 09:30:30

2

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

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

+0

我知道这将循环,直到永远......这是仅适用于测试..我想要do是这样做的,每次while循环圈循环位置变化,但它不会创建多个不同位置的圆。像这样我创建一个圆形和x值是1,而循环循环和比圆形x现在2,但它创建新的圆与x vlaue 2 – Ramilol 2010-08-10 04:50:23

+0

我不想超过一cirrece我只想要一个圆圈,将改变它的地方,就像我用x = 5px,y = 10创建的cicle一样。比它将循环比它将x更改为x = 6px更旧的cicler应该消失,并且应该创建x = 6的新循环 – Ramilol 2010-08-10 05:04:25

0

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

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

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

+0

我已经定义了这个画笔 hbrBackground \t =(HBRUSH)(COLOR_WINDOW + 1); 即使我删除更新它也不会帮助 – Ramilol 2010-08-10 06:25:40

+0

删除UpdateWindow将不会执行任何操作,因为您处于紧密的循环中,它显示的唯一原因是您调用UpdateWindow,它将直接调用您的消息处理程序。正如我所说的,使用WM_ERASEBKGND作为消息调用SendMessage(它也直接调用您的消息处理程序)。 InvalidateRect只发布消息,并期望您轮询消息队列以处理它们。 – 2010-08-10 06:53:38

+0

好吧有这么多WM_ERASEBKGND但我应该在里面它像这样 case WM_ERASEBKGND: //我应该在这里放什么 break; 我应该在循环 改变任何东西是完整的代码 http://pastesite.com/18047 – Ramilol 2010-08-10 07:13:42

0

我发现它展示了如何借鉴的东西MSDN上的例子in pure win32.

你不应该叫失效或Updatewindow在WM_PAINT,作为UpdateWindow发送一个新的WM_PAINT事件,和无效得到积累,直到下一个 WM_PAINT事件。

您应该将代码分成两个函数,一个用于执行移动,另一个用于在当前位置绘制圆。

你的动机 - 函数可以从任何地方(或许在定时器处理函数?)被调用,并应与

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

末端,以纪念为redrawal您的客户区,并通知你的窗口重绘自身。

Your Draw() - 函数应该读取使用移动器功能设置的位置,并且只需在此位置绘制一个圆。

(旁注:如果你希望尽量减少闪烁并获得流畅的动画,看看双缓冲一旦你得到了基本的动画和跑步)

UPDATE

你失踪更新函数中的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); 
} 
+0

确定 我greated一个新的功能 无效更新(HDC HDC,HWND HWND) { \t SF ++; FillRect(hdc,rect,(HBRUSH)(COLOR_WINDOW + 1)); \t InvalidateRect(hWnd,NULL,TRUE); (HDC hdc) 图形图形(hdc);图形图形(hdc);图形图形(hdc);图形图形 钢笔(颜色(255,0,0,255)); 图形。DrawEllipse(&pen,sf,0,10,10); } 这里是while循环 \t \t而(SD == 1) \t \t { \t \t \t的OnPaint(HDC); \t \t \t update(hdc,hWnd); \t \t} 现在我得到这个 它创造了一个圆圈,那就是它 任何想法? – Ramilol 2010-08-10 06:33:14