gpt4 book ai didi

windows - 消息队列在 Win32 中是如何工作的?

转载 作者:可可西里 更新时间:2023-11-01 13:27:47 25 4
gpt4 key购买 nike

我阅读了一些有关 Win32 的资料以及消息循环的工作原理,但我仍然不清楚:消息队列中到底存储了什么?与消息(WM_COMMANDWM_CREATE 等)对应的整数值或指向包含消息整数值和其他信息的 MSG 结构的指针诸如wParamlParam 等之类的东西?

最佳答案

为了狭义地回答你的问题,队列中的每条消息至少存储,

  • 消息指向的窗口句柄,
  • 消息代码 wParam 和 lParam,正如您已经正确记下的那样,
  • 消息发布的时间,您可以使用 GetMessageTime() 检索,
  • 对于 UI 消息,消息发布时光标的位置(参见 GetMessagePos())。

请注意,并非所有消息都实际存储在队列中。使用 SendMessage() 从拥有窗口的线程发送到窗口的消息永远不会被存储;相反,直接调用接收者窗口的消息函数。从其他线程发送的消息在处理之前一直存储,发送线程阻塞直到消息被回复,通过退出窗口函数或显式调用 ReplyMessage()。 API 函数 InSendMessage() 有助于确定 windows 函数是否正在处理从另一个线程发送的消息。

您或系统发布的消息存储在队列中,但有一些异常(exception)。

  • WM_TIMER 消息从未真正存储;相反,GetMessage() 会在队列中没有其他消息并且计时器已到期时构造一个计时器消息。这意味着,首先,定时器消息具有最低的出队优先级,其次,来自短周期定时器的多条消息永远不会溢出队列,即使 GetMessage() 暂时没有被调用.因此,将为给定计时器发送单个 WM_TIMER 消息,即使该计时器自处理完来自该计时器的最后一条 WM_TIMER 消息以来已经过多次。

  • 同样,WM_QUIT 也不会被存储,而只会被标记。 GetMessage() 假装在队列耗尽后检索到 WM_QUIT,这是它检索到的最后一条消息。

  • 另一个示例是 WM_PAINT 消息(向@cody-gray 致敬,以提醒您注意这一点)。当窗口的任何部分¹被标记为“脏”并需要重新绘制时,也会模拟此消息。这也是一个低优先级的消息,当队列变空时,窗口中的多个无效区域会立即重新绘制,以降低 GUI 的响应速度并减少闪烁。您可以通过调用 UpdateWindow() 强制立即重绘。此函数的作用类似于 SendMessage(),在重绘窗口的暴露部分之前它不会返回。如果该窗口的无效区域为空,此函数不会向该窗口发送 WM_PAINT,作为明显的优化。

可能还有其他异常和内部优化。

使用 PostMessage() 发布的消息最终进入拥有消息发布到的窗口的线程的队列中。

消息在内部以何种形式存储,我们不知道,也不关心。 Windows API 完全抽象了它。 MSG 结构填充在您传递给 GetMessage()PeekMessage() 的内存中。除了 Windows SDK 指南中记录的内容之外,您无需了解或担心内部实现的细节。


¹ 我不知道 WM_PAINT 和 WM_TIMER 相对于彼此的优先级究竟如何。我假设 WM_PAINT 的优先级较低,但我可能错了。

关于windows - 消息队列在 Win32 中是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9238552/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com