C#关于TreeView树在节点数较多时总是会出现闪烁的问题方法记录
首先介绍下背景吧,问题如题,这个问题应该说困扰我大半年了(不是说我没有请教大佬,不是说我没有上网查过,之前在搜索时,总是没有解决此问题~~),直到最近一次在在优化代码时,再次上网查找,在发现搜索词条”C#控件闪烁问题“,才有了下文。额额额,于是我记录了下面得到片段。
对于TreeView节点可以动态创建,而且数量还很大的时候,我们给其设置什么双缓冲,使用EndUpdate操作啥的,都是没有效果的。使用了下面的代码即可解决问题;
根据调式,我查找出瓶颈在于每次更新完界面的EndUpdate操作(使用这个是为了减少界面更新次数,但这里不理想是因为控件中中的元素很多),猜想大概每次更新,.Net底层都会更新重绘每个图元,所以速度会慢,造成闪烁。但是如果这样,使用双缓冲应该会有较好效果。再看代码,发现可能是更新动作太过频繁,于是降低速度,有所好转,但还是不行。
继续在网上查阅,最终找到一个方案比较合适。原来底层重绘每次会清除画布,然后再全部重新绘制,这才是导致闪烁最主要的原因。于是重载消息发送函数操作,禁掉这条消息。代码如下:
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0014) // 禁掉清除背景消息WM_ERASEBKGND
return;
base.WndProc(ref m);
}
成功!
注意了,注意了,这里其实不只是TreeView控件有闪烁问题,在C#中只要控件的内容数量大,都会存在闪烁。产生闪烁原因如下:
Windows在窗口的具体绘制之前,会发送WM_ERASEBKGND消息通知该窗口檫除背景。默认情况下,会以窗口的默认背景色清除窗口。
WM_ERASEBKGND消息和WM_PAINT消息的另外一种含义:背景色与前景色
可以这样理解WM_ERASEBKGND消息和WM_PAINT消息:
1.WM_ERASEBKGND消息用于通知系统或者程序员绘制背景色
2.WM_PAINT消息用于通知程序员绘制前景色,比如在WM_PAINT中调用TextOut函数输出文本
详情可以看看这位网友的:https://blog.csdn.net/analogous_love/article/details/50039467
注:双缓冲还是有用的,在更新不是很频繁且控件内含元素不是特别多的时候。一旦元素过多,每次更新时间都比较长,即便使用了双缓冲,仍解决不了闪烁问题。个人认为最终比较理想的方法还是禁掉清除背景消息。
附:一些尝试过但失败的记录(下面的方法我没有尝试)
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)
{
// 此处书写过滤消息代码
}
但是实际实验显示无效果,不知是什么原因,没有细究。
上面转载网友的!仅为记录下。
C#关于TreeView树在节点数较多时总是会出现闪烁的问题方法记录的更多相关文章
- 初始化bootstrap treeview树节点
最近在做启明星图库时,使用了Jquery Bootstrap Treeview插件.但是,遇到了一个初始化的问题.先看效果如下: 当用户打开图库时,左边分类第一个类别是“所有分类”,默认需要选中. ...
- TreeView 树节点的处理
TreeView 树节点的处理 using System; using System.Collections.Generic; using System.ComponentModel; using S ...
- winform中生成TreeView树
无论是webform还是winform,TreeView都是常用功能.使用递归方法很方便. 下面分享一个小实例. 数据库中3个字段,分别是:ID,itemType_name,itemType_PID ...
- WinForm控件TreeView 只部分节点显示 CheckBox
WinForm控件TreeView 只部分节点显示 CheckBox 用过asp.net的应该知道,要在treeview中实现上述功能可以使用ShowCheckBox 属性指定那些节点显示check ...
- C++计算二叉树的节点数和高度
用struct结构体的写法: /* * description: 计算二叉树的层数和节点数 * writeby: nick * date: 2012-10-23 16:16 * */ #include ...
- Codeforces 509F Progress Monitoring:区间dp【根据遍历顺序求树的方案数】
题目链接:http://codeforces.com/problemset/problem/509/F 题意: 告诉你遍历一棵树的方法,以及遍历节点的顺序a[i],长度为n. 问你这棵树有多少种可能的 ...
- ztree树 叶子节点路径的集合
1.Question Description: ztree树各个节点都带有路径,如“/根节点”,"/根节点/一级节点",“根节点/一级节点/二级节点‘; 现在想获取所选的最末级节点 ...
- 获取所有树叶子节点 注册添加事件 if ($(node).tree('isLeaf', node.target)) 是否叶子节点
//获取所有树叶子节点 注册添加事件 if ($(node).tree('isLeaf', node.target)) 是否叶子节点 $(function () { $('.easyui-tree') ...
- zTree实现删除树子节点
zTree实现删除树子节点 1.实现源码 <!DOCTYPE html> <html> <head> <title>zTree实现基本树</tit ...
随机推荐
- 团队选题报告(bull beer)
一.团队成员及分工 团队名称:bull beer 团队成员: 黄文东:选题报告word撰写 沈培:原型设计,博客撰写,ppt制作 邓泽中:住院 刘帅:查找相关资料 二.选题报告内容 项目名称:学费管理 ...
- android学习笔记--AlarmManager
AlarmManager称呼为全局定时器,有的称呼为闹钟.其实它的作用和Timer有点相似. 都有两种相似的用法: (1)在指定时长后执行某项操作(2)周期性的执行某项操作 AlarmManager ...
- .NET运行时中的监测和可观测性
今年5月份的时候研究分布式追踪的问题知道了的拦截方式比较零散, 刚好8月份的时候看到这篇文章,这个文章总结的比较完整.存档了很久,趁今天有空翻译给大家.原文地址,校验:张蘅水 .NET是一个托管运行时 ...
- Form 表单提交的几种方式
简单的总结一下form表单提交的几种方式:1.最简单的方式 就用form的submit提交方式,这种提交方式是不需要回调函数的 这种方式最近到一个form提供action路径后台接受就可以< ...
- Centos7 Jenkins日志过大
df 查看 占用 [root@instance-ncwnnt0e /]# df Filesystem 1K-blocks Used Available Use% Mounted on devtmpfs ...
- .net core中使用autofac进行IOC
.net Core中自带DI是非常简单轻量化的,但是如果批量注册就得扩展,下面使用反射进行批量注册的 public void AddAssembly(IServiceCollection servic ...
- C# 设置程序启动项
托盘图标设置 新建一个NotifyIcon,会在托盘处显示一个图标. NotifyIcon.Icon可以直接设置一个ico图片,也可以延用原有程序的图标. notifyIcon.Icon = Syst ...
- OO第二次博客作业——电梯调度
OO第二次博客作业——电梯调度 前言 最近三周,OO课程进入多线程学习阶段,主要通过三次电梯调度作业来学习.从单部电梯的傻瓜式调度到有性能要求的调度到多部电梯的调度,难度逐渐提升,对同学们的要求逐渐变 ...
- 007. 服务间通信 RPC & REST over HTTP(s) & 消息队列
服务间通信 服务间通信的几种方式: RPC.REST over HTTP(s).消息队列. https://www.jianshu.com/p/2a01d4383d0b RPC https://bl ...
- Dynamics 365 启用跟踪及读取跟踪文件工具
微软动态CRM专家罗勇 ,回复315或者20190313可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 当根据错误提示排查问 ...