如何避免CDialog的OnHScroll事件中CStatusBar闪烁
解决CStatusBar水平滚动时的闪烁问题
优化SetWindowPos的重绘行为
原代码调用SetWindowPos时未加入SWP_NOREDRAW标志,导致每次移动状态栏都会触发默认重绘,即使传入redrawWindow=false也无法阻止。修改参数加入该标志,仅在需要时手动触发重绘:m_StatusBar.SetWindowPos(nullptr, 0, rect.bottom - statusBarHeight, rect.Width(), statusBarHeight, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW);给状态栏启用双缓冲
通过添加WS_EX_COMPOSITED扩展样式,让状态栏使用双缓冲绘制,避免闪烁。如果是自定义状态栏类,在PreSubclassWindow中设置:void CMyStatusBar::PreSubclassWindow() { CStatusBar::PreSubclassWindow(); SetWindowLongPtr(m_hWnd, GWL_EXSTYLE, GetWindowLongPtr(m_hWnd, GWL_EXSTYLE) | WS_EX_COMPOSITED); }若未自定义类,可在状态栏创建时指定该扩展样式。
给父对话框添加WS_CLIPCHILDREN样式
该样式让父窗口重绘时跳过子窗口区域,避免父窗口与状态栏的重绘冲突导致闪烁。在对话框OnInitDialog中添加:ModifyStyle(0, WS_CLIPCHILDREN);调整RedrawWindow参数减少擦除操作
修改手动重绘的参数,加入RDW_NOERASE避免不必要的背景擦除,进一步降低闪烁概率:m_StatusBar.RedrawWindow(nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOERASE);减少MoveStatusBar的调用频率
在OnHScroll事件中,仅当滚动位置实际变化时才调用MoveStatusBar,避免频繁触发重绘。例如记录上次滚动位置,对比后再执行移动操作。
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

