WM_PAINT消息ValidateRect

来源:百度知道 编辑:UC知道 时间:2024/05/30 05:25:27
当窗口出现无效区域的时候系统会发送WM_PAINT消息通知用户程序重绘
我在WM_PAINT消息中不做任何处理,让系统不停的发送WM_PAINT消息。

这时用其他窗口将该窗口内的按钮给覆盖掉,按钮就被擦除掉了。
然后在WM_PAINT消息中处理ValidateRect(m_hWnd,NULL);更新整个窗口为有效,这时在用其他窗口将该窗口内的按钮给覆盖掉,按钮并没有被擦除。
我想问下,按钮既然能显示在屏幕上,就证明也是画上去的,那么是由谁来
画这个按钮呢,WM_PAINT消息处理了ValidateRect()它只是负责将整个更新区域变得有效,并不负责画按钮呀

每个窗口(HWND)实例,在windows操作系统中,都有个上下文记录区,其中记录着当前窗口的无效区域数据。系统内核利用空闲时间检查所有窗口的无效区,如果非空,就产生一个WM_PAINT发送给此线程再转发到当前窗口来处理。
当然此时,此窗口的无效区域还是存在的,通过在WM_PAINT中执行BeginPaint,就将此无效区域清空(使用ValidateRect一样效果),在执行具体的绘制操作。(这些执行都在窗口的Default中执行了,MS不给你看具体的过程,所以在MFC的系统代码中看不到。)。如果不将无效区域清空,系统将周而复始的产生WM_PAINT消息,导致OnIdle不能被执行,且当前程序CPU占用差不多100%。(由于是空闲时间处理,所以对话框的其他消息处理没被阻塞,可以按按钮等操作)。
——所以你的第一种情况就是这个。
如果使用了ValideRect,那么就阻滞了wm_paint消息的不断产生,CPU占用会是0.
1.如果第一种情况下,拖动窗口,将被全部重新绘制,因为拖动的操作调用了RedrawWindow函数,此函数不光产生整个窗口的 Invalide调用,同时接下来还直接执行窗口的绘制操作(读取窗口的无效区,如果不屏蔽CDialog::OnPaint,就在OnPaint里面绘制了)。所以你的第二个情况执行ValideRect后,拖动操作,也不能重新绘制整个窗口了。
2.如果是被另外一个对话框覆盖,那个对话框将会向其下的窗口(默认的窗口Z轴顺序)发生设置无效区域的指令——具体生成无效区域的操作是在内核执行的。接下来的事情那个窗口就不管了。这里有个疑点:如果第二个窗口覆盖在当前窗口上,并且拖动,就会导致当前窗口被重绘制;而在没有ValidateRect时候,又不重绘,我怀疑这都是MoveWindow函数的执行机理造成的.
3.关于子窗口重绘(按钮重绘制),首先是判断父窗口有无效区,如果此无效区域内有子窗口,那此也设置此子窗口的无效区,下一次系统空闲就产生此子窗口的WM_PAINT消息,那么线程就泵出这个消息,调用子窗口自绘(绘制过程被MS封装)。这样也就自然产生了,从Z轴最低到最高的绘制顺序。

我是这样想的,ValidateRect使一个区域有效的时候是对区域里所有元素发送一对WM