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

时间:2015-06-09 00:01:50

标签: c++ c visual-studio user-interface winapi

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

1)与Unicode编程标准保持一致(例如,使用wWinMainMessageBoxW代替WinMainMessageBox/MessageBoxA。这种“标准”似乎在各地都得到了强制执行。示例:this question (comments)

2)在创建非空 Win32项目时,Visual Studio提供的模型的一致性。我做到了,注意到了:

  • “关于”对话框的回调函数类型为INT_PTR,而不是BOOL;
  • WndProc函数返回0,而不是TRUE(即1),如教程中所示;
  • switch变量的msg语句默认返回DefWindowProc()而不是FALSE;
  • 未指定WM_CLOSE处理(我猜对话框对某些事件有默认处理)。

_
因此,有一种奇怪的行为,其中名为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;
}

1 个答案:

答案 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