WM_PAINT消息小结

WM_PAINT是Windows窗口系统中一条重要的消息,应用程序通过处理该消息实现在窗口上的绘制工作。

1. 系统何时发送WM_PAINT消息?

系统会在多个不同的时机发送WM_PAINT消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时,等等,这些动作都是由 系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;大多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,这一般是通过InvalidateRect和 InvalidateRgn函数来完成的。InvalidateRect和InvalidateRgn把指定的区域加到窗口的Update Region中,当应用的消息队列没有其他消息时,如果窗口的Update Region不为空时,系统就会自动产生WM_PAINT消息。

系统为什么不在调用Invalidate时发送WM_PAINT消息呢?又为什么非要等应用消息队列为空时才发送WM_PAINT消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽 可能地推后做。不过这样也有利于提高绘制的效率:两个WM_PAINT消息之间通过InvalidateRect和InvaliateRgn使之失效的区域就会被累加起来,然后在一个WM_PAINT消息中一次得到 更新,不仅能避免多次重复地更新同一区域,也优化了应用的更新操作。像这种通过InvalidateRect和InvalidateRgn来使窗口区域无效,依赖于系统在合适的时机发送WM_PAINT消息的机 制实际上是一种异步工作方式,也就是说,在无效化窗口区域和发送WM_PAINT消息之间是有延迟的;有时候这种延迟并不是我们希望的,这时我们当然可以在无效化窗口区域后利用SendMessage 发送一条WM_PAINT消息来强制立即重画,但不如使用Windows GDI为我们提供的更方便和强大的函数:UpdateWindow和RedrawWindow。UpdateWindow会检查窗口的Update Region,当其不为空时才发送WM_PAINT消息;RedrawWindow则给我们更多的控制:是否重画非客户区和背景,是否总是发送WM_PAINT消息而不管Update Region是否为空等。

2. BeginPaint

BeginPaint和WM_PAINT消息紧密相关。试一试在WM_PAINT处理函数中不写BeginPaint会怎样?程序会像进入了一个死循环一样达到惊人的CPU占用率,你会发现程序总在处理一个接 一个的WM_PAINT消息。这是因为在通常情况下,当应用收到WM_PAINT消息时,窗口的Update Region都是非空的(如果为空就不需要发送WM_PAINT消息了),BeginPaint的一个作用就是把该Update Region置为空,这样如果不调用BeginPaint,窗口的Update Region就一直不为空,如前所述,系统就会一直发送WM_PAINT消息。

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

另外要注意的一点是,BeginPaint只能在WM_PAINT处理函数中使用。

时间: 2024-11-10 05:35:10

WM_PAINT消息小结的相关文章

wm paint-求教WM_PAINT消息和非WM_PAINT消息下绘图的区别

问题描述 求教WM_PAINT消息和非WM_PAINT消息下绘图的区别 小弟新学WIN32下的编程.对WM_PAINT消息下绘制图形和非WM_PAINT下绘图感到很困惑.不知道什么时候需要在WM_PAINT下绘图,什么时候收到消息后直接绘图.求教.

窗口刷新问题(WM_PAINT、BeginPaint、EndPaint的说明)

在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 qu

C#开发WINDOWS应用程序时消息的处理

window|程序 WINDOWS应用程序是靠消息驱动的,在VC中我们通过CLASSWIZARD可以为某窗口类添加消息处理函数,CLASSWIZARD将为你添加消息映射,对于WINDOWS消息,生成的消息处理函数重载了基类的虚拟方法.而在C#中如何处理消息呢?本文针对VS.NET BETA1环境下的C#简单地介绍WINDOWS消息以及自定义消息的处理方法. 示例代码下载 17K 一.生成一个名为MSGApplication的工程 工程的建立方法请参考:C#学习笔记之一 二.处理WM_PAINT消

C#钩子本线程内消息拦截

钩子其实就是调用一下API而已: 1.安装钩子: SetWindowsHookEx 函数原形:HHOOK SetWindowsHookEx( int idHook, // 钩子类型, HOOKPROC lpfn, // 钩子函数地址 INSTANCE hMod, // 钩子所在的实例的句柄, DWORD dwThreadId // 钩子所监视的线程的线程号 ) hMod: 对于线程序钩子,参数传NULL: 对于系统钩子:参数为钩子DLL的句柄 dwThreadId:对于全局钩子,该参数为NULL

揭开.NET消息循环的神秘面纱

循环 曾经在Win32平台下奋战的程序员们想必记得,为了弄清楚"消息循环"的概念,度过多少不眠之夜.尽管如今在应用程序代码的编写过程中,我们已经不再需要它,但是深刻理解Windows平台内部的消息流转机制依然必要.. 在早年直接用Win32/Win16 API写程序的时代,消息循环是我们必须搞懂的第一个观念.现在,不管你用是Windows上面的哪一套Application Framework(MFC.VCL.VB..NET Framework),甚至Unix.Linux.MacOSX上

汇编教程之处理键盘输入消息

在本课中,我们将要学习WINDOWS程序是如何处理键盘消息的. 理论: 因为大多数的PC只有一个键盘,所以所有运行中的WINDOWS程序必须共用它.WINDOWS 将负责把击键消息送到具有输入焦点的那个应用程序中去.尽管屏幕上可能同时有几个应用程序窗口,但一个时刻仅有一个窗口有输入焦点.有输入焦点的那个应用程序的标题条总是高亮度显示的. 实际上您可以从两个角度来看键盘消息:一是您可以把它看成是一大堆的按键消息的集合,在这种情况下,当您按下一个键时,WINDOWS就会发送一个WM_KEYDOWN给

深度解析VC中的消息(中)

队列消息和非队列消息 从消息的发送途径来看,消息可以分成2种:队列消息和非队列消息.消息队列由可以分成系统消息队列和线程消息队列.系统消息队列由Windows维护,线程消息队列则由每个GUI线程自己进行维护,为避免给non-GUI现成创建消息队列,所有线程产生时并没有消息队列,仅当线程第一次调用GDI函数数系统给线程创建一个消息队列.队列消息送到系统消息队列,然后到线程消息队列:非队列消息直接送给目的窗口过程. 对于队列消息,最常见的是鼠标和键盘触发的消息,例如WM_MOUSERMOVE,WM_

在C#应用程序与DLL交互中使用消息

C#是一种类似 Java 的完全面向对象的高级编程语言,其处理过程采用事件驱动方式,但在实际的使用过程中,有时候通过调用系统原有的消息处理起来会更简单,特别是在处理与DLL文件的交互时,实践证明的确是非常方便的. 在C#中使用自定义消息 在C#中使用自定义消息非常简单,只需要下面几个简单的步骤就可以了: 1.定义消息 定义消息的方法与在VC中定义消息有一点点不同,比如在VC中申明一个自定义消息是这样的: #define WM_TEST WM_USER + 101 而在C#中消息需要定义成 Win

模态窗口其实就是在当前窗口调用系统的消息循环,响应用户的操作,将相关的消息发送到对应的窗口(转)

  上周准备在公司内部转岗,面了3个部门windows客户端相关的工作,最终拿到3个Offer,主要涉及C++和Windows两大块内容,C++的题目基本都答上了,Windows一直都是我的弱项,在这里记录一下Windows相关的题目.有些答不上的问题就没列出来,还有些问题忘了,下面的答案有些大部分是我自己的理解,有些是直接从网上copy的,有问题大家可以讨论. 1:GetMessage和PeekMessage的区别? GetMessage:获取消息队列中的一个消息,存入MSG中,并从消息队列中