Windows的窗口刷新机制相关

本文详细探讨了Windows窗口的刷新管理,包括父子窗口和兄弟窗口之间的刷新策略,以及OnEraseBkGnd与OnPaint的处理。重点讨论了WS_CLIPCHILDREN样式对窗口刷新的影响,以及如何避免闪烁问题。此外,还介绍了WM_PAINT消息、BeginPaint函数和重绘函数如InvalidateRect、UpdateWindow和RedrawWindow的使用方法。
摘要由CSDN通过智能技术生成

Windows的窗口刷新机制

1、Windows的窗口刷新管理

窗口句柄(HWND)都是由操作系统内核管理的,系统内部有一个z-order序列,记录着当前窗口从屏幕底部(假象的从屏幕到眼睛的方向),到屏幕最高层的一个窗口句柄的排序,这个排序不关注父窗口还是子窗口。

当任意一个窗口接收到WM_PAINT消息产生重绘,更新区域绘制完成以后,就搜索它的前面的一个窗口,如果此窗口的范围和更新区域有交集,就向这个窗口发送WM_PAINT消息,周而复始,直到执行到顶层窗口。才算完成。

1.1 父子窗口间的刷新管理

对于一个对话框(主窗口)来说,理论上其所有子窗口都在他的前面——也就是更靠近眼睛的位置),当主窗口接收WM_PAINT绘制完成后,会引起更新区域上所有子窗口的重绘(所有子窗口也是自底向上排序的)。

子窗口是具有WS_CHILD或者WS_CHILDWINDOW样式的窗口。和一般窗口一样,子窗口通过WM_PAINT来绘图。子窗口也维护一个更新区域,应用程序和系统都可以通过设置该更新区域无效来产生WM_PAINT消息。

子窗口的更新和显示区域受到父窗口的影响,其他样式的窗口则不会。系统常常设置父窗口的更新区域的同时设置子窗口的更新区域,使父窗口收到WM_PAINT消息的同时子窗口也能收到WM_PAINT消息。系统把子窗口的位置限制在父窗口的client区域,超出这个区域就会被裁减掉。

无论何时,只要父窗口的更新区域包含了子窗口的一部分,系统就会为子窗口设置更新区域。此时,系统先向父窗口发送WM_PAINT消息,然后向子窗口发送消息让子窗口可以恢复被父窗口覆盖的内容。

但是如果只有子窗口设置了更新区域,系统不会给父窗口也设置。在无效化子窗口时,系统不会给父窗口发WM_PAINT(因为被覆盖住了,根本没有必要)。同样的,如果使被子窗口覆盖住的父窗口的部分区域无效化,系统也不会给父窗口发送WM_PAINT的。在这种情况下,无论子窗口还是父窗口都不会收到WM_PAINT消息。

父子窗口间的刷新,还受父窗口是否设置了WS_CLIPCHILDREN样式影响。

父窗口如果设置了WS_CLIPCHILDREN这个样式的话,当父窗口的更新区域被设置的时候,子窗口的更新区域不会被设置。父窗口作用在子窗口下面的任何绘图全部被裁减掉。

因此,当父窗口无效且收到WM_PAINT消息时,如果没有设置WS_CLIPCHILDREN样式,则所有子窗口都会在父窗口处理WM_PAINT之后收到WM_PAINT重绘消息;如果父窗口带有WS_CLIPCHILDREN样式,则不会引起子窗口重绘。

1.2 兄弟窗口间的刷新管理

如果两个窗口重叠,则两个窗口都会收到WM_PAINT消息。他们收到WM_PAINT消息的顺序与z-index相反,即最上面的(z-order最高)的收到WM_PAINT消息最晚。

应用程序可以为窗口设置WS_CLIPSIBLING样式来避免兄弟窗口的绘制重叠。设置了这个,高z-order的窗口部分就会被上面的窗口裁减掉了,此部分被覆盖的区域就不会被刷新了。

结论

1)WS_CLIPCHILDREN样式主要是用于父窗口,也就是说当在父窗口绘制的时候,父窗口上还有一个子窗口,那么如果设置了这个样式的话,子窗口所在区域父窗口就不负责绘制;

2)所有的overlapped和popup风格的窗口,都有WS_CLIPSIBLINGS属性。也就是说这类风格的窗口,你是去不掉WS_CLIPSIBLINGS样式的,这样就是它不会在其与兄弟窗口重叠的区域绘图;

3)WS_CLIPSIBLINGS样式只适用于同级窗口,实际上还需要和控件的叠放顺序(z order)配合使用才能看出明显的效果。

2、OnEraseBkGnd与OnPaint

2.1 常见的问题

在OnEraseBkGnd中,如果你不调用原来缺省的OnEraseBkGnd只是重画背景则不会有闪烁。而在OnPaint里面,由于它隐含的调用了OnEraseBkGnd,而你又没有处理OnEraseBkGnd函数,这时就和窗口缺省的背景画刷相关了。缺省的OnEraseBkGnd操作使用窗口的缺省背景画刷刷新背景(一般情况下是白刷),而随后你又自己重画背景造成屏幕闪动。

然而OnEraseBkGnd不是每次都会被调用的。如果你调用Invalidate的时候参数为T

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值