为基于对话框的应用程序实现回调函数
我正在阅读一篇关于如何在Visual C ++中创建基于对话框的GUI应用程序的非常古老的教程( 源代码 – 葡萄牙语)。 基于我对WinAPI编程的薄弱知识,我决定修改建议的代码主要是为了实现两件事:
1)与Unicode编程标准的一致性(例如使用wWinMain
和MessageBoxW
而不是WinMain
和MessageBox/MessageBoxA
)。 这样的“标准”似乎全面实施。 示例: 这个问题(评论)
2)在创建非空Win32项目时,Visual Studio提供的模型的一致性。 我这样做并注意到:
- “关于”对话框的回调函数是
INT_PTR
类型而不是BOOL
; -
WndProc
函数返回0,而不是TRUE(这是1),如教程中所示; -
msg
变量的switch
语句默认返回DefWindowProc()而不是FALSE; - 没有指定WM_CLOSE处理(我猜对话框对某些事件有默认处理)。
_
因此,有一个奇怪的行为,其中名为Confirm的MessageBox失焦 – 即我无法单击“确定”和“取消”按钮。
问题:我是否正确地假设Visual Studio生成的模板代码比教程中的代码更正确,这对我来说似乎不值得信任? 如果是的话,我忘了什么吗? 我的代码出了什么问题,为什么我不能单击Messagebox按钮?
我的最终代码如下:
#define WIN32_LEAN_AND_MEAN #include #include "resource.h" INT_PTR CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_DESTROY: PostQuitMessage(0); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: if (MessageBoxW(hWnd, L"Close?", L"Confirm", MB_OKCANCEL) == IDOK) DestroyWindow(hWnd); break; // more code to place here } break; default: return DefWindowProc(hWnd, msg, wParam, lParam); } return 0; } int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { int ret = DialogBoxW(hInstance, MAKEINTRESOURCEW(IDD_DIALOG1), NULL, WndProc); return 0; }
为了完整性,下面是基于教程的代码,它实际上工作正常:
BOOL CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: return TRUE; case WM_CLOSE: DestroyWindow(hWnd); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: if (MessageBoxW(hWnd, L"Close?", L"Confirm", MB_OKCANCEL) == IDOK) DestroyWindow(hWnd); break; } break; default: return FALSE; } return TRUE; }
所以,我明白了。 Visual Studio向导创建的代码确实演示了Windows API的正确实现。
注意事项:
-
对话框过程不应调用
DefWindowProc()
。 正如Hans Passant在评论中指出的那样,这就是MessageBox无法正常工作的原因。 -
VS生成的
WndProc()
函数的目的是处理主应用程序窗口的消息,顾名思义。 还有另一个函数About()
,它处理“关于”对话框的消息。 -
对话框过程的返回类型是
INT_PTR
,这是对BOOL
的改进,因为它通过在64位环境中具有不同的大小来解决平台差异,从而避免了可移植性问题。 -
switch
块不需要default
子句:与窗口过程不同,对话框过程从不调用DefWindowProc函数。 相反,如果它处理消息则返回TRUE,否则返回FALSE。
(对话框编程注意事项 – MSDN) -
对话框具有事件的默认处理:
(DialogBox)函数(…)启动自己的消息循环以检索和分派对话框的消息。
(DialogBoxfunction – MSDN)没有必要像我一样处理
WM_DESTROY
– 甚至WM_DESTROY
。 事实上,这样做可能会导致问题,如此处所见 。