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. 速卖通API开发步骤

    http://gw.api.alibaba.com/dev/doc/intl/sys_auth.htm?ns=aliexpress.open#concept 关键字段说明 1.appKey和appSe ...

  2. [剑指Offer]45-把数组排成最小的数

    题目链接 https://www.nowcoder.com/practice/8fecd3f8ba334add803bf2a06af1b993?tpId=13&tqId=11185&t ...

  3. HA状态下防火墙损坏处理

    问题描述: web登录防火墙管理地址,发现在 状态-系统信息 里集群成员只有一台原备机.到机房发现原主机只有power灯是亮着的,HA灯和status灯都不亮. 用笔记本直连防火墙的mgmt口不亮,c ...

  4. Mac git 终端使用

    终端有这个提示,这个按照命令 输入你的 git账号和邮箱就可以, 不然一直出这个提示 Your name and email address were configured automatically ...

  5. vue-router2

    六,导航钩子 导航钩子函数主要是在导航跳转的时候做一些操作,比如跳转页面之前,进行判断 进而选择跳转到哪里 钩子函数根据生效范围根据其生效范围可以分为全局钩子函数,路由独享钩子函数 和 组件钩子函数. ...

  6. mysql修改表引擎Engine

    修改my.ini,在[mysqld]下加上default-storage-engine=INNODB 其中红色字体部分是要指定的引擎名称.用sql语句修改已经建成表的引擎:alter table ta ...

  7. vue缓存之keep-alive,设置想要缓存的页面

    由于项目需求从a页面跳转到b页面,返回a页面,a页面数据不能被刷新掉,方法很多列举12 方法1 a页面通过学期按钮切换学期,该学期里more进入b页面,返回a页面,返回回到对应a页面进入的高亮按钮设置 ...

  8. 05. pt-diskstats

    pt-diskstats --devices-regex=sda --interval=1 --iterations=3 --show-timestamps #ts device rd_s rd_av ...

  9. python 找出一篇文章中出现次数最多的10个单词

    #!/usr/bin/python #Filename: readlinepy.py import sys,re urldir=r"C:\python27\a.txt" disto ...

  10. NC 日志文件注册

    在实际开发中,例如接口向外系统发送数据,这些数据前台看不到,一般都是记录日志,然后在后台日志文件中查看.但是,用系统原本日志文件来看,有时会记录一些别的模块日志信息.所以,我们可以注册个自己的模块日志 ...