WM_PAINT和WM_ERASEBKGND消息
2015-04-03 17:02
162 查看
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后可能不会立即重绘窗口,因为它要等到消息队列中的其它消息发送完后才能被处理。函数原型:
其参数决定了是否要在WM_PAINT消息前发送WM_ERASEBKGND消息来擦除窗口背景,bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。
InvalidateRect()同Invalidate功能相同,但可以指定重绘的区域,函数原型:
① 在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 );
参考出处:http://www.cnblogs.com/BeyondTechnology/archive/2011/03/25/1995942.html [b]3、[/b]GetUpdateRect(LPRECT lpRect, BOOL bErase = FALSE)可以获得需要更新的区域,在调用了InvalidRect后可以用这个函数来获得无效区域,但如果调用了BeginPaint则获得的区域为空,所以在OnPaint中调用GetUpdateRect()无效。 GetClientRect()得到的RECT以所在窗口左上角为原点,且不包括标题栏,外框。 GetWindowRect()得到的RECT以屏幕左上角为原点,获得整个窗口的矩形。 ScreenToClient()就是把屏幕坐标系下的RECT坐标转换为客户区坐标系下的RECT坐标。 ClientToScreen()就是把客户区坐标系下的RECT坐标转换为屏幕坐标系下的RECT坐标。
相关文章推荐
- 窗口绘制有关的消息整理 WM_PAINT, WM_NCPAINT, WM_ERASEBKGND
- WM_PAINT 和 WM_ERASEBKGND 消息的区别
- WM_PAINT 和 WM_ERASEBKGND 消息的区别 .
- PAINT和WM_ERASEBKGND消息
- 深度分析WM_PAINT和WM_ERASEBKGND消息
- WM_PAINT 和 WM_ERASEBKGND 消息的区别
- 深度分析WM_PAINT和WM_ERASEBKGND消息
- Invalidate(TRUE)与Invalidate(FALSE)区别(前者会发送WM_ERASEBKGND消息全部刷新,然后使用WM_PAINT消息绘制,而后者只发送WM_PAINT消息)
- WM_Paint 消息详解
- 系统何时发送WM_PAINT消息?
- wm_paint 消息详细解析(
- WM_PAINT消息小结
- WM_PAINT在微软官方定义中,wParam和lParam都没有使用,所以就被Delphi给重定义了这个消息,还增加了DC(Delphi可任意改写消息的结构,只需要保持前4个字节是消息即可,另外要携带微软定义的所有必要信息就行了)
- 对话框找不到WM_ERASEBKGND消息的解决方法与对话框背景图片的载入方法
- 关于WM_ERASEBKGND和WM_PAINT的深刻理解
- WM_PAINT与WM_ERASEBKGND
- VC对话框如何添加WM_ERASEBKGND消息(OnEraseBkgnd函数)及对话框使用位图背景并透明
- 关于WM_PAINT消息
- WM_Paint 消息详解
- WM_Paint消息详解