消息队列如何在Win32中工作? [英] How does the message queue work in Win32?

查看:191
本文介绍了消息队列如何在Win32中工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了Win32上的一些内容以及消息循环的工作方式,但是我仍然不清楚:消息队列中到底存储了什么?对应于消息(WM_COMMANDWM_CREATE等)的整数值,还是指向包含消息整数值和其他内容(例如wParamlParam等)的MSG结构的指针?

I read some stuff on Win32 and how the message loop works, and there's something that is still unclear to me: What exactly is stored in the message queue? The integer value that corresponds to a message (WM_COMMAND, WM_CREATE, etc) or a pointer to a MSG structure containing the message integer value and other stuff like wParam, lParam, etc?

推荐答案

要狭义地回答您的问题,队列中的每个消息至少要存储

To answer your question narrowly, each message in the queue stores, at the least,

  • 消息所指向的窗口句柄,
  • 您已经正确指出的消息代码wParam和lParam,
  • 发布消息的时间,您使用GetMessageTime()进行检索,
  • 对于UI消息,张贴消息时光标的位置(请参见GetMessagePos()).
  • a window handle to which the message is directed,
  • the message code, wParam and lParam, as you already correctly noted,
  • the time when the message was posted, that you retrieve with GetMessageTime(),
  • for UI messages, the position of the cursor when the message was posted (see GetMessagePos()).

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

Note that not all messages are actually stored in the queue. Messages that are sent with SendMessage() to a window from the thread that owns the window are never stored; instead, a receiver window's message function is called directly. Messages sent from other threads are stored until processed, and the sending thread blocks until the message is replied to, either by exiting the window function or explicitly with a call to ReplyMessage(). The API function InSendMessage() helps figure out whether the windows function is processing a message sent from another thread.

您或系统帖子的消息存储在队列中,但有一些例外.

Messages that you or the system post are stored in the queue, with some exceptions.

  • WM_TIMER消息从不真正地存储;相反,如果队列中没有其他消息并且定时器已经成熟,则GetMessage()会构造一个定时器消息.这意味着,首先,计时器消息具有最低的出队优先级,其次,即使短时间不调用GetMessage(),来自短时间计时器的多个消息也永远不会溢出队列.结果,即使给定计时器发送了单个 WM_TIMER消息,即使该计时器自处理该计时器的最后一个WM_TIMER消息以来已经经过了多次.

  • WM_TIMER messages are never actually stored; instead, GetMessage() constructs a timer message if there are no other messages in the queue and a timer has matured. This means that, first, the timer messages have the lowest dequeuing priority, and, second, that multiple messages from a short period timer would never overflow queue, even if GetMessage() is not called for a while. As a result, a single WM_TIMER message is sent for the given timer, even if the timer has elapsed multiple times since the last WM_TIMER message from that timer has been processed.

类似地,WM_QUIT也没有存储,而是仅被标记. GetMessage()假装在队列用尽后检索到WM_QUIT,这是它检索到的最后一条消息.

Similarly, WM_QUIT is also not stored, and rather only flagged. GetMessage() pretends to have retrieved the WM_QUIT after the queue has been exhausted, and this is the last message it retrieves.

另一个示例是WM_PAINT消息(提示给@ cody-gray的提示).当窗口¹的任何部分都标记为脏"并需要重新粉刷时,也会模拟此消息.这也是一条低优先级的消息,它使队列中的所有无效区域在队列变空时立即全部重新绘制,以降低GUI的响应速度并减少闪烁.您可以通过调用UpdateWindow()强制立即重绘.该函数的作用与SendMessage()相同,即在重新绘制窗口的暴露部分之前,它不会返回.如果该窗口的无效区域为空,此函数不会向该窗口发送WM_PAINT,这是显而易见的优化.

Another example is the WM_PAINT message (hat tip to @cody-gray for reminding about this). This message is also simulated when any part of the window¹ is marked as "dirty" and needs repainting. This is also a low-priority message, made so that multiple invalidated regions in a window are repainted all at once when the queue becomes empty, to reduce responsiveness of the GUI and reduce flicker. You can force an immediate repaint by calling UpdateWindow(). This function acts like SendMessage(), in the sense that it does not return until the exposed part of the window is redrawn. This function does not send a WM_PAINT to the window if the invalid region of that window is empty, as an obvious optimization.

可能还有其他例外和内部优化.

Probably, there are other exceptions and internal optimizations.

PostMessage()发布的消息最终在拥有该消息发布窗口的线程的队列中结束.

Messages posted with PostMessage() end up in the queue of a thread that owns the window to which the message is posted.

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

In what form the messages are stored internally, we do not know, and we do not care. Windows API abstracts that completely. The MSG structure is filled in memory you pass to GetMessage() or PeekMessage(). You do not need to know or to worry about the details of internal implementation beyond those documented in Windows SDK guides.

¹我不知道WM_PAINT和WM_TIMER相对于彼此的优先级如何精确.我认为WM_PAINT的优先级较低,但是我可能错了.

¹ I do not know how exactly WM_PAINT and WM_TIMER are prioritized relative to each other. I assume WM_PAINT has a lower priority, but I may be wrong.

这篇关于消息队列如何在Win32中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