对话框管理器第四章:对话框消息循环
对话框消息循环,其实也不复杂,其核心实现代码,也就下面几行代码:
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)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。
相关推荐
- 随心所欲地对vcpkg依赖进行版本控制
- Posted on 02月24日
- IContextMenu第十部分:组合扩展的准备工作
- Posted on 11月16日
- 小技巧:IIS提示如果应下载文件,请添加 MIME 映射
- Posted on 06月16日
- 实战经验:修改PHP session存放位置
- Posted on 12月09日
评论已关闭。