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