第二个是双缓冲技术,这是个很有用的技术,也是用于防止闪烁的,但不是普通窗口更新原因引起的闪烁,而是由于大的绘图量引起的,通常,您的专业软件的某种绘图需要调用的方法有时需要重复多个步骤,完成所有已经超过了刷新一次(有刷新频率决定)的时间,这样,您的所有更新可能不在同一次刷新内绘制完毕,就会出现分批绘制在屏幕上的情况(不是一瞬间同时显示),为了防止这种现象的发生我们才需要用到双缓冲,因此,这种分批绘制的问题实际上并不是通常意义的闪烁问题.
双缓冲的原理很简单,就是在内存中先建立一个位图,把您需要绘制到设备的内容一步步先绘制到内存中这个位图上, 由于此时不在设备上绘制,所以与显示无关.等到内存中完成了所有步骤变可以将其一次性绘制到设备上显示.这种做法第一比较耗内存,第二比较耗时间,因为要绘制2次,虽然第二次是很快的,达到的效果就是没有让用户觉得您是在一步步变计算编绘制,而是一次性绘制.如果计算量大,窗口还可能瞬间无效变白.
下面贴出一段代码来看看双缓冲技术的实现.


if (this.bmp == null)
return;
using (Bitmap memBitmap = new Bitmap(dstRect.Width, dstRect.Height))
{
using (Graphics gxOff = Graphics.FromImage(memBitmap))
{
gxOff.Clear(this.BackColor);图像显示应用程序画面闪烁
gxOff.PageUnit = GraphicsUnit.Pixel;
try{gxOff.DrawImage(bitmap, dstRect, srcRect, gxOff.PageUnit);}catch{}
//在内存中实现您的绘图逻辑,在gxOff上面绘制

using (Graphics g = this.CreateGraphics())
{
g.DrawImage(memBitmap, 0, 0);
}

}

}




其中memBitmap是内存中开辟的位图,完成这次绘制就要被回收,gxOff是从这个位图包装的虚拟设备,g则是窗体的真实设备.第三个拾年个就是将您在内存中画完的内容一次性画到屏幕上.



至于什么invalidate(false)之类纯属胡扯,那是控制是否刷新窗体子控件的.


下面来谈谈如何避免常规情况下的刷新.
很多人有这种习惯首先在Form_Paint或者OnPiant函数中调用自己的绘图函数,假设为Display()图像显示应用程序画面闪烁
然后在需要刷新的事件处理,例如Form_Resize内部,或者滚动条滚动的事件处理内,调用this.Invalidate()之类的.这就是引起闪烁的根源,首先,Form一旦Resize不用您调用窗体自己会强制刷新一次,除非您有区别与OnPaint调用的处理,例如,滚动条长度的重设,否则不需处理这个事件.然后是滚动条滚动时候,最好也不要调用Invalidate()而是直接调用您的绘图函数,Display(),这样您的窗口就不会闪烁了