用一个变态的方法解决winform闪烁问题

很久没有写东西了,希望各位海涵。。

 

 

一、问题

Winform的程序其实在绘制机制上有较大的性能问题,这个问题本身是由于绘制过程是通过system.drawing里面大量使用pvinvke调用api解决的,由于.net的速度问题这个瓶颈很难解决。下面一个图片显示了为什么在一个mdi窗口显示一个模态窗口会闪烁的问题,同理对于mdi子窗口切换也是一样的。

 

1. 在窗口显示出来之前(shown事件),这些控件的句柄已经创建,但.net运行时还来不及处理paint事件。这个效果大致是这样的:

 

 

而原始Form是这样的:

 

所以一般只要窗口背景显示颜色不是默认的Control(button face)背景色,这个闪烁都是无法避免的,即使你用Double Buffer也没用。这个问题在.net 1.1里不是很突出,但到了2.0及以后的版本非常明细。

 

2. 一般大多控件都是在Shown事件以后才逐步的收到绘制消息绘制更新。不再强调.net的绘制速度问题,但大家的肉眼都能识别出来。。。。

 

二、解决 

本人这个问题困扰好久,其实本身对程序的影响并不大,但总觉得效果不佳影响整个程序的表现。解决方法是2个

 

2.1 稍微的改善

 

在Shown事件里强制刷新下,闪烁会减弱,但不会消失。

private void Form2_Shown(object sender, EventArgs e) { this.Refresh(); }  

 

2.2 变态的改善

 

这个可以完全解决闪烁问题,但如果机器稍慢第一次运行可能稍微迟钝。方法是把控件在显示前都隐藏掉。

 

namespace WindowsApplication1 { public partial class Form2 : Form { public Form2() { InitializeComponent(); } //在显示之前把控件全部隐藏掉 private void Form2_Load(object sender, EventArgs e) { foreach (Control c in this.Controls) c.Visible = false; } //在显示之后再把控件显示出来 private void Form2_Shown(object sender, EventArgs e) { foreach (Control c in this.Controls) c.Visible = true; } } }

 

俺也不想用这么变态的方法,但实际测试结果是只有这种方法才能完全消除闪烁。

 

强调:使用这种方法请不要设置Form的DoubleBuffer属性=true,否则适得其反。

 

 

三、额外的说明

为什么在Vista下Winform闪烁的问题会好一些?

答:其实是一样的,只是Vista默认的Aero主题有一个渐变的动画过程,这个动画过程可以欺骗用户的眼睛,觉得闪烁少了点。

当然您也可以模拟在xp等其他系统下进行一个淡入淡出的渐变,来改善下。参考http://topic.csdn.net/u/20091228/12/6d39d772-c119-4fbb-be3f-adee12d895bb.html 20楼兄台的帖子。

 

补充:另外一个原因是vista的图形机制和之前版本的Windows有较大的区别。

 

 

MDI切换的闪烁

 

mdi 子窗口 切换时的闪烁问题除了上面的原因外还有一个问题,如果窗口不是最大化的,通过点击窗口标题头切换也会有很明显的闪烁。最明显的例子是,如果你按住鼠标点标题头,不释放鼠标,这个绘制过程要等2-3秒才出来。

 

 

好多控件都没画出来。。。

解决方法:在Activate事件里加个Refresh

 

private void Form3_Activated(object sender, EventArgs e) { this.Refresh(); }

 

 

你可能感兴趣的:(MS.NET技术)