C# Winform频繁刷新导致界面闪烁解决方法
C#Winform频繁刷新导致界面闪烁解决方法
对于大多数应用程序,.NET Framework 提供的默认双缓冲将提供最佳效果。默认情况下,标准 Windows 窗体控件是双缓冲的。可以通过两种方法对窗体和所创作的控件启用默认双缓冲。一种方法是将 DoubleBuffered 属性设置为 true,另一种方法是通过调用 SetStyle 方法将 OptimizedDoubleBuffer 标志设置为 true。两种方法都将为窗体或控件启用默认双缓冲并提供无闪烁的图形呈现。建议仅对已为其编写所有呈现代码的自定义控件调用 SetStyle 方法。
在构造函数里加上以下代码:

- 1 this.DoubleBuffered = true;//设置本窗体
- 2 SetStyle(ControlStyles.UserPaint, true);
- 3 SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
- 4 SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲
- 5 //SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
- 6
- 7 //UpdateStyles();

二、C#控件的闪烁问题解决方法总结
最近对代码作了一些优化,试验后效果还可以,但是发现界面会闪烁,具体是TreeView控件会闪烁,语言为C#,IDE为VS2005。在查阅一些资料,使用了一些基本技术后(如开启双缓冲),发现没什么效果。
于是使用Profiler工具,查找出瓶颈在于每次更新完界面的EndUpdate操作(使用这个是为了减少界面更新次数,但这里不理想是因为控件中中的元素很多),猜想大概每次更新,.Net底层都会更新重绘每个图元,所以速度会慢,造成闪烁。但是如果这样,使用双缓冲应该会有较好效果。再看代码,发现可能是更新动作太过频繁,于是降低速度,有所好转,但还是不行。
继续在网上查阅,最终找到一个方案比较合适。原来底层重绘每次会清除画布,然后再全部重新绘制,这才是导致闪烁最主要的原因。于是重载消息发送函数操作,禁掉这条消息。代码如下:
- 1 protected override void WndProc(ref Message m)
- 2 {
- 3 if (m.Msg == 0x0014) // 禁掉清除背景消息
- 4 return;
- 5 base.WndProc(ref m);
- 6 }
成功!
注:双缓冲还是有用的,在更新不是很频繁且控件内含元素不是特别多的时候。一旦元素过多,每次更新时间都比较长,即便使用了双缓冲,仍解决不了闪烁问题。个人认为最终比较理想的方法还是禁掉清除背景消息。
附:一些尝试过但失败的记录
1)使用setStyle
网上有说使用setStyle函数去设置该控件的参数,具体为:
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
这三个选项参数后者是依赖前者的,必须并存,否则无效。并且这个函数本身是protected的,所以首先需要继承某控件再使用。
这个目标是跟前面正确解决方案一致,也是禁止清除背景并开启双缓冲,但需要使用用户绘制选项,而且是全部交由用户绘制。这需要自己实现控件的全部绘制,比较麻烦。所以这个方法不是完全不可行,但是需要额外工作量,不推荐。我也没有使用。
2)使用BeginUpdate和EndUpdate
这一对操作对于需要批量操作更新控件的情景有比较好的效果,比如初始化时批量添加了大量节点。坏处就在于不能即时更新。所以,对于频繁的更新节点并希望立即反映到界面的情况不适用。如果使用并且没有禁掉清除界面消息的话,则控件看起来就会不停的闪烁,而且以白底为主,内容几乎不可见(这个视频繁程度而定)。因为界面更新都在EndUpdate处完成,操作太多导致EndUpdate阻塞时间过长,且清空在先,更新在后,导致界面看起来长时间处于空白状态。
3)使用ControlStyles.EnableNotifyMessage选项
这个选项的作用和正确解决方案也是一致的。使用方法是:
SetStyle(ControlStyles.EnableNotifyMessage, true);
protected override void onNotifyMessage(Message m)
{
// 此处书写过滤消息代码
}
但是实际实验显示无效果,不知是什么原因,没有细究。
三、个人在一个winfrom中测试利用timer控件对要刷新的控件进行定时刷新,可能也能起到作用。
四、C# winform 局部刷新
做winform界面程序时,经常会遇到后台处理占用大量时间的情况,这就会造成界面假死状态。一般解决界面假死有两种方式:要么把占用大量时间的处理方式放入其他线程;要么把界面显示放入其他线程。第一种方式应该比较简单,开单独的线程,处理数据,将处理数据显示到界面就好。但是我们经常需要在主程序运算一些内容,否则可能会改动比较大。因此,这里讲讲第二种方式。
同样是使用多线程,但是c#在其他线程刷新有一点点问题,即不能跨线程操作界面。这可以使用控件的Invoke方法解决:

- 1 private delegate void CrossThread();
- 2 Control control = ....;
- 3 CrossThread cross = delegate()
- 4 {
- 5 control.Refresh();
- 6 };
- 7 control.Invoke(cross);

这样可以让控件在其它线程刷新界面。
再加上开新线程后的通用方法:

- 1 private void InvaliateControl(Control control)
- 2 {
- 3 Thread t = new Thread(
- 4 new ThreadStart(delegate()
- 5 {
- 6 CrossThread cross = delegate()
- 7 {
- 8 control.Refresh();
- 9 };
- 10 control.Invoke(cross);
- 11 }
- 12 ));
- 13 }

