代码改变世界

关于WM_PAINT消息

2008-07-02 19:05  libiver  阅读(187)  评论(0编辑  收藏  举报

                                关于WM_PAINT消息

 

在Windows  API编程中,WM_PAINT是Windows窗口的一个重要消息,应用程序就是通过响应这个消息来完成窗口的绘制。

The WM_PAINT message is generated by the system and should not be sent by an application.

     The system sends this message when there are no other messages in the application's message

queue

 

注意:WM_PAINT消息是由系统产生,非要等应用程序的消息队列为空时才发送WM_PAINT消息 。

其实系统会在很多的不同的机制下发送WM_PAINT消息,比如调用UpdateWindow函数,第一次创建窗口,改变了窗口的大小,最大化,最小化等等。这些动作的产生都是有系统来控制的,应用程序只是接收消息,并处理消息。

 

今天在处理WM_PAINT消息时产生了一个低级的错误,并搞的我花了快一个小时才找到原因。我在处理消息时,没有使用BeginPaintEndPaint这对函数,结果我其余的消息弹不出来,窗口拖动时,不停闪烁(其实那就是重绘)。后来还是在MSDN上找到了答案,现将原话贴出来。(MSDNThe WM_PAINT Message标题中

     BeginPaint sets the update region of a window to NULL. This clears the region, preventing it from

 generating subsequent WM_PAINT messages. If an application processes a WM_PAINT message but

 does not call BeginPaint or otherwise clear the update region, the application continues to receive 

WM_PAINT messages as long as the region is not empty. In all cases, an application must clear the

 update region before returning from the WM_PAINT message. 

     BeginPaint函数的作用就是将窗口需要重绘的区域设置为空(也就是Update Region置空)。在正常情况下,我们接收到了WM_PAINT消息后,窗口的Update Region都是非空的(如果为空就不需要发送WM_PAINT消息了)。而当你响应这个消息的时候又不调用BeginPaint来清空,窗口的Update Region就一直是非空的,系统就会一直发送WM_PAINT消息。这样就形成了一个处理WM_PAINT消息的死循环。这就是我出现错误的原因,低级错误。

     BeginPaintWM_ERASEBKGND消息也有关系。当窗口的Update Region被标志为需要擦除背景时,BeginPaint会发送WM_ERASEBKGND消息来重画背景,同时在其返回信息里有一个标志表明窗口背景 是否被重画过。当我们用InvalidateRectInvalidateRgn来把指定区域加到Update Region中时,可以设置该区域是否需要被擦除背景,这样下一个BeginPaint就知道是否需要发送WM_ERASEBKGND消息了。

    当然关于 WM_PAINT消息还有很多的知识需要学习。另外要注意的一点是,BeginPaint只能在WM_PAINT处理函数中使用,并且在调用了BeginPaint函数后,不要忘记了调用EndPaint函数,他们可是一对的。