窗口刷新问题(WM_PAINT)

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

在Windows API编程中,WM_PAINT是Windows窗口的一个重要消息,应用程序就是通过响应这个消息来完成窗口的绘制。
  The WM_PAINT message is generated by the system and should not be sent by an application.The system sends this message when there are no other messages in the application's message queue
  注意:WM_PAINT消息是由系统产生,非要等应用程序的消息队列为空时才发送WM_PAINT消息。
  其实系统会在很多的不同的机制下发送WM_PAINT消息,比如调用UpdateWindow函数,第一次创建窗口,改变了窗口的大小,最大化,最小化等等。这些动作的产生都是有系统来控制的,应用程序只是接收消息,并处理消息。

当Window检测到窗口被覆盖的地方需要恢复的时候,它会向用户程序发送一个WM_PAINT消息,消息中包括了需要恢复的区域,然后由用户程序来决定如何恢复被覆盖的内容。窗口过程收到WM_PAINT消息后,并不代表整个客户区都需要被刷新,有可能客户区被覆盖的区域只有一小块,这个区域叫做“无效区域”,程序只需要更新这个区域。与WM_TIMER消息类似,WM_PAINT消息也是一个低级别的消息,虽然它不会像WM_TIMER消息一样被丢弃,但Windows总是在消息循环空的时候才把WM_PAINT放入其中,实际上,Windows为每个窗口维护一个“绘图信息结构”,无效区域的坐标就在其中,每当消息循环空的时候,如果Windows发现存在一个无效区域,就会放入一个WM_PAINT消息。

无效区域的坐标并不附带在WM_PAINT消息的参数中,在程序中有其他方法可以获取,WM_PAINT消息只是通知程序有个区域需要更新而已,所以Windows也不会同时将两条WM_PAINT消息放入消息循环中,当Windows要放入一条WM_PAINT消息的时候,如果发现已经存在一个无效区域了,那么它只需要把新旧两个无效区域合并计算出一个无效区域就可以了,消息循环中还是只需要一条WM_PAINT消息。
  如果程序在WM_PAINT消息中对客户区刷新完毕后工作并没有结束,如果不使无效区域变得有效,Windows会在下一轮消息循环中继续放入一个WM_PAINT消息,而不是根据程序是否执行了刷新过程,所以程序也可以不去刷新客户区,而是简单地用一个ValidateRect函数直接让客户区变得有效,以此来“欺骗”Windows已经没有无效区域了,当Windows检查“绘图信息结构”的时候发现没有了无效区域,也就不会继续发送WM_PAINT消息了。

系统何时发送WM_PAINT消息?
  系统会在多个不同的时机发送WM_PAINT消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时,等等,这些动作都是由 系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;大多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,这一般是通过InvalidateRect和 InvalidateRgn函数来完成的。InvalidateRect和InvalidateRgn把指定的区域加到窗口的Update Region中,当应用的消息队列没有其他消息时,如果窗口的Update Region不为空时,系统就会自动产生WM_PAINT消息。
  系统为什么不在调用Invalidate时发送WM_PAINT消息呢?又为什么非要等应用消息队列为空时才发送WM_PAINT消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽 可能地推后做。不过这样也有利于提高绘制的效率:两个WM_PAINT消息之间通过InvalidateRect和InvaliateRgn使之失效的区域就会被累加起来,然后在一个WM_PAINT消息中一次得到 更新,不仅能避免多次重复地更新同一区域,也优化了应用的更新操作。像这种通过InvalidateRect和InvalidateRgn来使窗口区域无效,依赖于系统在合适的时机发送WM_PAINT消息的机 制实际上是一种异步工作方式,也就是说,在无效化窗口区域和发送WM_PAINT消息之间是有延迟的;有时候这种延迟并不是我们希望的,这时我们当然可以在无效化窗口区域后利用SendMessage 发送一条WM_PAINT消息来强制立即重画,但不如使用Windows GDI为我们提供的更方便和强大的函数:UpdateWindow和RedrawWindow。UpdateWindow会检查窗口的Update Region,当其不为空时才发送WM_PAINT消息;RedrawWindow则给我们更多的控制:是否重画非客户区和背景,是否总是发送WM_PAINT消息而不管Update Region是否为空等。

c++窗口立即新重绘 当窗体需要更新内容或是重绘外观背景的时候,应用程序通常会发送一条WM_PAINT消息,通知窗体进行重新绘制。 阅读详情

相关推荐

关于WM_ERASEBKGND和WM_PAINT的深刻理解

一直以来,对于WM_PAINTWM_ERASEBKGND消息是很清楚,从书上和网上找了很多资料,大体上有以下几点说法: 1>WM_PAINT先产生,WM_ERASEBKGND后产生 2.WM_PAINT产生后,在调用BeginPaint时 hdc = BeginPain

