【问题标题】:Window message priority authoritative description窗口消息优先级权威描述
【发布时间】:2012-05-26 00:18:20
【问题描述】:

我发现 some places 提到的窗口消息是由 GetMessage 返回的,优先级是从它们发送的方式派生的,SendMessage 是最高的,而不是 PostMessage,并且仅比用户输入。但是,我在这方面找不到任何权威参考,即来自 Microsoft。 obvious page 似乎明确否认它(说消息按 FIFO 顺序处理,很少有例外),我找不到任何其他参考。

但是我有一个应用程序行为表明存在优先级(每秒处理几个 WM_USER thread 消息,但点击有时需要几秒钟才能得到处理)。所以我想从权威来源了解它的预期行为,以便我可以修复应用程序。

注意:邮件使用PostThreadMessage 发送。我正在查看来自GetMessage 的消息,因此非排队消息不会在这里发挥作用。线程和窗口消息之间的差异可能是可能的。

注意:该应用程序在 WinCE 上运行,特别是 5.0,如果它很重要的话。

【问题讨论】:

    标签: winapi windows-ce


    【解决方案1】:

    Hans's answerthe linked MSDN documentation 没有什么不同。

    消息按照先进先出的顺序处理,就像标准队列一样,有几个特殊的例外,例如 WM_TIMERWM_PAINT 消息。 Hans 将这类消息称为“从窗口状态合成”的消息; MSDN 只是明确地把它们叫出来:

    除了WM_PAINT 消息、WM_TIMER 消息和WM_QUIT 消息之外,系统始终在消息队列的末尾发布消息。这可确保窗口以正确的先进先出 (FIFO) 顺序接收其输入消息。但是,WM_PAINT 消息、WM_TIMER 消息和WM_QUIT 消息保留在队列中,并且仅当队列不包含其他消息时才转发到窗口过程。此外,同一窗口的多个WM_PAINT 消息合并为一个WM_PAINT 消息,将客户区的所有无效部分合并为一个区域。结合WM_PAINT 消息可以减少窗口必须重绘其客户区内容的次数。

    问题是使用SentMessage 发送的消息没有排队,而使用PostMessage 发送的消息是。 MSDN 上的同一篇文章在next section 中也说了这么多:

    未排队的消息立即发送到目标窗口过程,绕过系统消息队列和线程消息队列。

    [...]

    一些发送非排队消息的函数是BroadcastSystemMessageBroadcastSystemMessageExSendMessageSendMessageTimeoutSendNotifyMessage

    没有“优先事项”。但是,您描述的行为很容易解释。最有可能的是,WM_USER 消息是通过调用SendMessage 函数发送的,该函数绕过消息队列并将消息直接发送到目标窗口的窗口过程。这使得它们看起来以更高的“优先级”进行处理,因为它们在SendMessage 函数返回之前立即得到处理,有效地绕过了队列的其余部分。

    这反过来解释了为什么单击事件需要更长的时间来处理 - 因为它们只是与所有其他输入消息一起被推入队列,因此窗口直到之后才开始处理它们通过调用SendMessage来处理直接发送给它的消息。

    重要警告:我对 Windows CE 一无所知,您的问题表明您正在专门谈论它。我在此处描述的行为对于 Windows 的桌面版本是准确的,但如果该行为与 Windows CE 的行为之间存在任何差异,我不会知道并且我可能会出错。

    【讨论】:

    • 该答案与 MSDN 文档的说法不同。答案说发布的消息仍然在用户交互之前处理,这与观察相匹配,但我在 MSDN 文档中没有看到类似的内容。此外,我正在查看来自 GetMessage 的消息,因此我什至看不到非排队消息。
    • 我在回答中澄清了:用户消息使用PostThreadMessage 发送,并由调用GetMessage 的代码处理。我在调度到窗口过程之前正在查看。
    • @Jan:我不知道我还能如何解释它以使其更清楚。汉斯对链接问题的回答与 MSDN 文档之间绝对没有不一致。在WM_PAINTWM_TIMER 等特殊消息之前处理已发布的消息。这些在答案和文档中都被明确指出。此外,GetMessage确实返回/处理发送的消息,因此您仍然会看到通过调用SendMessage 发送的消息。使用SendXxx 函数发送的消息将首先被处理,然后是使用PostXxx 函数发送的消息。
    • 这不是一个特殊的“优先级”事情,只是因为它们的实现方式不同。发送的消息没有排队,它们由窗口过程立即处理。在已发送的消息被处理后,已发布的消息将排队并按 FIFO 顺序处理。像 WM_PAINTWM_TIMER 这样的特殊消息表示布尔值并且是特殊情况的。另请参阅the documentation for the GetMessage function,它简要介绍了在未提供覆盖的情况下如何处理消息。
    • 不,不涉及“特殊”消息。仅发布线程消息和鼠标事件。但是,此链接确实提到已发布的消息在硬件消息之前处理。请将此链接放入主要答案中(并删除其余大部分内容,该链接是我正在寻找的唯一相关位)。谢谢。
    猜你喜欢
    • 2011-11-05
    • 2015-08-29
    • 2015-02-11
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    • 2014-02-08
    • 2012-09-04
    相关资源
    最近更新 更多