关于win32 sdk 窗口重画的问题
各位大师好。刚学win32api有点疑问;就是::GetClientRect(hwnd,&rect);::InvalidateRect(hwnd,&rect,true);...
各位大师好。刚学win32 api有点疑问;
就是
::GetClientRect(hwnd,&rect);
::InvalidateRect(hwnd,&rect,true);
这两句话不是会给程序发送WM_PAINT消息吗,我知道这个PAINT是不会立即执行的,因为有优先级。
所以在后面要强制WM_PAINT的话就加了一句:
::UpdateWindow(hwnd);
这句话就可以直接立即重画窗口了。
但是我的疑问是
为什么直接::UpdateWindow(hwnd)就不能达到窗口重画的效果呢?
msdn上说UpdateWindow的执行条件是客户区不为空,但是我的客户区明明是有东西呀..(至少有几条线或者图形),只调用UpdateWindow的时候为什么就不重画呢?
偏偏要加上:
::GetClientRect(hwnd,&rect);
::InvalidateRect(hwnd,&rect,true); 展开
就是
::GetClientRect(hwnd,&rect);
::InvalidateRect(hwnd,&rect,true);
这两句话不是会给程序发送WM_PAINT消息吗,我知道这个PAINT是不会立即执行的,因为有优先级。
所以在后面要强制WM_PAINT的话就加了一句:
::UpdateWindow(hwnd);
这句话就可以直接立即重画窗口了。
但是我的疑问是
为什么直接::UpdateWindow(hwnd)就不能达到窗口重画的效果呢?
msdn上说UpdateWindow的执行条件是客户区不为空,但是我的客户区明明是有东西呀..(至少有几条线或者图形),只调用UpdateWindow的时候为什么就不重画呢?
偏偏要加上:
::GetClientRect(hwnd,&rect);
::InvalidateRect(hwnd,&rect,true); 展开
4个回答
展开全部
你理解错了msdn的话了,WM_PAINT会发送的条件不是“客户去不为空”,而是失效区域不为空!
这个区域就是你标记的或者是Winodws标记为失效的区域,失效的意思是这个区域内的内容已经不正确了,取消重新绘制。
你如何设置失效区域:调用InvalidateRect,另外,如果你要设置整个客户区都失效:
InvalidateRect(hWnd, NULL, TRUE); 不必调用GetClientRect。
何时Windows会自动设置失效区域?比如,你的窗口被其他窗口遮挡,如果此时用户把你的程序激活到前台,Windows自动设置刚才遮挡的部分为失效区域。以便在随后的WM_PAINT的时候这个区域会擦除之前的内容(之前的内容其实是另一个窗口的内容),画上自己窗口的内容。如果你的程序从最小化还原,整个客户去都会被Windows自动设置为失效区域。不过,鼠标滑过窗孔不会导致Windows自动设置失效区域,鼠标滑过在Windows中有特别处理,不需要程序员自己来操心。
只有当这个失效区域不为空的时候WM_PAINT才会被发送!而函数UpdateWindow的实质就是发送WM_PAINT,因而你如果不指定InvalidateRect则通过UpdateWindow不会更新窗口(确切的说是不一定会更新窗口,取决于Windows是否为你自动设置了失效区域)。
另外,Windows出于程序运行效率的考虑,在画图的时候,只有在失效区域的内容会被更新到屏幕上,如果你画了一个物体,在失效区域以外,那么这些语句直接会被Windows忽略。所以,正确设置失效区域是相当重要的,比如你写一个程序,有一个正方形,一个圆形,如果你这时候改变正方形的颜色,只要把这个正方形设置为失效区域即可。虽然你在响应WM_PAINT的时候同时也画了这个圆形,但是圆形由于不再失效区域,这些代码对Windows来说就相当于走了个过场,实际上没有操作显存。简单的程序,你偷懒直接设置全部客户去失效是可行的,但是如果你的WM_PAINT响应非常复杂,那么你不合理设置失效区域会导致程序界面闪烁,响应缓慢等问题。
这个区域就是你标记的或者是Winodws标记为失效的区域,失效的意思是这个区域内的内容已经不正确了,取消重新绘制。
你如何设置失效区域:调用InvalidateRect,另外,如果你要设置整个客户区都失效:
InvalidateRect(hWnd, NULL, TRUE); 不必调用GetClientRect。
何时Windows会自动设置失效区域?比如,你的窗口被其他窗口遮挡,如果此时用户把你的程序激活到前台,Windows自动设置刚才遮挡的部分为失效区域。以便在随后的WM_PAINT的时候这个区域会擦除之前的内容(之前的内容其实是另一个窗口的内容),画上自己窗口的内容。如果你的程序从最小化还原,整个客户去都会被Windows自动设置为失效区域。不过,鼠标滑过窗孔不会导致Windows自动设置失效区域,鼠标滑过在Windows中有特别处理,不需要程序员自己来操心。
只有当这个失效区域不为空的时候WM_PAINT才会被发送!而函数UpdateWindow的实质就是发送WM_PAINT,因而你如果不指定InvalidateRect则通过UpdateWindow不会更新窗口(确切的说是不一定会更新窗口,取决于Windows是否为你自动设置了失效区域)。
另外,Windows出于程序运行效率的考虑,在画图的时候,只有在失效区域的内容会被更新到屏幕上,如果你画了一个物体,在失效区域以外,那么这些语句直接会被Windows忽略。所以,正确设置失效区域是相当重要的,比如你写一个程序,有一个正方形,一个圆形,如果你这时候改变正方形的颜色,只要把这个正方形设置为失效区域即可。虽然你在响应WM_PAINT的时候同时也画了这个圆形,但是圆形由于不再失效区域,这些代码对Windows来说就相当于走了个过场,实际上没有操作显存。简单的程序,你偷懒直接设置全部客户去失效是可行的,但是如果你的WM_PAINT响应非常复杂,那么你不合理设置失效区域会导致程序界面闪烁,响应缓慢等问题。
追问
回答的很专业,邮箱:daoluanxiaozi@126.com,希望能跟你一起学习。(收到邮件后采纳)
展开全部
UpdateWindow在窗口有变化时重绘,无变化就没必要重绘了。就跟你在word中点完保存不做任何修改再点保存没什么变化一样。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
1:设置无效区
InvalidateRect
2:立即刷新
UpdateWindow();
如果只有2的话并没有设置过无效区域,结合你自己的理解再想想
InvalidateRect
2:立即刷新
UpdateWindow();
如果只有2的话并没有设置过无效区域,结合你自己的理解再想想
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
UpdateWIndow执行的条件是客户区不为空。
这里的客户区指的不是你那儿有什么东西,
而是通过GetClientRect取得的客户区,
然后通过InvalidateRect使得取得的客户区失效,
这样等到响应WM_PAINT时,才会重绘。
重绘是因为需要重绘,例如你移动了窗口,或者你的窗口被别的窗口挡着了,
如果窗口好好的在哪儿,什么都没有变,为什么要重绘
这里的客户区指的不是你那儿有什么东西,
而是通过GetClientRect取得的客户区,
然后通过InvalidateRect使得取得的客户区失效,
这样等到响应WM_PAINT时,才会重绘。
重绘是因为需要重绘,例如你移动了窗口,或者你的窗口被别的窗口挡着了,
如果窗口好好的在哪儿,什么都没有变,为什么要重绘
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询