我读了一些关于 Win32 以及消息循环如何工作的内容,但有一些东西我仍然不清楚:消息队列中到底存储了什么?对应于消息的整数值(WM_COMMAND
, WM_CREATE
等)或指向MSG
包含消息整数值和其他内容的结构,例如wParam
, lParam
, etc?
为了狭隘地回答你的问题,队列中的每条消息至少存储,
- 消息定向到的窗口句柄,
- 消息代码 wParam 和 lParam,正如您已经正确指出的那样,
- 您检索消息的发布时间
GetMessageTime()
,
- 对于 UI 消息,消息出现时光标的位置posted (see
GetMessagePos()
).
请注意,并非所有消息实际上都存储在队列中。发送的消息SendMessage()
从拥有该窗口的线程到该窗口的数据永远不会被存储;相反,直接调用接收者窗口的消息函数。从其他线程发送的消息将被存储直到处理,并且发送线程会阻塞,直到消息得到答复(通过退出窗口函数或显式调用ReplyMessage()
。 API函数InSendMessage()
帮助确定 Windows 函数是否正在处理从另一个线程发送的消息。
您或系统发布的消息都存储在队列中,但有一些例外。
WM_TIMER 消息实际上从来没有stored;反而,GetMessage()
如果队列中没有其他消息并且计时器已到期,则构造计时器消息。这意味着,首先,定时器消息具有最低的出队优先级,其次,来自短周期定时器的多个消息永远不会溢出队列,即使GetMessage()
有一段时间没有被叫到。结果,一个single即使自处理来自该计时器的最后一个 WM_TIMER 消息以来该计时器已经经过多次,也会为给定计时器发送 WM_TIMER 消息。
类似地,WM_QUIT 也不会被存储,而只是被标记。GetMessage()
队列耗尽后,假装已检索到 WM_QUIT,这是它检索到的最后一条消息。
另一个例子是 WM_PAINT 消息(向 @cody-gray 致敬以提醒您这一点)。当窗口的任何部分被标记为“脏”并且需要重新绘制时,也会模拟此消息。这也是一条低优先级消息,以便在队列变空时立即重新绘制窗口中的多个无效区域,以降低 GUI 的响应能力并减少闪烁。您可以通过调用强制立即重新绘制UpdateWindow()
。这个函数的作用就像SendMessage()
,从某种意义上说,直到重新绘制窗口的暴露部分之前它不会返回。这个函数的作用是not如果该窗口的无效区域为空,则发送 WM_PAINT 到该窗口,这是一个明显的优化。
可能还有其他例外和内部优化。
发布的消息PostMessage()
最终进入拥有消息发布到的窗口的线程的队列中。
消息在内部以什么形式存储,我们不知道,也不关心。 Windows API 完全抽象了这一点。 MSG 结构填充在您传递给的内存中GetMessage()
or PeekMessage()
。除了 Windows SDK 指南中记录的内容之外,您无需了解或担心内部实现的细节。
1 我不知道 WM_PAINT 和 WM_TIMER 相对于彼此的优先级到底如何。我认为 WM_PAINT 的优先级较低,但我可能是错的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)