Win32对话框窗口过程设为类成员函数时CreateDialog类型报错如何解决
问题原因
你遇到的编译错误是因为非静态类成员函数的签名和Win32回调要求的签名不匹配:非静态成员函数会隐式携带this指针作为第一个参数,所以编译器会认为它的原型和全局回调函数DLGPROC的原型不一致,强制转换也无法正常运行。
你已经实现了静态包装器WinProcWraper,只要调整调用逻辑即可,不需要做无意义的强转。
修正步骤
替换CreateDialog为CreateDialogParam,传入类实例指针
你需要把类对象的this指针作为自定义参数传给对话框,这样静态包装器才能拿到实例地址,调用普通成员函数的窗口过程。
2. ## 调整静态包装器的逻辑适配对话框消息
普通窗口第一个消息是WM_NCCREATE,但模态/非模态对话框的初始化消息是WM_INITDIALOG,自定义参数存在该消息的lParam中,需要调整存储this指针的逻辑。
3. ## 替换SetWindowLong/GetWindowLong为Ptr版本适配64位系统
原代码用long存指针在64位环境下会截断地址,改用指针安全的API兼容性更好。
修正后代码
H文件不需要修改
CPP文件修改部分:
// 调整静态包装器逻辑适配对话框 LRESULT CALLBACK MyClass::WinProcWraper(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { // 对话框初始化消息,拿到传入的类实例指针 if (WM_INITDIALOG == message) { // 用SetWindowLongPtr存指针,兼容64位 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)lParam); return TRUE; } // 从userdata拿实例指针,调用成员窗口过程 MyClass* pThis = (MyClass*)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (pThis) { return pThis->WinProc(hWnd, message, wParam, lParam); } // 没拿到实例前走默认对话框过程 return DefWindowProc(hWnd, message, wParam, lParam); } int APIENTRY MyClass::WinMainProc(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; this->hInstance = hInstance; this->MyClassRegisterClass(hInstance); // 改用CreateDialogParam,最后一个参数传入当前类实例的this指针 HWND hWnd = CreateDialogParam( hInstance, MAKEINTRESOURCE(IDD_MAIN_DIALOG), 0, (DLGPROC)MyClass::WinProcWraper, // 传静态包装器,不是非静态的WinProc (LPARAM)this // 传入当前实例指针给WM_INITDIALOG ); this->hWnd = hWnd; ShowWindow(hWnd,nCmdShow); UpdateWindow(hWnd); while (GetMessage(&msg, NULL, 0, 0)) { if (!IsWindow(hWnd) || !IsDialogMessage(hWnd,&msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return static_cast<int>(msg.wParam); }
内容的提问来源于stack exchange,提问作者TylerD007
相关产品推荐
相关产品推荐

