如何在Win32 API(C++)中获取WM_PAINT脏矩形的客户区坐标?
解决Win32中获取客户区绝对坐标脏区域的问题
要获取客户区坐标系下的脏区域(更新区域)坐标,不能依赖BeginPaint返回的PAINTSTRUCT——因为BeginPaint会将DC的裁剪区原点偏移到脏区域的左上角,导致rcPaint的left/top始终为0。正确的做法是在调用BeginPaint之前,通过GetUpdateRgn获取原始更新区域:
核心实现步骤
- 调用
GetUpdateRgn获取窗口当前的更新区域,该区域的坐标基于客户区绝对坐标系。 - 通过
GetRgnBox将区域转换为包围矩形(如果是多块不连续脏区域,会返回整体的边界框;若需处理每块独立区域,可使用EnumRgn枚举)。 - 后续再调用
BeginPaint/EndPaint完成标准绘制流程,避免窗口一直处于需要重绘的状态。
代码示例
case WM_PAINT: { // 先获取原始更新区域(客户区绝对坐标) HRGN hUpdateRgn = CreateRectRgn(0, 0, 0, 0); int rgnResult = GetUpdateRgn(hwnd, hUpdateRgn, FALSE); // FALSE:不清除更新区域 if (rgnResult != ERROR && rgnResult != NULLREGION) { RECT dirtyClientRect; GetRgnBox(hUpdateRgn, &dirtyClientRect); // 转换为回调所需的参数 int x = dirtyClientRect.left; int y = dirtyClientRect.top; unsigned int width = static_cast<unsigned int>(dirtyClientRect.right - dirtyClientRect.left); unsigned int height = static_cast<unsigned int>(dirtyClientRect.bottom - dirtyClientRect.top); // 这里添加获取像素数据的逻辑(比如通过GetDIBits从DC读取) void* pixelBuffer = ...; std::size_t bufferSize = ...; // 调用你的重绘回调 paint_callback(x, y, width, height, pixelBuffer, bufferSize); } DeleteObject(hUpdateRgn); // 完成标准WM_PAINT流程,清除更新标记 PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // 这里可保留必要的默认绘制逻辑(如果需要) EndPaint(hwnd, &ps); return 0; }
处理多块不连续脏区域
如果窗口的脏区域是多个独立矩形,GetRgnBox只能获取整体边界框。若需要针对每块区域单独调用回调,可使用EnumRgn枚举区域内的所有矩形:
// 枚举回调函数 int CALLBACK EnumRgnProc(LPRECT lpRect, LPARAM lParam) { auto callback = reinterpret_cast<paint_callback_t*>(lParam); int x = lpRect->left; int y = lpRect->top; unsigned int w = static_cast<unsigned int>(lpRect->right - lpRect->left); unsigned int h = static_cast<unsigned int>(lpRect->bottom - lpRect->top); // 同样需获取对应区域的像素数据后调用回调 void* pixels = ...; std::size_t size = ...; (*callback)(x, y, w, h, pixels, size); return TRUE; // 继续枚举 } // 在WM_PAINT中替换GetRgnBox的部分: EnumRgn(hdc, hUpdateRgn, EnumRgnProc, reinterpret_cast<LPARAM>(&paint_callback));
关键注意事项
GetUpdateRgn的第三个参数bErase必须设为FALSE,否则会提前清除更新区域,导致BeginPaint无法正确处理。- 使用完创建的区域对象后,必须调用
DeleteObject释放资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Alexandre Deus
相关产品推荐
相关产品推荐

