WM_PAINT(父子窗口间)
窗口句柄(HWND)都是由操作系统内核管理的,系统内部有一个z-order序列,记录着当前从屏幕底部(假象的从屏幕到眼睛的方向),到屏幕最高层的一个窗口句柄的排序,这个排序不关注父窗口还是子窗口。
当任意一个窗口接受到WM_PAINT消息产生重绘,更新区绘制完成以后,就搜索它的前面的一个窗口,如果此窗口的范围和更新区有交集,就向这个发送wm_paint消息,周而复始,直到执行到顶层窗口。才算完成。
对于一个对话框(主窗口来说,设置了WS_CLIPCHILDREN样式时,其所有子窗口都在他的前面——也就是更靠近眼睛的位置),所以主窗口接受wm_paint绘制完成后,会引起更新区上所有子窗口的重绘(所有子窗口也是从底到外排序的)。
只要有更新区域的产生.
无所谓谁管,每个窗口都是对等的,都有自己的消息相应函数,只不过属性不同。
逻辑上可以这么理解,但其实,操作系统是按主窗口排序,然后一个主窗口的所有子窗口是等级的,它们再一个排序。所以逻辑上可以说,系统中所有窗口句柄都有个排序。
子窗口无效不会引起父窗口重绘,父窗口无效,如果父窗口(没有WS_CLIPCHILDREN属性)收到WM_PAINT,则所有子窗口都会在父窗口处理WM_PAINT之后收到WM_PAINT重绘消息,当然,如果父窗口带有属性WS_CLIPCHILDREN,则不会引起子窗口重绘
子窗口更新区域
子窗口是具有WS_CHILD或者WS_CHILDWINDOW样式的窗口。和一般窗口一样,子窗口通过WM_PAINT来绘图。子窗口也维护一个更新区域,应用程序和系统都可以通过设置该更新区域来产生WM_PAINT消息。
子窗口的更新和显示区域受到父窗口的影响,其他样式的窗口则不会。系统常常设置父窗口的更新区域的同时设置子窗口的更新区域,使父窗口收到WM_PAINT消息的同时子窗口也能收到WM_PAINT消息。系统把子窗口的位置限制在父窗口的client区域,超出这个区域就会被裁减掉。
无论何时,只要父窗口的更新区域包含了子窗口的一部分,系统就会为子窗口设置更新区域。此时,系统先向父窗口发送WM_PAINT消息,然后向子窗口发送消息让子窗口可以恢复被父窗口覆盖的内容。
但是如果只有子窗口设置了更新区域,系统不会给父窗口也设置。在无效化子窗口时,系统不会给父窗口发WM_PAINT(因为被覆盖住了,根本没有必要)。同样的,如果使被子窗口覆盖住的父窗口的部分无效化,系统也不会给父窗口发送WM_PAINT的。在这种情况下,无论子窗口还是父窗口都不会收到WM_PAINT消息。
应用程序如果设置了WS_CLIPCHILDREN这个样式的话,当父窗口的更新区域被设置的时候,子窗口的更新区域不会被设置。父窗口作用在子窗口下面的任何绘图全部被裁减掉。
子窗口的更新和可视区域也受到兄弟窗口的影响。如果两个窗口重叠,则两个窗口都会收到WM_PAINT消息。他们受到WM_PAINT消息的顺序与z-index相反,即最上面的(z-order最高)的收到WM_PAINT消息最晚。
应用程序可以设置WS_CLIPSIBLING来避免兄弟窗口的绘制重叠。设置了这个,高z-order的窗口部分就被下面的窗口裁减掉了。
父窗口先收到WM_PAINT,先绘制父窗口,然后再刷新子窗口
WS_CLIPCHILDREN是来设置父窗口的属性的,设置以后,父窗口刷新的时候不再自动去刷新子窗口的区域,需要你自己去刷新子控件区域
WS_CLIPCHILDREN
好,到此为止,应该说点有结论的话了。
(1)WS_CLIPCHILDREN样式主要是用于父窗口,也就是说当在父窗口绘制的时候,父窗口上还有一个子窗口,那么设置了这个样式的话,子窗口区域父窗口就不负责绘制。
(2)所有的overlapped和popup风格的窗口,都有WS_CLIPSIBLINGS 属性。也就是说这类风格的窗口,你是去不掉WS_CLIPSIBLINGS 属性的,不会在它重叠的兄弟窗口绘图;
(3)更进一步说明,WS_CLIPSIBLINGS只是用于子窗口(For use with the WS_CHILD style only.)
(4)WS_CLIPSIBLINGS实际上还需要和控件的叠放顺序(z order)配合使用,才能看出明显的效果。