为基于对话框的应用程序实现回调函数
Implementing callback function for dialog-based application
我正在阅读一篇关于如何在 Visual C++ 中创建基于对话框的 GUI 应用程序的非常古老的教程(source - 葡萄牙语)。基于我对 WinAPI 编程的薄弱了解,我决定修改建议的代码主要是为了实现两件事:
1) 与 Unicode 编程标准一致(例如使用 wWinMain
和 MessageBoxW
而不是 WinMain
和 MessageBox/MessageBoxA
).这样的"standard"好像到处都是强制执行的。示例:this question (comments)
2) 创建非空 Win32 项目 时与 Visual Studio 提供的模型一致。我这样做并注意到:
- "About" 对话框的回调函数类型为
INT_PTR
而不是 BOOL
;
WndProc
函数 returns 0,而不是教程中的 TRUE(即 1);
msg
变量的 switch
语句默认为 return DefWindowProc() 而不是 FALSE;
- WM_CLOSE 未指定处理(我猜对话框对某些事件有默认处理)。
_
结果,出现了一个奇怪的行为,其中名为 Confirm 的 MessageBox 失去了焦点 - 即我无法单击 OK 和 Cancel 按钮。
问题:我的假设是否正确 Visual Studio 生成的模板代码比教程中的代码更正确,这似乎并不正确我值得信赖吗?如果是,我忘记了什么吗?我的代码有什么问题,为什么我不能点击 Messagebox 按钮?
我的最终代码如下:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#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()
。这就是 MessageBox 不起作用的原因,正如 Hans Passant 在评论中指出的那样。
VS生成的WndProc()
函数的作用是为主应用程序window处理消息,顾名思义。还有另一个函数 About()
,它处理“关于”对话框的消息。
对话框程序的 return 类型是 INT_PTR
,这是对 BOOL
的改进,因为它通过在 64 位环境中使用不同的大小来解决平台差异,避免可移植性问题。
switch
块不需要 default
子句:
Unlike a window procedure, a dialog box procedure never calls the
DefWindowProc function. Instead, it returns TRUE if it processes a
message or FALSE if it does not.
(Dialog Box Programming Considerations - MSDN)
- 对话框默认处理事件:
The (DialogBox) function (...) starts its own message loop to retrieve
and dispatch messages for the dialog box.
(DialogBox function - MSDN)
无需像我一样处理 WM_DESTROY
- 甚至 WM_DESTROY
。事实上,这样做可能会导致问题 .
我正在阅读一篇关于如何在 Visual C++ 中创建基于对话框的 GUI 应用程序的非常古老的教程(source - 葡萄牙语)。基于我对 WinAPI 编程的薄弱了解,我决定修改建议的代码主要是为了实现两件事:
1) 与 Unicode 编程标准一致(例如使用 wWinMain
和 MessageBoxW
而不是 WinMain
和 MessageBox/MessageBoxA
).这样的"standard"好像到处都是强制执行的。示例:this question (comments)
2) 创建非空 Win32 项目 时与 Visual Studio 提供的模型一致。我这样做并注意到:
- "About" 对话框的回调函数类型为
INT_PTR
而不是BOOL
; WndProc
函数 returns 0,而不是教程中的 TRUE(即 1);msg
变量的switch
语句默认为 return DefWindowProc() 而不是 FALSE;- WM_CLOSE 未指定处理(我猜对话框对某些事件有默认处理)。
_
结果,出现了一个奇怪的行为,其中名为 Confirm 的 MessageBox 失去了焦点 - 即我无法单击 OK 和 Cancel 按钮。
问题:我的假设是否正确 Visual Studio 生成的模板代码比教程中的代码更正确,这似乎并不正确我值得信赖吗?如果是,我忘记了什么吗?我的代码有什么问题,为什么我不能点击 Messagebox 按钮?
我的最终代码如下:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#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()
。这就是 MessageBox 不起作用的原因,正如 Hans Passant 在评论中指出的那样。VS生成的
WndProc()
函数的作用是为主应用程序window处理消息,顾名思义。还有另一个函数About()
,它处理“关于”对话框的消息。对话框程序的 return 类型是
INT_PTR
,这是对BOOL
的改进,因为它通过在 64 位环境中使用不同的大小来解决平台差异,避免可移植性问题。switch
块不需要default
子句:
Unlike a window procedure, a dialog box procedure never calls the DefWindowProc function. Instead, it returns TRUE if it processes a message or FALSE if it does not.
(Dialog Box Programming Considerations - MSDN)
- 对话框默认处理事件:
The (DialogBox) function (...) starts its own message loop to retrieve and dispatch messages for the dialog box.
(DialogBox function - MSDN)
无需像我一样处理 WM_DESTROY
- 甚至 WM_DESTROY
。事实上,这样做可能会导致问题