我正在尝试理解“消息循环”。 这是它的样子:
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
到目前为止,我很清楚(至少我希望如此)这个概念。当用户使用键盘和鼠标与 Windows 应用程序交互时,这些事件将由相应的设备驱动程序转换为适当的消息并发布到系统消息队列。
操作系统从队列中一一删除消息,并检查每条消息,将它们发送到负责创建目标窗口的相应应用程序线程的队列。
现在在我的应用程序中
MSG msg;
GetMessage(&msg, NULL, 0, 0);
从线程特定消息队列中删除消息并填充 MSG 结构。
但是
TranslateMessage
据说会将虚拟击键转换为字符并将它们发送回调用者线程的消息队列。
DispatchMessage
指示操作系统调用适当目标窗口的Windows过程。
两个疑问:
1)TranslateMessage的具体功能是什么?它只是将虚拟击键翻译为字符消息(我假设虚拟击键是除字母和数字之外的击键),如果将字符消息发送回队列,不是循环坏了?
2)鼠标事件呢?它们是直接调度的吗?
是的,当您的消息循环看起来像这样时,您必须调用 TranslateMessage() 是没有意义的。 但这并不是规范的 Petzold 消息循环的样子:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(hMainWindow, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
加速器在这里很重要,也称为“快捷键”。 无论哪个窗口具有焦点,您的程序都希望响应它们。 就像F1显示程序的帮助文件一样,无论哪个控件具有焦点。 您不想编写子类化每个控制窗口的代码来识别 F1。
因此,如果它是快捷键,那么您不想想要调用TranslateMessage。 如果该键恰好与键入键匹配,则该键不应产生 WM_CHAR 消息。 这就是为什么它是一个单独的调用。