1、OnPaint()函数是窗口重绘消息WM_PAINT的响应函数,当窗口重绘时会产生WM_ERASEBKGND消息和WM_PAINT消息,而且WM_ERASEBKGND会先于WM_PAINT产生,所以窗口重绘时,会先调用OnEraseBkGnd()擦除窗口,再调用OnPaint绘制窗口。如果你在OnPaint()里自绘了窗口,在窗口重绘的时候会发现窗口会闪一下,原因就是OnEraseBkGnd()函数中使用默认的画刷(一般为灰白色)来擦除窗口。解决这个问题有三个方法:

① 在OnEraseBkGnd()中实现绘制窗口的工作,注释掉OnEraseBkGnd()中擦除窗口的代码。

② 在OnPaint中实现绘制窗口的工作,注释掉OnEraseBkGnd()中擦除窗口的代码。

③ 在OnPaint中实现绘制窗口的工作,在创建窗口时设置背景画刷为空。

由于WM_PAINT消息需要等消息队列中的其它消息发送完后才能被处理,而在OnEraseBkGnd()中实现绘制窗口的工作的话,窗口元件有任何小变动都会调用OnEraseBkGnd(),OnPaint()在调用之前OnEraseBkGnd()可能已经调用了好几次,所以最好的方法是在OnEraseBkGnd()中只做简单不耗时的绘图工作,而复杂的绘制工作在OnPaint()中进行。

窗口重绘的时候并不一定会产生WM_ERASEBKGND消息,在调用Invalidate()和InvalidateRect()重绘窗口的时候可以通过参数bErase来指定是否产生WM_ERASEBKGND消息来擦除背景。

2、Invalidate()使整个客户区无效,客户区无效则会发送WM_PAINT消息对整个客户区进行重绘。调用Invalidate后可能不会立即重绘窗口,因为它要等到消息队列中的其它消息发送完后才能被处理。函数原型:

void Invalidate( BOOL bErase = TRUE);

其参数决定了是否要在WM_PAINT消息前发送WM_ERASEBKGND消息来擦除窗口背景,bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。

InvalidateRect()同Invalidate功能相同,但可以指定重绘的区域,函数原型:

BOOL InvalidateRect(const RECT *lpRect, BOOL bErase = TRUE);

UpdateWindow()会通过发送WM_PAINT消息对客户区进行重绘,如果没有可绘制的区域则不进行重绘。如果有可绘制的区域的话UpdateWindow()会立即重绘窗口,它发送的WM_PAINT消息不会进入消息队列而是直接调用窗口过程进行重绘。所以一般是调用Invalidate()后接着调用UpdateWindow()来达到窗口立即重绘的目的。函数原型: 
void UpdateWindow();
RedrawWindow()也是用来使窗口重绘的,它更加灵活,其flags参数可以是下面值的组合:RDW_INVALIDATE使区域无效,RDW_UPDATENOW立即重绘窗口,RDW_ERASE重绘区域内的背景将被擦除。所以RedrawWindow()可以实现
InvalidateRect + UpdateWindow功能之和。函数原型:
BOOL RedrawWindow(
LPCRECT lpRectUpdate = NULL,
CRgn* prgnUpdate = NULL,
UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE
);  InvalidateRgn()函数通过添加一个区域到一个窗口的更新区域中来使指定矩形的客户区域无效;这个无效的区域和所有更新区域中的其他区域将被标记用来在下一个WM_PAINT消息发生的时候描绘。 
 参考出处:http://www.cnblogs.com/BeyondTechnology/archive/2011/03/25/1995942.html 
3、GetUpdateRect(LPRECT lpRect, BOOL bErase = FALSE)可以获得需要更新的区域,在调用了InvalidRect后可以用这个函数来获得无效区域,但如果调用了BeginPaint则获得的区域为空,所以在OnPaint中调用GetUpdateRect()无效。
GetClientRect()得到的RECT以所在窗口左上角为原点,且不包括标题栏,外框。
GetWindowRect()得到的RECT以屏幕左上角为原点,获得整个窗口的矩形。
ScreenToClient()就是把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标。
ClientToScreen()就是把客户区坐标系下的RECT坐标转换为屏幕坐标系下的RECT坐标。

