您的位置:首页 > 其它

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

2010-09-14 17:28 681 查看
很久没有写东西了,希望各位海涵。。

一、问题

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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