7

我试图理解“消息循环”。这是它的外观:

MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

到目前为止,我对这个概念很清楚(至少我希望如此)。当用户使用键盘和鼠标与 Windows 应用程序交互时,这些事件被相应的设备驱动程序转换为适当的消息并发布到系统消息队列。

操作系统从队列中逐一删除消息并检查它们中的每一个以将它们发送到负责创建目标窗口的相应应用程序线程的队列。

现在在我的应用程序中

MSG msg;
GetMessage(&msg, NULL, 0, 0);

从线程特定的消息队列中删除消息并填充 MSG 结构。

但是TranslateMessage据说将虚拟击键转换为字符并将它们发送回调用者线程的消息队列。

DispatchMessage指示 OS 调用适当的目标窗口的 Windows 过程。

两个疑惑:

1)TranslateMessage的确切功能是什么;是否只是将虚拟击键转换为字符消息(我假设虚拟击键是字母和数字以外的击键),如果字符消息被发送回队列,循环是否中断?

2)鼠标事件呢?它们是直接调度的吗?

4

2 回答 2

10

是的,当您的消息循环看起来像这样时,您必须调用 TranslateMessage() 是没有意义的。但这不是规范的 Petzold 消息循环的样子:

while (GetMessage(&msg, NULL, 0, 0))
{
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

加速器在这里很重要,也称为“快捷键”。无论哪个窗口具有焦点,您的程序都希望响应它们。就像 F1 显示程序的帮助文件一样,不管哪个控件有焦点。您不想编写子类化每个控制窗口的代码来识别 F1。

所以如果它是一个快捷键,那么你不想调用 TranslateMessage。如果键碰巧与键入键匹配,则该键不应产生 WM_CHAR 消息。这就是为什么它是一个单独的调用。

于 2012-09-25T12:17:42.257 回答
3

简而言之,

  1. 是的,它只是将虚拟按键转换为字符消息
  2. 是的,他们是直接派出的,见msdn上的这个博客

详情见

于 2012-09-25T11:31:24.277 回答