通常的windows 复杂的界面须要使用多层窗口并且要用贴图来美化,因此不可避免在窗口移动或者改变大小的时候出现闪烁。windows
先来谈谈闪烁产生的缘由函数
缘由一:
若是熟悉显卡原理的话,调用GDI函数向屏幕输出的时候并非马上就显示在屏幕
上只是写到了显存里,而显卡每隔一段时间把显存的内容输出到屏幕上,这就是刷新周期。spa
通常显卡的刷新周期是 1/80秒左右,具体数字能够本身设置的。内存
这样问题就来了,通常画图都是先画背景色,而后再把内容画上去,若是这两次操做不在同一个
刷新周期内完成,那么给人的视觉感觉就是,先看到只有背景色的图像,而后看到画上内容的图像,
这样就会感受闪烁了。原理
解决方法:尽可能快的输出图像,使输出在一个刷新周期内完成,若是输出内容不少比较慢,那么采用
内存缓冲的方法,先把要输出的内容在内存准备好,而后一次输出到显存。要知道一次API调用通常能够
在一个刷新周期内完成。方法
对于GDI,用建立内存DC的方法就能够了移动
缘由二:时间
复杂的界面有多层窗口组成,当windows在窗口改变大小的时候是先重画父窗口,而后重画子窗口,子父
窗口重画的过程通常没法在一个刷新周期内完成,因此会呈现闪烁。co
咱们知道父窗口上被子窗口挡住的部分其实不必重画的数字
解决方法:给窗口加个风格 WS_CLIPCHILDREN ,这样父窗口上被子窗口挡住的部分就不会重画了。
若是同级窗口之间有重叠,那么须要再加上 WS_CLIPSIBLINGS 风格
缘由三:
有时候须要在窗口上使用一些控件,好比IE,当你的窗口改变大小的时候IE会闪烁,即便你有了WS_CLIPCHILDREN
也没用。缘由在于窗口的类风格有CS_HREDRAW 或者 CS_VREDRAW,这两个风格表示窗口在宽度或者高度变化的时候
重画,可是这样就会引发IE闪烁
解决方法:注册窗口类的时候不要使用这两个风格,若是窗口须要在改变大小的时候重画,那么能够在WM_SIZE的时候
调用RedrawWindow。
缘由四:
界面上窗口不少,并且改变大小时不少窗口都要移动和改变大小,若是使用MoveWindow或者SetWindowPos两个API来
改变窗口的大小和位置,因为他们是等待窗口重画完成后才返回,因此过程很慢,这样视觉效果就可能会闪烁。
解决方法:
使用如下API来处理窗口移动,BeginDeferWindowPos, DeferWindowPos,EndDeferWindowPos
先调用 BeginDeferWindowPos 设定须要移动的窗口的个数
使用DeferWindowPos,来移动窗口,这个API并不真的形成窗口移动
EndDeferWindowPos 一次性完成全部窗口的大小和位置的改变。
有个地方要特别注意,要仔细计算清楚要移动多少个窗口,BeginDeferWindowPos设定的个数必定要和实际的个数一致,不然在Win9x下,若是实际移动的窗口数多于调用BeginDeferWindowPos时设定的个数,可能会形成系统崩溃。在Windows NT系列下不会有这样的问题。