[MFC] 界面闪烁若干种解决办法

来源:互联网 发布:mac显示桌面快捷方式 编辑:程序博客网 时间:2024/05/25 16:40

界面闪烁原因,可以参考这里
总结了工作中使用过的如下几种方法 ,具体原理就不说了,如果有相应的UI开发经验 应该很容易懂,不懂的话根据我提供的关键字自己搜索一下具体原理。

1、双缓冲
这个是最基本的  不详说了 可自己搜索相关信息

2、OnEraseBkgnd { return TRUE; }
这一种也没什么好说的

3、对窗口设置WS_CLIPCHILDREN和WS_CLIPSIBLINGS风格 
至于为什么可以解决闪烁 可MSDN上查看这两种属性的具体信息

4、重绘窗口时 尽量用InvalidateRect 不要用Invalidate

 ----------------以上几种应该是大部分人都接触过的 以下几种方法可能稍微用的少一些 ----------------

5、SetRedraw(FALSE)
应用举例:如果在短时间内 对一个CListCtrl有大量的增删改操作,
可在操作前调用一次m_ListCtrl.SetRedraw(FALSE) 避免在操作过程中列表框刷新
操作结束后 调用一次m_ListCtrl.SetRedraw(TRUE) 恢复刷新
千万注意 有一个类似的API LockWindowUpdate 该API和SetRedraw有区别 不但不能解决闪烁 反而引起闪烁。原因可以参考http://bbs.csdn.net/topics/310205465。调用这个API后,在窗口锁定期间会堆积重绘消息,当解锁时再分发堆积的消息,这样反而会造成窗口闪烁。

6、BeginDeferWindowPos(),DeferWindowPos(),EndDeferWindowPos()

应用举例:在主窗口的OnSize中 调整所有子窗口的新位置 不要使用MoveWindow或SetWindowPos移动子窗口 否则闪烁

7、resize主窗口时,以虚框代替重绘,即“not  repaint  while  draging”
场景:resize主窗口时 如果在OnSize中实时更新子窗口的UI布局 界面会有闪烁 为了避免拖动中频繁闪烁 可以在拖动中不实际更新主窗口的大小
而以一个虚拟的矩形框代表主窗口的新位置(很多软件都有这个效果)
具体技术说明 参考API:SystemParametersInfo
代码如下:

    void CMyDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)    {            // 1,查询当前系统“拖动显示窗口内容”设置        SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bDragFullWindow, NULL);               // 2,如果需要修改设置,则在每次进入CDialog::OnNcLButtonDown默认处理之前修改        if(m_bDragFullWindow)             SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, FALSE, NULL, NULL);        // 3,默认处理,系统会自动绘制虚框        CDialog::OnNcLButtonDown(nHitTest, point);                // 4,默认处理完毕后,还原系统设置        if(m_bDragFullWindow)             SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, NULL, NULL);    }
1 0