用一个变态的方法解决winform闪烁问题
2010-09-14 17:28
681 查看
很久没有写东西了,希望各位海涵。。
一、问题
Winform的程序其实在绘制机制上有较大的性能问题,这个问题本身是由于绘制过程是通过system.drawing里面大量使用pvinvke调用api解决的,由于.net的速度问题这个瓶颈很难解决。下面一个图片显示了为什么在一个mdi窗口显示一个模态窗口会闪烁的问题,同理对于mdi子窗口切换也是一样的。
1. 在窗口显示出来之前(shown事件),这些控件的句柄已经创建,但.net运行时还来不及处理paint事件。这个效果大致是这样的:
![](http://hi.csdn.net/attachment/201009/14/0_1284453595Lo8O.gif)
而原始Form是这样的:
![](http://hi.csdn.net/attachment/201009/14/0_1284453671ZAf0.gif)
所以一般只要窗口背景显示颜色不是默认的Control(button face)背景色,这个闪烁都是无法避免的,即使你用Double Buffer也没用。这个问题在.net 1.1里不是很突出,但到了2.0及以后的版本非常明细。
2. 一般大多控件都是在Shown事件以后才逐步的收到绘制消息绘制更新。不再强调.net的绘制速度问题,但大家的肉眼都能识别出来。。。。
二、解决
本人这个问题困扰好久,其实本身对程序的影响并不大,但总觉得效果不佳影响整个程序的表现。解决方法是2个
2.1 稍微的改善
在Shown事件里强制刷新下,闪烁会减弱,但不会消失。
2.2 变态的改善
这个可以完全解决闪烁问题,但如果机器稍慢第一次运行可能稍微迟钝。方法是把控件在显示前都隐藏掉。
俺也不想用这么变态的方法,但实际测试结果是只有这种方法才能完全消除闪烁。
强调:使用这种方法请不要设置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秒才出来。
![](http://hi.csdn.net/attachment/201009/14/0_1284456391zEyp.gif)
好多控件都没画出来。。。
解决方法:在Activate事件里加个Refresh
一、问题
Winform的程序其实在绘制机制上有较大的性能问题,这个问题本身是由于绘制过程是通过system.drawing里面大量使用pvinvke调用api解决的,由于.net的速度问题这个瓶颈很难解决。下面一个图片显示了为什么在一个mdi窗口显示一个模态窗口会闪烁的问题,同理对于mdi子窗口切换也是一样的。
1. 在窗口显示出来之前(shown事件),这些控件的句柄已经创建,但.net运行时还来不及处理paint事件。这个效果大致是这样的:
![](http://hi.csdn.net/attachment/201009/14/0_1284453595Lo8O.gif)
而原始Form是这样的:
![](http://hi.csdn.net/attachment/201009/14/0_1284453671ZAf0.gif)
所以一般只要窗口背景显示颜色不是默认的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秒才出来。
![](http://hi.csdn.net/attachment/201009/14/0_1284456391zEyp.gif)
好多控件都没画出来。。。
解决方法:在Activate事件里加个Refresh
private void Form3_Activated(object sender, EventArgs e) { this.Refresh(); }
相关文章推荐
- 使用VS2005 CTP July调试WinForm的一个问题,解决方法与各位分享。
- [转]winform 窗口闪烁问题解决方法
- C++库研究笔记——使用函数模板还是类模板?+ 一个类型重复问题的两种解决方法
- 刚进入win7系统就提示检测到一个硬盘问题的解决方法
- Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法
- DataGuard - 一个关于Physical Standby中recover问题的解决方法
- 【技术文档】开发一个人力资源管理系统遇到的问题及解决的方法
- “无法更新EntitySet“*****”,因为它有一个DefiningQuery,而<ModificationFunctionMapping>元素中没有支持当前操作的<InsertFunction>元素”问题的解决方法
- WindowsMobile(Winform)开发中的数据存储(解决在不同的Form中要调用对方的方法或者使用对方的数据问题)
- 在winform中嵌入Flash(swf)的方法及常见问题的解决
- 参数一个以上的问题解决方法
- Cocos2dx编译到android遇到的一个坑爹问题以及解决方法
- 一天安装一个mysql,不是吓唬你,哈哈,mysql问题解决方法1067 can not connect to localhost (带MySql常用错误代码表)
- (超好)xp系统遇到问题解决方法总结(提供了一个解决问题库)
- SQL Server 2008 能用机器名连接,不能用IP地址连接问题 的一个解决方法
- spring 中配置log4j输出日志常见的一个小问题解决方法
- 在MSYS下用MingW GCC编译libgmp的一个小问题及解决方法
- 【Android问题】Android导入一个工程时提示 Invalid project description的解决方法
- 关于一个字符出现1次或者n次输出问题的解决方法
- 执行SQL语句时出现问题操作必须使用一个可更新的查询错误的解决方法