这样就可以在任何时候,调用此方法对控件进行刷新,而不将整个界面刷新。如果对于同一个控件,连续多次刷新,可以添加一个成员变量作为标记,以免同一控件连续多次刷新,提升部分性能。
补充:在主线程调用耗时操作用此方法可能会有问题,经过验证调用Invoke函数,其实是在主线程刷新界面。
原文链接:http://blog.csdn.net/weixin_40976261/article/details/78517409
C# Winform频繁刷新导致界面闪烁解决方法的更多相关文章
- winform频繁刷新导致界面闪烁解决方法
转自龙心文 原文 winform频繁刷新导致界面闪烁解决方法 一.通过对窗体和控件使用双缓冲来减少图形闪烁(当绘制图片时出现闪烁时,使用双缓冲) 对于大多数应用程序,.NET Framework 提供 ...
- 【Visual C++】Windows GDI贴图闪烁解决方法
一般的windows 复杂的界面需要使用多层窗口而且要用贴图来美化,所以不可避免在窗口移动或者改变大小的时候出现闪烁. 先来谈谈闪烁产生的原因 原因一:如果熟悉显卡原理的话,调用GDI函数向屏幕输出的 ...
- XCode编译文件过多导致内存吃紧解决方法
XCode编译文件过多导致内存吃紧解决方法 /Users/~~/Library/Developer/Xcode/DerivedData 1) 然后 找到编译文件 删除 就好了哦 快去试试看吧
- 多线程访问winform控件出现异常的解决方法
一. 多线程访问winform控件出现异常的解决方法 1. 问题描述<1> 如果创建某控件的线程之外的其他线程试图调用该控件,则会引发一个 InvalidOperationExcept ...
- Jquery方法load之后导致js失效解决方法
Jquery方法load之后导致js失效解决方法 >>>>>>>>>>>>>>>>>>> ...
- yum安装命令:遇到的问题报错如下: File "/usr/bin/yum", line 30 except KeyboardInterrupt, e: 通过看报错可以了解到是使用了python2的语法,所以了解到当前yum使用的Python2,因为我单独安装了python3,且python3设置为默认版本了,所以导致语法问题 解决方法: 使用python2.6 yum install
1.安装zip yum install -y unzip zip 2.安装lrszs yum -y install lrzsz 3.安装scp 遇到下面的问题: 结果提示: No package sc ...
- 阿里云提出的漏洞(Phpcms V9某处逻辑问题导致getshell漏洞解决方法)的问题
最近从阿里云云盾检测流出来的,相比使用阿里云服务器的朋友已经收到漏洞提醒:Phpcms V9某处逻辑问题导致getshell漏洞解决方法,这个漏洞怎么办呢?CMSYOU在这里找到针对性解决办法分享给大 ...
- GDI+ 绘图闪烁解决方法
闲着没事,准备做一个类似于TeeChart的自定义控件,结果第一步的绘图就把我给难倒了,虽然早就知道GDI绘图的闪烁问题很坑,但是却没有想到如此之坑,折腾了两天,才找到解决方法. 首先在窗体加载的时候 ...
- Unity中UI界面颤抖解决方法
将Render Mode中属性改为Screen Space - Camera 摄像机挂在Canvas属性下会出现UI界面颤抖的效果. UI界面颤抖解决方式:将Render Mode中属性改为Scree ...
随机推荐
- [BZOJ1588][HNOI2002]营业额统计 无旋Treap
[HNOI2002]营业额统计 时间限制: 5 Sec 内存限制: 162 MB 题目描述 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以 ...
- 【BZOJ4311】向量(线段树分治,斜率优化)
[BZOJ4311]向量(线段树分治,斜率优化) 题面 BZOJ 题解 先考虑对于给定的向量集,如何求解和当前向量的最大内积. 设当前向量\((x,y)\),有两个不同的向量\((u1,v1),(u2 ...
- 解题:AHOI 2005 航线规划
题面 这种不断删边的首先肯定想到时光倒流啊=.= 在最后剩下的连通图上跑出一棵搜索树,先将边权都赋为$1$,那么两点间的关键航线就是链上边权和,而每加入一条非树边$u,v$都会使得$u,v$链上的边的 ...
- syntax error: non-declaration statement outside function body
在函数外部使用形如:name:="mark"这样语句会出现 syntax error: non-declaration statement outside function bod ...
- 形态学及其他集合运算(Morphological and Other Set Operations)
摘 要:本实验主要实现形态学图像处理.主要验证图像集合的交并补运算.膨胀和腐蚀处理并利用图像集合的运算,实现形态学边界抽取算法并进行特征边界抽取.同时将膨胀和腐蚀扩展至灰度图像,编写函数实现灰度 ...
- 协程-遇到I/O自动切换
参考博客:http://www.cnblogs.com/alex3714/articles/5248247.html 一.前言 Gevent 是一个第三方库,可以轻松通过gevent实现并发同步或异步 ...
- poi对EXCEL的操作(一)
(原创自己这段时间对poi的研究心得) 一.基础的对象 1.wookbook工作簿 创建工作簿 wookbook XSSFWorkbook类的构造方法 XSSFWorkbook ...
- 2017北京国庆刷题Day6 morning
期望得分:100+100+20=220 实际得分:100+100+20=220 模拟栈 #include<cstdio> #include<cstring> using nam ...
- PHP扩展--taint检测隐藏漏洞
简介 Taint 可以用来检测隐藏的XSS code, SQL注入, Shell注入等漏洞, 并且这些漏洞如果要用静态分析工具去排查, 将会非常困难, 比如对于如下的例子: <?php echo ...
- R0—New packages for reading data into R — fast
小伙伴儿们有福啦,2015年4月10日,Hadley Wickham大牛(开发了著名的ggplots包和plyr包等)和RStudio小组又出新作啦,新作品readr包和readxl包分别用于R读取t ...