WIN32如何将绘制结果缓存到位图以降低鼠标事件触发的重复绘制开销
实现方案
1. 新增必要变量定义
在全局或窗口类成员中新增缓存脏位标记,用来标识缓存内容是否需要更新:
BOOL g_bCacheDirty = TRUE;初始值设为TRUE,保证程序启动时第一次绘制会生成缓存- 确保你已有的内存DC
in_ghdc和关联的HBITMAP要和窗口客户区尺寸匹配,窗口大小改变时也要同步更新缓存并标记脏位。
2. 界面变更通知触发逻辑
当业务逻辑触发界面内容需要更新时,仅执行两个操作即可:
- 将
g_bCacheDirty设置为TRUE - 调用
InvalidateRect(hWnd, NULL, FALSE);触发窗口重绘,不需要直接调用绘制函数
3. 调整现有绘制函数逻辑
将你现有的CreatePanelDynamic函数逻辑替换为脏位判断逻辑,参考代码如下:
int anistat = 0; BOOL g_bCacheDirty = TRUE; void CreatePanelDynamic(HWND h, HDC hdc, DRAWPANEL DrawFun, int Flag = 0) { RECT rc; GetClientRect(h, &rc); int cx = rc.right - rc.left; int cy = rc.bottom - rc.top; if (PanelID == PrevPanelID) { // 面板ID未变化的场景 if (g_bCacheDirty) { // 仅脏位为TRUE时,才重新绘制内容到缓存DC _CreatePanel(h, in_ghdc, DrawFun); g_bCacheDirty = FALSE; } // 所有场景最终都直接将缓存内容复制到当前显示DC BitBlt(hdc, 0, 0, cx, cy, in_ghdc, 0, 0, SRCCOPY); anistat = 0; dystat = 0; } else // 切换面板需要执行动画的场景 { if (Flag == 0) { CreatePanelAnimation(h, hdc, DrawFun); dystat = 1; } if (Flag == 1) { _CreatePanel(h, hdc, DrawFun); dystat = 1; } // 切换面板完成后,将新的面板内容同步到缓存 BitBlt(in_ghdc, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY); g_bCacheDirty = FALSE; PrevPanelID = PanelID; anistat = 0; } }
4. 鼠标事件处理逻辑调整
鼠标hover、离开事件触发时,不需要调用任何绘制函数,也不需要修改脏位,仅调用InvalidateRect(h, NULL, FALSE);触发重绘即可,此时重绘流程会直接走BitBlt复制缓存的逻辑,不会触发重绘计算,资源占用极低。
注意事项
- 如果窗口支持调整大小,需要在
WM_SIZE消息回调中重新创建匹配新尺寸的in_ghdc和关联HBITMAP,同时将g_bCacheDirty设为TRUE触发缓存更新 - 确保
in_ghdc是全局或和窗口绑定的长期有效对象,程序退出时记得释放关联的HBITMAP和HDC,避免GDI资源泄漏 - 鼠标事件中不需要调用
UpdateWindow强制同步重绘,仅调用InvalidateRect即可满足需求
内容的提问来源于stack exchange,提问作者末影小末EnderMo
相关产品推荐
相关产品推荐

