为基于对话框的应用程序实现回调函数

Implementing callback function for dialog-based application

我正在阅读一篇关于如何在 Visual C++ 中创建基于对话框的 GUI 应用程序的非常古老的教程(source - 葡萄牙语)。基于我对 WinAPI 编程的薄弱了解,我决定修改建议的代码主要是为了实现两件事:

1) 与 Unicode 编程标准一致(例如使用 wWinMainMessageBoxW 而不是 WinMainMessageBox/MessageBoxA ).这样的"standard"好像到处都是强制执行的。示例:this question (comments)

2) 创建非空 Win32 项目 时与 Visual Studio 提供的模型一致。我这样做并注意到:

_
结果,出现了一个奇怪的行为,其中名为 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。事实上,这样做可能会导致问题 .