我正在阅读一篇关于如何在Visual C ++中创建基于对话框的GUI应用程序的非常古老的教程(source - 用葡萄牙语)。基于我对WinAPI编程的微弱知识,我决定修改建议的代码主要是为了实现两件事:
1)与Unicode编程标准保持一致(例如,使用wWinMain
和MessageBoxW
代替WinMain
和MessageBox/MessageBoxA
。这种“标准”似乎在各地都得到了强制执行。示例:this question (comments)
2)在创建非空 Win32项目时,Visual Studio提供的模型的一致性。我做到了,注意到了:
INT_PTR
,而不是BOOL
; WndProc
函数返回0,而不是TRUE(即1),如教程中所示; switch
变量的msg
语句默认返回DefWindowProc()而不是FALSE; _
因此,有一种奇怪的行为,其中名为Confirm的MessageBox失焦 - 即我无法单击“确定”和“取消”按钮。
问题:我是否认为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;
}
答案 0 :(得分:1)
所以,我明白了。 Visual Studio向导创建的代码确实演示了Windows API的正确实现。
注意事项:
对话框程序不应调用DefWindowProc()
。这就是MessageBox无法正常工作的原因,如评论中 Hans Passant 所述。
VS生成的WndProc()
函数的目的是处理主应用程序窗口的消息,顾名思义。还有另一个函数About()
,它处理“关于”对话框的消息。
对话框过程的返回类型为INT_PTR
,这比BOOL
有所改进,因为它通过在64中具有不同的大小来解决平台差异比特环境,避免可移植性问题。
switch
块不需要default
子句:
与窗口过程不同,对话框过程从不调用 DefWindowProc功能。相反,如果它处理a,它返回TRUE 如果没有,则显示消息或FALSE (Dialog Box Programming Considerations - MSDN)
对话框具有事件的默认处理:
(DialogBox)函数(...)启动自己的消息循环来检索 并为对话框发送消息 (DialogBox function - MSDN)
没有必要像我一样处理WM_DESTROY
- 甚至WM_DESTROY
。事实上,这样做可能会导致问题as seen here。