c++ - 使用类成员作为 WNDPROC/DLGPROC 有或没有全局

标签 c++ winapi callback wrapper wndproc

我将继续对此进行总结,我如何使用作为类成员的对话过程?我正在创建一个窗口包装器类,但是 CreateDialogParam需要一个全局对话过程,所以我尝试了这个解决方法:

我已经对这个主题做了一些搜索。我正在制作 Dialog我正在子类化的类 CMainWnd然后实例化它。在Dialog我有一个定义为 INT_PTR CALLBACK Dialog::cb_proc(HWND,UINT,WPARAM,LPARAM) 的成员函数.现在,我知道windows必须有一个全局函数作为回调过程。

所以我做了一个std::map<HWND,Dialog*> DlgProcs映射以将对话框窗口句柄与其 Dialog 类指针相关联。

还有一个 INT_PTR CALLBACK DlgMainProc(HWND,UINT,WPARAM,LPARAM)所以我可以把它传递给CreateDialogParam() .在 DlgMainProc(...) 的正文中我在 map 上搜索使用 hWnd参数来查找 Dialog*并返回其 cb_proc(..)成员(member)。

我的问题是没有任何消息得到处理,这是因为我的 Dialog 中的成员程序类永远不会被调用。即使当我放一个 MessageBox()DlgMainProcif (DlgProcs.find(hWnd) != DlgProcs.end()) { 里面语句,消息框显示,一遍又一遍,直到我不得不从 Visual Studio 2008 中止程序。这告诉我它正在寻找 hWnd在我的 map 上。奇怪的是,如果我把它放在 else 中,它也会这样做之后的声明,矛盾地告诉我它没有找到 hWnd在 map 上。

如果我在 cb_proc 中放置一个消息框成员函数它根本不会显示。但在此期间,我从未遇到任何编译器、链接器或运行时错误。当我从中删除消息框时(不必中止程序,这只是为了调试目的)程序运行但没有消息得到处理,X 按钮不会关闭程序,按钮点击什么都不做。


这是 PasteBin 代码:http://pastebin.com/GsGUBpZU 顺便说一句,我对此进行子类化没有问题,我的窗口创建得很好,只是没有处理任何消息,cb_proc只是永远不会被调用。

编辑:这是代码的相关部分

map<HWND,Dialog*> g_DlgProcs;

INT_PTR CALLBACK g_MainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
        if (g_DlgProcs.find(hWnd) != g_DlgProcs.end()) {
                Alert("blah"); // Gets executed repeatedly
                return g_DlgProcs[hWnd]->cb_proc(hWnd, msg, wParam, lParam);
        } else {
                Alert("blah"); // Removing the above alert, this gets
                               // executed repeatedly, erm, as well.. O.o strange
                return FALSE;
        }
}

Dialog::Dialog(int id, HWND parent /* = HWND_DESKTOP */) {
        _id = id;
        _parent = parent;

        // Tried this before CreateDialogParam
        g_DlgProcs.insert(make_pair(_handle, this));

        _handle = CreateDialogParam(
                (HINSTANCE)GetModuleHandle(NULL),
                MAKEINTRESOURCE(id), _parent,
                (DLGPROC)g_MainDlgProc, NULL
        );

        // Then tried it after CreateDialogParam
        g_DlgProcs.insert(make_pair(_handle, this));
}

INT_PTR CALLBACK Dialog::cb_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
        Alert("blah"); // Never gets executed

        bool handled = true;

        switch (msg)
        {
        case WM_INITDIALOG:
                OnInitialize();
                break;
        case WM_COMMAND:
                if (HIWORD(wParam) == 0 || HIWORD(wParam) == 1) {
                        OnMenuCommand((HIWORD(wParam) == 1), (int)LOWORD(wParam));
                } else {
                        OnCtrlCommand((int)HIWORD(wParam), (int)LOWORD(wParam), (HWND)lParam);
                }
                break;
        case WM_NOTIFY:
                {
                        LPNMHDR head = (LPNMHDR)lParam;
                        OnNotification(head->code, head->idFrom, head->hwndFrom);
                }
                break;
        case WM_CLOSE:
                OnClose(); // DestroyWindow(_handle)
                break;
        case WM_DESTROY:
                OnDestroy(); // PostQuitMessage(0)
        default:
                handled = ProcessMsg(msg, wParam, lParam);
        }

        // Convert bool to Windows BOOL enum
        return ((handled == true) ? TRUE : FALSE);
}

有人知道为什么它永远不会被调用吗?或者可能只是指导我使用另一种方法将成员函数用作 DLGPROC?

最佳答案

标准解决方案是将您的this 指针作为最后一个参数传递给Create,DialogParam,将其存储在您的中的DWLP_USER 中>WM_INITDIALOG 处理程序,然后从 DWLP_USER 中检索它。基本上你使用 DWLP_USER 作为你的 map 。

关于c++ - 使用类成员作为 WNDPROC/DLGPROC 有或没有全局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12582511/

相关文章:

c++ - 如何在运行时检查 Win32 句柄的 "type"

http - Webhooks 是一种风格/模式还是一种规范?

javascript - 如何将现有回调 API 转换为 Promise?

c++ - 16 位 float 和 GL_HALF_FLOAT

c++ - 当存在两个用户定义的复制构造函数时,有没有办法执行复制构造函数?

c - 如何用C在Windows中分别获取用户和系统环境变量

objective-c - 指针在 FSEventStream 回调中丢失(ObjC 和 ARC)

c++ - 为什么我用 WriteFile 写入 0 个字节?

c++ - 如何在C++中将二进制文件转换为WAV文件

c++ - 从另一个线程关闭 WINAPI 中的重定向控制台