Invalidate()详解

本文深入探讨了Invalidate与WM_PAINT消息在Windows程序设计中的交互作用,解释了Invalidate如何标记需要重绘的区域,并在合适时机触发WM_PAINT消息实现重绘。同时,介绍了UpdateWindow和RedrawWindow函数如何优化重绘过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Invalidate() 很好的文章【转】

InvalidateRect只是增加重绘区域,在下次WM_PAINT的时候才生效

InvalidateRect函数中的参数TRUE表示系统会在你画之前用背景色将所选区域覆盖一次,默认背景色为白色,可以通过设置BRUSH来改变背景色。

Invalidate()之后:
...OnPaint()->OnPrepareDC()->OnDraw()
所以只是刷新在OnPaint()和OnDraw()函数中的绘图语句。其它地方没有影响。

Invalidate标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。类似于PostMessage(WM_PAINT),需要处理到WM_PAINT消息时才真正重绘。以为您Invalidate之后还有其他的语句正在执行,程序没有机会去处理WM_PAINT消息,但当函数执行完毕后,消息处理才得以进行。

Invalidate只是放一个WM_PAINT消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出WM_PAINT,才执行PAINT,所以不管Invalidate放哪里,都是最后的。

InvalidateRect(hWnd,&rect,TRUE);向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制,
rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,使背景重绘,当然在客户区域重绘之前。
UpdateWindow只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT

如果希望立即刷新无效区域,可以在调用InvalidateRect之后调用UpdateWindow,如果客户区的任一部分无效,则UpdateWindow将导致Windows用WM_PAINT消息调用窗口过程(如果整个客户区有效,则不调用窗口过程)。这一WM_PAINT消息不进入消息队列,直接由WINDOWS调用窗口过程。窗口过程完成刷新以后立刻退出,WINDOWS将控制返回给程序中UpdateWindow调用之后的语句。(windows程序设计第5版 P98)

UpdateData()顺便说下,这个函数不是刷新界面用的。
UpdateData();参数为FALSE时,将界面上控件绑定的变量的数据导到控件内,参数为TRUE时,导入方向则相反

 

附:Invalidate 与WM_PAINT之间的关系

系统会在多个不同的时机发送WM_PAINT消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时,等等,这些动作都是由系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;大多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,这一般是通过InvalidateRect和 InvalidateRgn函数来完成的。InvalidateRect和InvalidateRgn把指定的区域加到窗口的Update Region中,当应用的消息队列没有其他消息时,如果窗口的Update Region不为空时,系统就会自动产生WM_PAINT消息。

系统为什么不在调用Invalidate时发送WM_PAINT消息呢?又为什么非要等应用消息队列为空时才发送WM_PAINT消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后做,这样有利于提高绘制的效率:在两个WM_PAINT消息之间多个Invalidate调用使之失效的区域就会被累加起来,然后在一个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是否为空等

 

转自:http://www.cppblog.com/Raycruiser/articles/44193.html

### Dify离线安装与配置 #### 准备工作 为了在 Linux 环境下进行 Dify 平台的离线安装,需先准备好所需的依赖环境以及下载好所有必要的资源文件。这通常意味着要提前在一个有网络连接的环境中准备这些资源。 #### 下载所需镜像和组件 确保已经获取到最新的 Docker 镜像以及其他可能需要的外部库或插件。对于 Dify 来说,这意味着从官方渠道或者其他可信源下载适用于目标系统的版本[^1]。 #### 设置本地仓库 如果计划完全断开互联网来进行部署,则还需要设置私有的 Docker Registry 或者其他形式的存储来保存之前下载好的镜像文件。这样可以在后续操作中直接拉取而不必联网查找。 #### 修改配置文件 编辑 `docker-compose.yml` 文件或其他相关配置文档以适应新的运行条件。特别是要注意调整服务之间的内部通信方式,比如更改默认使用的 IP 地址为宿主机的实际地址;同时也要确认所有的路径指向都是正确的,并且能够被容器正常读写访问。 #### 启动服务 完成上述准备工作之后就可以利用命令行工具启动整个项目了: ```bash sudo docker-compose up -d ``` 这条指令会依据定义的服务列表依次创建并开启各个子模块,在此期间应该密切监视日志输出以便及时发现潜在错误信息。 #### 测试连通性 最后一步是要验证新搭建起来的应用能否按照预期那样运作良好。可以通过浏览器打开对应的 URL 进入管理界面查看状态页面,也可以借助 curl 命令模拟请求测试 API 功能是否可用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值