如何将WinMain中的数据(如缓冲区指针)传递给WndProc?
WinMain与WndProc间的数据传递方案(避免全局变量)
一、利用窗口创建参数+句柄映射传递指针
在调用CreateWindowEx创建窗口时,最后一个参数lpParam可以直接传入你的缓冲区指针:
// WinMain中创建窗口 char* buffer = ...; // 你的缓冲区指针 HWND hWnd = CreateWindowEx( 0, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, (LPVOID)buffer // 将缓冲区指针传入窗口创建参数 );
之后在WinMain里定义一个静态的句柄-指针映射表,把当前窗口句柄和缓冲区指针绑定:
// WinMain内的静态映射,仅当前编译单元可见 static std::map<HWND, char*> hWndToBuffer; // 窗口创建完成后添加映射 hWndToBuffer[hWnd] = buffer;
接下来在WndProc中处理WM_PAINT时,直接通过窗口句柄从映射表中取出指针:
case WM_PAINT: { char* buffer = hWndToBuffer[hwnd]; PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // 这里使用buffer执行绘制逻辑 EndPaint(hwnd, &ps); } break;
这种方式比全局变量更可控,只会关联当前窗口的指针,不会污染全局命名空间。
二、WinMain消息循环拦截WM_PAINT的注意事项
Windows处理WM_PAINT有两种方式:
- 常规场景下,系统会将WM_PAINT投递到消息队列,可被WinMain的
GetMessage捕获; - 调用
UpdateWindow时,系统会直接发送WM_PAINT给WndProc,跳过消息队列,这种情况下WinMain的消息循环无法拦截。
如果要在WinMain中处理队列中的WM_PAINT,可以这么写:
MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { if (msg.message == WM_PAINT && msg.hwnd == hWnd) { // 直接用WinMain中的buffer处理绘制 PAINTSTRUCT ps; HDC hdc = BeginPaint(msg.hwnd, &ps); // 示例:绘制缓冲区内容 TextOut(hdc, 10, 10, buffer, strlen(buffer)); EndPaint(msg.hwnd, &ps); // 无需再派发给WndProc,跳过后续步骤 continue; } TranslateMessage(&msg); DispatchMessage(&msg); }
但要记住:直接发送的WM_PAINT无法被这种方式拦截,必须确保WndProc也能拿到缓冲区指针处理这类场景。
三、退而求其次:静态全局变量
如果上述方案都不适用,静态全局变量是最简便的选择——它仅在当前编译单元可见,不会影响其他模块:
// 在当前.cpp文件中定义静态全局指针 static char* g_pBuffer = nullptr; // WinMain中初始化指针 g_pBuffer = ...; // WndProc中直接使用 case WM_PAINT: if (g_pBuffer) { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // 使用g_pBuffer执行绘制 EndPaint(hwnd, &ps); } break;
缺点是如果创建多个窗口,需要额外处理指针与窗口的绑定逻辑。
内容的提问来源于stack exchange,提问作者Dosev
相关产品推荐
相关产品推荐

