browser icon
You are using an insecure version of your web browser. Please update your browser!
Using an outdated browser makes your computer unsafe. For a safer, faster, more enjoyable user experience, please update your browser today or try a newer browser.

解决窗口闪烁的常用方法

Posted by on 2006 年 02 月 10 日

你可以任意转载本文,但请在转载后的文章中注明作者和原始链接。
媒体约稿请联系 titilima_AT_163.com(把“_AT_”换成“@”)。

下面只是简要介绍了防止窗口闪烁的一般方法,也是我最常用到的。

  • 窗口的移动或改变大小是要导致窗口重绘的,所以如果客户区上存在两个子窗口A和B,且A和B都需要移动或改变大小(参考分隔条的情况),那么势必会导致客户区重绘两次。当然MoveWindow和SetWindowPos貌似都提供了处理窗口但不重绘的参数,不过我还是建议使用DeferWindowPos。
  • 在DC上画图,如果绘制的内容过多,那么将会导致DC的频繁闪烁。这个问题的解决方法是为目标DC创建一块兼容DC,然后在兼容DC上绘制,待绘制完毕后再将所有内容贴至原始DC上。这种方法也就是常说的“双缓冲”。
  • 当然,有的时候即使采用了双缓冲,仍然会看到明显的闪烁(比如在定时器中调用InvalidateRect刷新客户区)。这是由于在窗口重绘的时候,首先要用窗口的画刷填充整个窗口DC,然后再执行WM_PAINT中的内容。根本的解决办法是将窗口类的画刷设为NULL_BRUSH,这样就看不到闪烁了。
  • 此外,还可以通过发送WM_SETREDRAW消息、处理WM_ERASEBKGND消息、用InvalidateRect进行局部刷新、去掉窗口类的CS_HREDRAW/CS_VREDRAW样式、为窗口添加WS_CLIPCHILDREN/WS_CLIPSIBLINGS样式的方法来解决某些特定的闪烁问题。这些方法我没有尝试过,因为它们只是在闪烁的根本原因上打了擦边球,没有触及本质。

当然可能还存在更好的办法,欢迎大家一起讨论。

订阅本站

4 Comments

  • At 2006.02.22 09:42, 天神 said:

    现在的人都变得好快,让人都摸索不着。

    • At 2009.10.05 20:06, joe said:

      马老师,能否提供第三种例子呢

      • At 2009.10.06 00:52, 李马 said:

        [quote=joe]马老师,能否提供第三种例子呢[/quote]July 或 PDL 的源代码中有相关的使用,你可以参考一下。

        • At 2012.05.03 09:53, tjm_1990 said:
          (Required)
          (Required, will not be published)