对话框管理器第四章:对话框消息循环

对话框管理器第四章:对话框消息循环

作者:BlogUpdater |  时间:2022-08-02 |  浏览:143 |  评论已关闭 条评论

对话框消息循环,其实也不复杂,其核心实现代码,也就下面几行代码:

while (<dialog still active> &&
       GetMessage(&msg, NULL, 0, 0, 0)) {
 if (!IsDialogMessage(hdlg, &msg)) {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
 }
}

但是,我们还是从头开始讲起吧。故事发生在DialogBoxIndirectParam调用,你应该还记得,我们之前讲解过,系统会将所有对DialogBoxXX的调用,统一转换为对DialogBoxIndirectParam的调用,代码如下:

INT_PTR WINAPI DialogBoxIndirectParam(
    HINSTANCE hinst,
    LPCDLGTEMPLATE lpTemplate, HWND hwndParent,
    DLGPROC lpDlgProc, LPARAM lParam)
{
 /*
  * App hack!  Some people pass GetDesktopWindow()
  * as the owner instead of NULL.  Fix them so the
  * desktop doesn't get disabled!
  */
 if (hwndParent == GetDesktopWindow())
  hwndParent = NULL;

没错,我们在代码中做了一次App Hack。 在前面的文章中,我们讨论了传递 GetDesktopWindow() 作为父窗口问题。 有很多开发者都犯了这个错误,我们不得不把这个App Hack 内置到核心操作系统代码中。 如果我们不这样做的话,则成百上千的上层应用程序都需要进行改动。

由于只有顶层窗口可以是窗口所有者,所以我们必须从hwndParent(可能是子窗口)出发,沿着窗口层次结构向上走,直到找到一个顶层窗口。

 if (hwndParent)
  hwndParent = GetAncestor(hwndParent, GA_ROOT);

完成了第二次App Hack之后,我们开始创建我们的对话框了:

 HWND hdlg = CreateDialogIndirectParam(hinst,
               lpTemplate, hwndParent, lpDlgProc,
               lParam);

注意:和以前一样,我将忽略错误检查和各种对话框,因为它只会分散本条目的重点。
因为模态对话框会禁用它们的父窗口,所以在这里实现它:

 BOOL fWasEnabled = EnableWindow(hwndParent, FALSE);

然后我们进入对话框模态消息循环:

 MSG msg;
 while (<dialog still active> &&
        GetMessage(&msg, NULL, 0, 0)) {
  if (!IsDialogMessage(hdlg, &msg)) {
   TranslateMessage(&msg);
   DispatchMessage(&msg);
  }
 }

根据窗口退出消息的约定,我们重新投递我们可能收到的任何退出消息,以便下一个外部模态循环可以看到它。

 if (msg.message == WM_QUIT) {
  PostQuitMessage((int)msg.wParam);
 }

(聪明的读者可能已经注意到了看,上面的代码中有一个未初始化的变量错误:如果在 WM_INITDIALOG 处理期间调用了 EndDialog,则永远不会设置 msg.message。出于说明目的,我决定忽略这个错误。)

至此,我们的对话框完成使命了,我们需要清理一下。 请记住在销毁拥有的对话框之前启用所有者。

if (fWasEnabled)
 EnableWindow(hwndParent, TRUE);
DestroyWindow(hdlg);

最后,返回结果:

 return <value passed to EndDialog>;
}

恭喜,你现在是对话框专家了。 明天,我们将看看,如何充分利用今天学习到的专业知识。

练习:想办法偷偷穿过两层上面代码中关于父窗口的App Hack,最终得到一个对话框,其所有者是桌面,并解释这种情况的可怕后果。

总结
好了,对话框专家,你看到了:代码之下,没有什么神秘的东西,有因就有果。
这个世界,依然是唯物的。

最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《The dialog manager, part 4: The dialog loop》

最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。

评论已关闭。