Win32将WndProc封装为类成员时实例指针始终为空的问题
问题:封装WndProc为类私有成员时,实例指针始终为nullptr
尝试将WndProc封装为类的私有成员,采用静态WndProc + 成员HandleMsg的方案,已将窗口类的cbWndExtra设为LONG_PTR的大小,计划通过SetWindowLongPtr和GetWindowLongPtr存取类实例指针。但目前pApplication始终为nullptr,程序始终执行DefWindowProc,无法进入自定义消息处理函数。
相关代码
Application.h
private: static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept; LRESULT HandleMsg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept;
Application.cpp
LRESULT CALLBACK Application::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept { Application* pApplication; if (msg == WM_NCCREATE) { pApplication = static_cast<Application*>(reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams); SetWindowLongPtr(hWnd, GWL_USERDATA, reinterpret_cast<LONG_PTR>(pApplication)); } else { pApplication = reinterpret_cast<Application*>(GetWindowLongPtr(hWnd, GWL_USERDATA)); } if (pApplication) return pApplication->HandleMsg(hWnd, msg, wParam, lParam); return DefWindowProc(hWnd, msg, wParam, lParam); }
排查与解决步骤
确认窗口类注册时的
cbWndExtra设置
必须确保注册窗口类时,cbWndExtra被正确设置为sizeof(LONG_PTR):WNDCLASSEX wc = { sizeof(WNDCLASSEX) }; wc.cbWndExtra = sizeof(LONG_PTR); // 关键设置,不能遗漏或设错值 // 其他窗口类属性配置 RegisterClassEx(&wc);若
cbWndExtra未正确设置,SetWindowLongPtr和GetWindowLongPtr操作GWL_USERDATA会失效,导致实例指针无法正常存储。检查窗口创建时的
lpParam参数
调用CreateWindowEx创建窗口时,必须将当前Application实例指针传入lpParam参数,这是WM_NCCREATE中lpCreateParams的来源:CreateWindowEx( 0, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, this // 必须传递当前Application实例指针 );若此处传值错误(比如传
nullptr),WM_NCCREATE中拿到的实例指针自然无效。修正
WM_NCCREATE的返回逻辑WM_NCCREATE的返回值决定窗口是否能成功创建,不能直接跳过默认处理。修改静态WndProc:LRESULT CALLBACK Application::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) noexcept { Application* pApplication; if (msg == WM_NCCREATE) { CREATESTRUCT* pCreate = reinterpret_cast<CREATESTRUCT*>(lParam); pApplication = static_cast<Application*>(pCreate->lpCreateParams); SetWindowLongPtr(hWnd, GWL_USERDATA, reinterpret_cast<LONG_PTR>(pApplication)); // 必须调用默认处理并返回,否则窗口创建可能失败 return DefWindowProc(hWnd, msg, wParam, lParam); } else { pApplication = reinterpret_cast<Application*>(GetWindowLongPtr(hWnd, GWL_USERDATA)); } if (pApplication) return pApplication->HandleMsg(hWnd, msg, wParam, lParam); return DefWindowProc(hWnd, msg, wParam, lParam); }若直接返回
HandleMsg的结果(而HandleMsg未处理WM_NCCREATE),会导致窗口创建失败,后续消息自然拿不到有效指针。
内容的提问来源于stack exchange,提问作者0x54696d
相关产品推荐
相关产品推荐

