WM_PAINT消息是排队消息或非排队消息



在这篇关于消息和消息队列的文章中,有人说WM_PAINT是一种排队消息。

排队消息

每当用户移动鼠标、单击鼠标按钮或键入在键盘上,鼠标或键盘的设备驱动程序转换输入到消息中,并将它们放入系统消息队列中。系统从系统中一次删除一条消息消息队列,检查它们以确定目标窗口,以及然后将它们发布到创建目的地窗口。线程的消息队列接收所有鼠标和线程创建的窗口的键盘消息。螺纹从队列中删除消息,并指示系统将消息发送到适当的窗口处理过程。

除了WM_PAINT消息、WM_TIMER消息和WM_QUIT消息之外,系统总是在消息队列的末尾发布消息。这确保窗口以正确的第一顺序接收其输入消息先进先出(FIFO)序列。WM_PAINT消息,WM_TIMER消息和WM_QUIT消息保留在队列中仅当队列中不包含其他消息。此外,相同的多个WM_PAINT消息窗口合并为一个单独的WM_PAINT消息,合并所有将客户端区域的无效部分合并为一个区域。组合WM_PAINT消息减少了窗口必须重新绘制其客户端区域的内容。

但根据这本书";编程窗口";

但是,窗口过程可以调用一个函数,该函数将窗口过程另一条消息,在这种情况下,窗口过程必须在函数调用之前完成第二条消息的处理返回,此时窗口过程继续原始消息例如当窗口过程调用UpdateWindow时,Windows使用WM_PAINT消息调用窗口过程。当窗口过程完成对WM_PAINT消息的处理UpdateWindow调用将控件返回窗口过程。

如果WM_PAINT是排队消息,则应将其添加到消息队列中。因此,在处理完当前消息和消息队列中的所有其他消息之前,它不会进行处理。这与上述说法存在争议。

我想知道哪个是正确的,谢谢。

任何消息都可以使用SendMessage直接发送到窗口进程,或者使用PostMessage发布到窗口的消息队列。UpdateWindow函数使用SendMessage直接向窗口过程发送WM_PAINT消息,以便立即重新绘制窗口。当系统出于任何原因需要重新绘制窗口时,通常会将消息发布到窗口的消息队列中。

因此,WM_PAINT不是排队(发布)的消息,也不是发送的消息。这只是一个信息。它可以发送也可以邮寄。有些消息只是用来发送或发布的,但WM_PAINT不是其中之一。

以下是MSDN 中有关UpdateWindow函数的文档

UpdateWindow函数更新指定的如果窗口更新区域不为空。函数发送WM_PAINT消息直接到指定窗口的窗口过程,绕过应用程序队列。如果更新区域为空,则没有消息已发送。

WM_PAINT实际上并没有被系统发布在消息队列上,与WM_TIMER相同。如果您尝试从GetMessage循环打印WM_PAINT,您将看不到任何内容。在WM_PAINT消息上不调用DispatchMessage

我认为它是这样工作的:操作系统总是直接发布WM_PAINT。然而,如果不是通过UpdateWindow调用,它首先检查队列并等待,直到队列完全为空,然后才用WM_PAINT调用SendMessage。这样,在绘制之前,您仍然可以处理队列中的所有输入消息。

最新更新