我试图理解'消息循环'。 这是它的外观:
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)鼠标事件怎么样?他们是直接发送的吗?
答案 0 :(得分:8)
是的,当您的消息循环看起来像这样时,您必须调用TranslateMessage()是没有意义的。但这不是规范的Petzold消息循环的样子:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
加速器在这里很重要,也称为“快捷键”。无论哪个窗口具有焦点,您的程序都希望对它们做出响应。就像F1显示程序的帮助文件一样,无论哪个控件都有焦点。您不希望编写将每个控制窗口子类化以识别F1的代码。
因此,如果它是一个快捷键,那么不想要调用TranslateMessage。如果密钥恰好与键入密钥匹配,则密钥不应生成WM_CHAR消息。这就是为什么它是一个单独的电话。
答案 1 :(得分:3)
简而言之,
详见