消息队列在Win32中如何工作?

use*_*856 6 windows winapi windows-messages

我在Win32上阅读了一些内容以及消息循环是如何工作的,而且还有一些东西对我来说还不清楚:消息队列中究竟存储了什么?对应于消息中的整数值(WM_COMMAND,WM_CREATE等)或一个指针,指向MSG包含该消息的整数值和其他的东西等结构wParam,lParam等?

kkm*_*kkm 13

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

  • 消息所指向的窗口句柄,
  • 消息代码,wParam和lParam,正如您已经正确指出的那样,
  • 邮件发布的时间,您检索的时间GetMessageTime(),
  • 对于UI消息,消息发布时光标的位置(请参阅参考资料GetMessagePos()).

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

您或系统发布的消息存储在队列中,但有一些例外.WM_TIMER消息从未实际存储过 ; 相反,GetMessage()如果队列中没有其他消息并且计时器已经成熟,则构造一个计时器消息.这意味着,首先,定时器消息具有最低的出队优先级,其次,来自短周期定时器的多个消息永远不会溢出队列,即使GetMessage()暂时不调用.同样,WM_QUIT也不存储,而只是标记.GetMessage()假装在队列耗尽后检测到WM_QUIT,这是它检索的最后一条消息.可能还有其他例外和内部优化.

发布的消息UpdateWindow()最终位于拥有发布消息的窗口的线程的队列中.

消息以什么形式存储在内部,我们不知道,我们也不在乎.Windows API完全抽象出来.MSG结构填充在您传递给SendMessage()或的内存中PostMessage().除了Windows SDK指南中记录的内容之外,您无需了解或担心内部实现的详细信息.


Han*_*ant 9

Windows中的消息队列是一种抽象.将它想象成一个队列非常有帮助,但它的实际实现要详细得多.Windows中有四种不同的消息来源:

  • SendMessage()传递的消息.Windows直接调用窗口过程,Peek/GetMessage()不返回消息,但需要调用该函数才能调度.到目前为止,大多数消息都以这种方式传递.WM_COMMAND就是这样,它直接由转换关键事件的代码发送,比如TranslateAccelerator().没有类似队列的行为.

  • 从窗口状态合成的消息.最好的例子是WM_PAINT,当"窗口有一个脏矩形"状态标志被设置时传递.并且,当"定时器已到期"状态标志被设置时传送WM_TIMER.这些是"低优先级"消息,仅在消息队列为空时传递.它们由GetMessage()提供,但不以其他方式存在于队列中.

  • 输入键盘和鼠标的事件消息.这些是真正具有类似队列行为的消息.对于键盘,这确保了预先输入,当程序未准备好接受击键时,没有键击丢失.一堆状态与它相关联,例如,键盘的整个状态被复制.除了状态较少外,鼠标大致相同.的WM_MOUSEMOVE消息是一个有趣的角的情况下,队列不存储由所述光标穿过每单个像素.位置更改将累积到单个消息中,并在必要时存储或传递.

  • 通过显式PostMessage()调用存储在队列中的消息.这完全取决于程序代码,显然它只需要存储调用的参数加上调用的时间,这样就可以在GetMessage()时准确地重放它.