C语言实现Windows窗口Resize与重绘同步,解决抖动问题
解决Windows窗口Resize动画时界面元素抖动的问题
方法1:使用内存DC(双缓冲)预绘制元素
在窗口调整尺寸前,先基于新的窗口宽高在内存中完成所有界面元素的绘制,等窗口大小调整完成后,一次性将内存中的绘制结果复制到窗口DC,避免分步绘制导致的抖动。
示例代码:
// 假设在窗口调整尺寸的逻辑中 int new_width = ...; int new_height = ...; // 创建内存DC和兼容位图 HDC hdc = GetDC(window); HDC memDC = CreateCompatibleDC(hdc); HBITMAP memBitmap = CreateCompatibleBitmap(hdc, new_width, new_height); HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap); // 在内存DC中完成绘制(替换为你的实际绘制逻辑,基于new_width/new_height居中元素) RECT memRect = {0, 0, new_width, new_height}; FillRect(memDC, &memRect, (HBRUSH)GetStockObject(WHITE_BRUSH)); DrawCenteredPNG(memDC, new_width, new_height); // 你的居中绘制函数 // 调整窗口大小 bool success = SetWindowPos(window, NULL, xpos, ypos, new_width, new_height, SWP_NOZORDER | SWP_NOCOPYBITS); if (!success) { printf("Failed resizing window. Error code: %lu\n", GetLastError()); } // 将内存DC内容复制到窗口DC BitBlt(hdc, 0, 0, new_width, new_height, memDC, 0, 0, SRCCOPY); // 清理资源 SelectObject(memDC, oldBitmap); DeleteObject(memBitmap); DeleteDC(memDC); ReleaseDC(window, hdc);
方法2:锁定窗口更新直到操作完成
使用LockWindowUpdate暂时禁止窗口重绘,等窗口尺寸调整完成且绘制准备好后,再解锁并强制更新,避免中间状态的显示。
示例代码:
// 锁定窗口,禁止临时重绘 LockWindowUpdate(window); // 调整窗口大小 bool success = SetWindowPos(window, NULL, xpos, ypos, new_window_width, new_window_height, SWP_NOZORDER | SWP_NOCOPYBITS); if (!success) { printf("Failed resizing window. Error code: %lu\n", GetLastError()); LockWindowUpdate(NULL); // 失败必须解锁 return; } // 触发后台重绘 RECT rect = {0, 0, new_window_width, new_window_height}; InvalidateRect(window, &rect, TRUE); UpdateWindow(window); // 强制完成重绘流程 // 解锁窗口,显示最终结果 LockWindowUpdate(NULL);
方法3:调整SetWindowPos参数并同步重绘
给SetWindowPos添加SWP_FRAMECHANGED标志让窗口重新计算非客户区,结合RedrawWindow强制同步重绘,减少延迟:
bool success = SetWindowPos(window, NULL, xpos, ypos, new_window_width, new_window_height, SWP_NOZORDER | SWP_NOCOPYBITS | SWP_FRAMECHANGED); if (!success) { printf("Failed resizing window. Error code: %lu\n", GetLastError()); } // 同步重绘窗口及子控件 RedrawWindow(window, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
注意事项
LockWindowUpdate同一时间只能锁定一个窗口,使用后必须调用LockWindowUpdate(NULL)解锁,否则会影响其他窗口绘制。- 内存DC方式要注意资源的正确释放,避免内存泄漏。
- 若是逐帧扩展的动画,建议每帧都用双缓冲,同时控制帧率(比如定时器或短延时),让resize和重绘节奏匹配。
内容的提问来源于stack exchange,提问作者Andreas Sandberg
相关产品推荐
相关产品推荐

