首页 / 软件开发 / C++ / 窗口刷新问题(WM_PAINT、BeginPaint、EndPaint的说明)
窗口刷新问题(WM_PAINT、BeginPaint、EndPaint的说明)2011-04-21 C++博客 OnTheWay在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函数,第一次创建 窗口,改变了窗口的大小,最大化,最小化等等。这些动作的产生都是有系统来控制的,应 用程序只是接收消息,并处理消息。当Window检测到窗口被覆盖的地方需要恢复的时 候,它会向用户程序发送一个WM_PAINT消息,消息中包括了需要恢复的区域,然后由用户程 序来决定如何恢复被覆盖的内容。窗口过程收到WM_PAINT消息后,并不代表整个客户区都需 要被刷新,有可能客户区被覆盖的区域只有一小块,这个区域叫做“无效区域” ,程序只需要更新这个区域。与WM_TIMER消息类似,WM_PAINT消息也是一个低级别的消息, 虽然它不会像WM_TIMER消息一样被丢弃,但Windows总是在消息循环空的时候才把WM_PAINT放 入其中,实际上,Windows为每个窗口维护一个“绘图信息结构”,无效区域的坐 标就在其中,每当消息循环空的时候,如果Windows发现存在一个无效区域,就会放入一个 WM_PAINT消息。无效区域的坐标并不附带在WM_PAINT消息的参数中,在程序中有其他 方法可以获取,WM_PAINT消息只是通知程序有个区域需要更新而已,所以Windows也不会同时 将两条WM_PAINT消息放入消息循环中,当Windows要放入一条WM_PAINT消息的时候,如果发现 已经存在一个无效区域了,那么它只需要把新旧两个无效区域合并计算出一个无效区域就可 以了,消息循环中还是只需要一条WM_PAINT消息。如果程序在WM_PAINT消息中对客户 区刷新完毕后工作并没有结束,如果不使无效区域变得有效,Windows会在下一轮消息循环中 继续放入一个WM_PAINT消息,而不是根据程序是否执行了刷新过程,所以程序也可以不去刷 新客户区,而是简单地用一个ValidateRect函数直接让客户区变得有效,以此来“欺骗 ”Windows已经没有无效区域了,当Windows检查“绘图信息结构”的时候发 现没有了无效区域,也就不会继续发送WM_PAINT消息了。那么“绘图信息结构 ”怎么获取呢?BeginPaint函数的第二个参数是一个绘图信息结构的缓冲区地址, windows会在这里返回绘图信息结构,结构中包含了无效区域的位置和大小,绘图信息结构的 定义如下:typedef struct tagPAINTSTRUCT { // ps
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32];
} PAINTSTRUCT;