sdeeds的专栏 2万+

WM_PAINT详解和WM_ERASEBKGND

WM_PAINT简介: WM_PAINT消息在Windows程序设计中是很重要的。当窗口显示区域的一部分显示内容或者全部变为“无效”,以致于必须“更新画面”时,将由这个消息通知程序。 WM_PAINT产生的时机: 1. 系统产生 其实系统会在很多的同的机制下发送WM_PAINT消息,比如调用UpdateWindow函数,第一次创建窗口,改变了窗口的大小,最大化,最小化等等。这些动作...

Barry的博客 7831

C++程序编程中的WM_PAINTWM_ERASEBKGND、InvalidateRect、UpdateWindow、BeginPaint和EndPaint详解

Windows编程中的WM_PAINTWM_ERASEBKGND、InvalidateRect、UpdateWindow、BeginPaint和EndPaint详解。

dvlinker的技术专栏 9181

窗口新问题WM_PAINT、BeginPaint、EndPaint的说明)

在某些情况下,显示区域的一部分被临时覆盖,Windows试图保存一个显示区域,并在以后恢复它,但这一定能成功。在以下情况下,Windows可能发送WM_PAINT消息:   Windows擦除覆盖了部分窗口的对话框或消息框。   菜单下拉出来,然后被释放。   显示工具提示消息。   在某些情况下,Windows总是保存它所覆盖的显示区域,然后恢复它。这些情况是:   鼠标光标穿越显示

renwotao2009的专栏 1164

窗口新问题WM_PAINT、BeginPaint、EndPaint的说明

在某些情况下,显示区域的一部分被临时覆盖,Windows试图保存一个显示区域,并在以后恢复它,但这一定能成功。在以下情况下,Windows可能发送WM_PAINT消息:  Windows擦除覆盖了部分窗口的对话框或消息框。  菜单下拉出来,然后被释放。  显示工具提示消息。  在某些情况下,Windows总是保存它所覆盖的显示区域,然后恢复它。这些情况是:  鼠标光标穿越显示区域。  图标拖过显示区域。  处理WM_PAINT消息要求程序写作者改变自己向显示器输出的思维方式。程序应该组织成可以保留绘制显示

blood008的专栏 730

记一个界面新相关的Bug

今天遇到一个比较有意思的bug, 这里简单记录下。 Bug的症状是通过拖拉边框把我们客户端主窗口拖小之后,再最大化,会发现窗口显示有问题, 看起来像是新问题, 有些地方显示的对了。 这里要说明的是我这里的主窗口是非常复杂的窗口, 里面集成了很多组件(cpmponent),有很多层的子窗口。 这个问题只有在特定条件下才会发生, 正常情况下都是好的。 遇到这种问题,我们怎么处理?...

weixin_33748818的博客 1342

解决SDK中贴图 闪烁和调用 Invalidate之后 无法继续贴图的问题

还是 在做俄罗斯方框的过程中遇到的问题 1.调用了InvalidateRect之后 知否发现能继续贴图了 。。但是只要窗体一被遮住就没问题 解决 : 这是应为 InvalidateRect这个函数会使指定的矩形区域编程无效区域 会导致区域重绘 消息从 WM_ERASEBKGND -> WM_PAINT ...

weixin_30284355的博客 83

WM_PAINT 是如何触发的

WM_PAINT消息在Windows操作系统中是一个非常重要的消息,它用于通知窗口需要重绘其客户区。在处理WM_PAINT消息时,窗口程序通常会在其窗口处理函数中添加相应的消息处理逻辑。这通常涉及使用BeginPaint和EndPaint函数来设置和结束绘制操作,并在它们之间执行实际的绘制工作。总结来说,WM_PAINT消息是Windows操作系统用于通知窗口程序其客户区需要重绘的一种机制。它可以在多种场景下被触发,以确保窗口内容的正确显示。

lijian2017的博客 1552

父子窗口WM_PAINT

WM_PAINT(父子窗口) 窗口句柄(HWND)都是由操作系统内核管理的,系统内部有一个z-order序列,记录着当前从屏幕底部(假象的从屏幕到眼睛的方向),到屏幕最高层的一个窗口句柄的排序,这个排序关注父窗口还是子窗口。 当任意一个窗口接受到WM_PAINT消息产生重绘,更新区绘制完成以后,就搜索它的前面的一个窗口,如果此窗口的范围和更新区有交集,就向这个发送wm_paint消息,

zhqhaiqing的专栏 1901
上一篇: 小题
下一篇: 关于afx_msg
imgodor
博客等级 码龄17年 15粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值