调用win32 API并给类函数提供回调

Cru*_*mmy 4 c++ winapi

我正在尝试通过将一些现有的win32 UI代码放入类中来清理它.以前我有一个像这样的AppDlgProc函数:

BOOL CALLBACK AppDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { ... }
Run Code Online (Sandbox Code Playgroud)

我这样使用的是:

DialogBoxParam(hInstance, (LPCTSTR)IDD_SETTINGS, 0, AppDlgProc, 0);
Run Code Online (Sandbox Code Playgroud)

现在我将所有这些放在一个SettingsWindow对象中,然后调用settingsWindow-> show()来启动它:

void SettingsWindow::show(HINSTANCE hInstance) {
     DialogBoxParam(hInstance, (LPCTSTR)IDD_SETTINGS, 0, &SettingsWindow::AppDlgProc, 0);
}
Run Code Online (Sandbox Code Playgroud)

我很确定我在这里错误地给出了回调方法.Visual Studio告诉我"Intellisense:类型的参数......与DLGPROC类型的参数不兼容".谷歌搜索似乎告诉我似乎告诉我,我需要另一个论点 - 没有别的办法吗?

作为参考,我的AppDlgProc函数现在看起来像这样:

BOOL CALLBACK SettingsWindow::AppDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {  ... }
Run Code Online (Sandbox Code Playgroud)

Jon*_*ter 8

窗口和对话框程序(以及其他Win32回调函数)需要是静态或全局函数 - 它们不能是非静态类函数.Win32基本上是一个基于C的API,它没有this类函数所需的隐藏指针的概念.

执行此操作的常规方法是将函数声明为static,并在窗口属性中存储指向类实例的指针.例如,

struct SettingsWindow
{
    // static wrapper that manages the "this" pointer
    static INT_PTR CALLBACK AppDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        if (uMsg == WM_INITDIALOG)
            SetProp(hWnd, L"my_class_data", (HANDLE)lParam);
        else
        if (uMsg == WM_NCDESTROY)
            RemoveProp(hWnd, L"my_class_data");

        SettingsWindow* pThis = (SettingsWindow*)GetProp(hWnd, L"my_class_data");
        return pThis ? pThis->AppDlgFunc(hWnd, uMsg, wParam, lParam) : FALSE;
    }

    INT_PTR AppDlgFunc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        // the real dialog procedure goes in here
    }
};


// to show the dialog - pass "this" as the dialog parameter
DialogBoxParam(hInstance, (LPCTSTR)IDD_SETTINGS, 0, SettingsWindow::AppDlgProc,
    (LPARAM)this);
Run Code Online (Sandbox Code Playgroud)

  • `SetProp`文档说你必须在窗口被销毁之前删除窗口属性 - 大概是为了避免内存泄漏,虽然我不知道是否真的如此.无论如何,最好是自己整理一下. (3认同)