当前位置:网站首页>对话框管理器第四章:对话框消息循环
对话框管理器第四章:对话框消息循环
2022-08-03 02:49:00 【拓扑梅尔-漫漫开发路】
对话框消息循环,其实也不复杂,其核心实现代码,也就下面几行代码:
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》
边栏推荐
猜你喜欢
随机推荐
基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证
[Arduino] Reborn Arduino Monk (2)----Arduino Language
C语言——-动态内存开辟与管理(malloc,free,calloc,realloc)+柔性数组
Spark SQL简介
sql问题,如何能做到先声明表的名称,例如product202201,表示2022年一月份的货物表,再在声明过的表中查找,下面的代码运行时有错误显示找不到表table_name,请问改如何进行修改
[QNX Hypervisor 2.2用户手册]10 虚拟设备参考
【静态类型和动态类型 编译检查和运行检查 Objective-C中】
记录学习--Navicat使用自定义数据库列表
Jmeter TCP/UDP测试
重定向printf到USB CDC、串口2
monkey 压测
els 结束判断
信号和槽的绑定
Go新项目-编译项目的细节(4)
05-分布式计算框架
问题记录:jenkins构建时报错The goal you specified requires a project to execute but there is no POM in...
黑马程序员Servlet
如何画一张架构图(内含知识图谱)
【云原生】服务行业案例-不可预测的并发场景解决方案
ROS2自学笔记:机器视觉基础