问题描述
Microsoft 有一个 knowledge base article 描述如何修改 ATL .exe 中的消息循环,以便无模式对话框可以接收适当的消息。
我想知道如果您有多个潜在的无模式对话框,并且您不知道在任何给定时间可能存在哪些对话框,我想知道如何优雅地执行此操作。就像 .exe 可能托管几个不同的 COM 类,每个类都有不同的对话框,谁知道哪个可能会被实例化。
您是否会创建一个全局的 hwnd 集,并让每个对话框类在创建时将其 hwnd 放在该集合中,然后让消息循环遍历该集合,调用 IsDialogMessage
(和 TranslateAccelerator
) ?
解决方法
消息指定了它的目标(可能是实际对话的子级),我将通过拥有一组对话指针来处理这个问题,然后简单地使用 IsChild() 迭代测试集,并且仅当正确的对话 HWND发现我会使用 IsDialogMessage。
另一种方法是从 MSG 中的 HWND 向上遍历祖先树,以某种方式将 HWND 转换为对象,当您到达作为对话框的窗口时,请使用 IsDialogMessage。
,WTL 针对这一挑战的解决方案是拥有一个专门的消息循环类,该类将自身注册到静态容器中,以便对话可以发现它们所属线程的消息循环。
对话框可以通过 CMessageLoop::AddMessageFilter
向这些消息循环注册自己,并在翻译消息时调用它们的回调。
// register object for message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);