WM_PAINT和WM_ERASEBKGND消息的更多相关文章

  1. 深度分析WM_PAINT和WM_ERASEBKGND消息

    做windows开发这么久了,一直以来对WM_PAINT和WM_ERASEBKGND消息总是感觉理解的不准确,每次要自绘一个窗口都因为知其然不知其所以然,偶然发现一篇文章,详细透彻地分了这个两个消息的 ...

  2. WM_PAINT 与 WM_ERASEBKGND消息的深入分析

    当WM_PAINT消息不是由函数InvalidateRect产生的时(即通过最大话,最小化,移动,下拉菜单等),系统会先产生连续产生若干个WM_ERASEBKGND消息,紧接着在产生WM_PAINT消 ...

  3. Invalidate(TRUE)与Invalidate(FALSE)区别(前者会发送WM_ERASEBKGND消息全部刷新,然后使用WM_PAINT消息绘制,而后者只发送WM_PAINT消息)

    使用Invalidate(TRUE)函数时,它会向消息队列中添加了WM_ERASEBKGND和WM_PAINT两个消息. 使用Invalidate(FALSE)函数时,它只会向消息队列中添加了WM_P ...

  4. 窗口绘制有关的消息整理 WM_PAINT, WM_NCPAINT, WM_ERASEBKGND

    WM_PAINTWM_PAINT是Windows窗口系统中一条重要的消息,应用程序通过处理该消息实现在窗口上的绘制工作. WM_NCPAINT当窗口客户区以外的部分(如窗口标题栏.菜单栏等)需要需要重 ...

  5. WM_PAINT与WM_ERASEBKGND(用户操作和API这两种情况产生消息的顺序有所不同)

    1)当WM_PAINT不是由InvalidateRect产生时,即由最大化,最小化等产生时,或者移动产生(移动有时只会产生WM_ERASEBKGND消息)系统先发送WM_ERASEBKGND消息,再发 ...

  6. 终于懂了:WM_PAINT 与 WM_ERASEBKGND(三种情况:用户操作,UpdateWindow,InvalidateRect产生的效果并不相同),并且用Delphi代码验证 good

    一直对这两个消息的关系不是太了解,借重新深刻学习windows编程的机会研究一番. 1)当窗口从无效变为有效时,比方将部分覆盖的窗口恢复时会重绘窗口时:程序首先会通过发送其他消息调用DefWindow ...

  7. WM_PAINT产生原因有2种(用户操作和API)——WM_PAINT和WM_ERASEBKGND产生时的先后顺序不一定(四段讨论)

    1. 当WM_PAINT不是由InvalidateRect产生时,即由最大化,最小化等产生时,或者移动产生(移动有时只会产生WM_ERASEBKGND消息)系统先发送WM_ERASEBKGND消息,再 ...

  8. 关于WM_ERASEBKGND和WM_PAINT的深刻理解

    一直以来,对于WM_PAINT和WM_ERASEBKGND消息不是很清楚,从书上和网上找了很多资料,大体上有以下几点说法:1>WM_PAINT先产生,WM_ERASEBKGND后产生 2.WM_ ...

  9. WM_PAINT消息小结

    WM_PAINT是Windows窗口系统中一条重要的消息,应用程序通过处理该消息实现在窗口上的绘制工作. 1. 系统何时发送WM_PAINT消息? 系统会在多个不同的时机发送WM_PAINT消息:当第 ...

随机推荐

  1. 测试用户体验相关——UI设计准则及方法

    之前跟我们uxc同学聊过一些,记录下来,方便在工作中不断渗透深入和理解,能够逐渐养成比较好的审美和对UI交互问题的敏锐的觉察力. 以问题为导向来吧... 第一个问题:一个menu中的图标一定要风格一致 ...

  2. java实现rabbitMQ延时队列详解以及spring-rabbit整合教程

    在实际的业务中我们会遇见生产者产生的消息,不立即消费,而是延时一段时间在消费.RabbitMQ本身没有直接支持延迟队列功能,但是我们可以根据其特性Per-Queue Message TTL和 Dead ...

  3. 使用IntelliJ IDEA 搭建 spring mvc开发环境

    填好GroupId.ArtifactId,一路Next创建工程,在main 目录创建 java文件夹并转换为Sources Root,创建好工程目录结构如下: 配置工程 配置 pom.xml,引入相关 ...

  4. 开机进入boot menu和application menu,无法开机

        1.开机点击F1进入到bios界面 2.进入Security—Secure Boot—Disabled 如果不修改Secure boot选项为Disabled,在光驱引导时可能会出现报错 3. ...

  5. 浅谈XListView的使用

    XListView是github上的开源第三方控件 内部封装好的一个类XListView 其内部包含XListViewFooter XListViewHeader 两个自定义类(控件)如此实现上拉加载 ...

  6. centos7下keepalived1.3.4安装与使用

    keepalived是集群管理中保证集群高可用的一个服务软件,其功能类似于heartbeat,用来防止单点故障. 一.下载keepalived http://www.keepalived.org/ 如 ...

  7. 解决JFinal多文件上传时只获取到第一个文件名

    我的思路: 用户生成时随即生成一串随机字符作为该用户的文件上传目录,并保存该字符串到用户的某一字段.需要显示上传的附件时,遍历这个文件夹.上传时可把文件名设置为上传时间. 1.生成上传路径 可写在注册 ...

  8. IE7下面踩得坑

    bug1.position:fixed:z-index:99; 出现了z-index:2的层级跑到他上面了, 为什么?会出现这问题??? 检查: 1你的固定定位的容器是不是被其他容器包裹,你包裹得容器 ...

  9. 数据库以及pymysql

    1.pymysql模块操作数据库详细 import pymysql # user = 'chun' # psw = conn = pymysql.connect(host='localhost',us ...

  10. mysql 5.17 的update失败问题

    在使用workbench的时候,写入update语句,会很提现失败,原因是安全模式; 可能是workbench在数据库更新的时候是有限制的,防止错误哦l 更改方法也很简单; Edit - Profer ...