码迷,mamicode.com
首页 > 其他好文 > 详细

WM_PAINT和WM_ERASEBKGND消息

时间:2015-04-03 19:07:12      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:

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

void Invalidate( BOOL bErase = TRUE);

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

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

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

CWnd::UpdateWindow()会通过发送WM_PAINT消息对客户区进行重绘,如果没有可绘制的区域则不进行重绘。如果有可绘制的区域的话UpdateWindow()会立即重绘窗口,它发送的WM_PAINT消息不会进入消息队列而是直接调用窗口过程进行重绘。所以一般是调用Invalidate()后接着调用UpdateWindow()来使窗口立即重绘函数原型:
void UpdateWindow();
CWnd::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 

WM_PAINT和WM_ERASEBKGND消息

标签:

原文地址:http://www.cnblogs.com/milanleon/p/4389922.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!