如何避免多控件窗体重新布局时闪烁

适用场景:

需要在某容器控件中动态装载多个子控件,而且该容器控件可能需要改变WindowFormState,即从Normal转变为Maxmized,或者是其他状态转换啦, what ever :)

如果没有应用任何特殊处理,你就会发现,当容器控件状态转换时,其上的子控件在经过一阵狂闪之后(可能背景控件颜色和自身相互交替出现),最终恢复至平静; 这种情形当然无论是程序员自己和客户都不愿意看到的

ok,废话一通之后,咱们开始解释原因,以及考虑解决方案

为什么会闪烁?

因为窗体控件状态转换时,windows需要负责"擦除"其背景,重新绘制,在一台性能并不优良的终端上(很大可能程度上客户端电脑都不是那么强劲吧) ,这个过程不是一时半会就能完成的,尤其对于很多个子控件的情况,因此就…

解决之道?

如果稍微写过WinForm程序的同学,肯定或多或少的用过ListView控件,简单易用嘛 :) 那么一定也知道该控件有2个比较有意思的方法:

BeginUpdate

Prevents the control from drawing until the EndUpdate method is called.

EndUpdate

Resumes drawing of the list view control after drawing is suspended by the BeginUpdate method.

从msdn的解释来看,这2个方法的应用能解决往ListView控件中分多次Add ListViewItem时闪烁的问题,ok,既然它能这么处理,咱们自己的容器控件为什么不能依葫芦画瓢呢?

btw. 其实我一开始也没任何好方法解决闪烁问题,后来偶尔想到ListView的此特性 :)

看看ListView.BeginUpdateInternal方法怎么写:

internal void BeginUpdateInternal()
{
 if (this.IsHandleCreated)
 {
  if (this.updateCount == 0)
  {
   this.SendMessage(11, 0, 0);
  }
  this.updateCount = (short) (this.updateCount + 1);
 }
}

关键一行在 this.SendMessage(11, 0, 0); 虾米意思呢? 它给自身Send了一个code为11的windows消息,11代表虾米?

在windows消息定义中可以看到 WM_SETREDRAW = 0x0B (0x0B也就是11),这行代码的意思是告诉windows对ListView控件停止重绘界面,直到显式要求重新绘制为止. 很牛叉对不对 :Dok,在EndUpdateInternal中又做了虾米?

internal bool EndUpdateInternal(bool invalidate)
{
 if (this.updateCount <= 0)
 {
  return false;
 }
 this.updateCount = (short) (this.updateCount - 1);
 if (this.updateCount == 0)
 {
  this.SendMessage(11, -1, 0);
  if (invalidate)
  {
   this.Invalidate();
  }
 }
 return true;
}

同样有一行代码: this.SendMessage(11, –1, 0); 11还是同一个意思,此时告知windows可以重绘ListView控件了

ok,到这时候应该明白这2个方法含义了吧,也就是说对子控件的操作都是在一个“冻结”的状态中进行的,等到所有准备工作就绪,才对最终状态重新绘制,因此界面就不会出现闪烁状态.

时间: 2025-01-01 19:44:47

如何避免多控件窗体重新布局时闪烁的相关文章

winform 窗体中用datagridview控件如何实现编辑时自动匹配相应数据

问题描述 如上图是textbox文本框实现的输入自动补全,但是我想在datagridview控件中实现编辑时自动补全,该如何做(非数据库) 解决方案 解决方案二:在EditingControlShowing事件获取e.Control,转换成TextBox,后面和TextBox补全是一样的解决方案三:引用1楼shingoscar的回复: 在EditingControlShowing事件获取e.Control,转换成TextBox,后面和TextBox补全是一样的 有代码吗?不是很懂这些解决方案四:

vb.net 控件backgroundcolor为半透明时,如何让其它控件也半透明显示?

问题描述 vb.net 控件backgroundcolor为半透明时,如何让其它控件也半透明显示? Label1.BackColor = Color.FromArgb(100 0 0 0) 这样做以后只让窗体的背景图片半透明显示了,而其它控件却被遮盖了.(图片为窗体背景)怎么让控件也半透明地显示出来? 解决方案 http://blog.csdn.net/sxycgxj/article/details/6114798http://download.csdn.net/download/zenas/1

实例-跪求大神啊,VB中dwgthumb控件打开DWG文件时需要设置什么参数

问题描述 跪求大神啊,VB中dwgthumb控件打开DWG文件时需要设置什么参数 VB中dwgthumb控件打开DWG文件时需要设置什么参数,用没用实例呢,谢谢啊,大神 解决方案 http://www.newxing.com/Code/VB/TXCL/dwg_462.htmlhttp://download.csdn.net/detail/dirk2212/4197363http://download.csdn.net/download/dirk2212/4198022http://www.edu

winform委托修改控件text为汉字时显示为问号

问题描述 winform委托修改控件text为汉字时显示为问号 如题,我用spilt以逗号为间隔分开了几个字符串,最后一个字符串是汉字比如你好,调用 SetLabel(str[2].ToString());显示到控件,public void SetLabel(string text){if (fs.label3.InvokeRequired){SetLabelCallBack sl = new SetLabelCallBack(SetLabel);this.Invoke(sl new objec

100个chart控件实时绘图时,单击单个chart控件显示每个chart控件的放大曲线时总是滞后

问题描述 100个chart控件实时绘图时,单击单个chart控件显示每个chart控件的放大曲线时总是滞后 我有100个chart控件组成的数据采集界面,一段时间要对这100个单独的chart控件进行数据绘图,单独点击某一个chart控件还能看到每一个chart控件的放大曲线图,遇到的问题就是:恰好在对100个chart控件同时进行绘图时,此时单击任何一个chart控件都会卡住,只到100个chart的绘图过程结束,单个chart的放大界面曲线才能看到,有什么办法能让这两个过程互不影响吗?线程

vc++6 0-用vc++6.0 利用windows media player控件制作播放器时

问题描述 用vc++6.0 利用windows media player控件制作播放器时 在win7 64位环境下 要对 播放器进行暂停 快进等操作时 调用 CWMPcontrols 函数时 显示 'CWMPcontrols.h': No such file or directory 头文件 也加了 cwmpcontrols.h 头文件换成小写也是不行的 也说不能打开 没有这个文件 cwmpcontrols.h 头文件是存在的在工程目录下: 解决方案 你的VC++版本太旧,没有这个头文件.建议你

activex-C#开发ActiveX控件调用dll文件时,dll文件放在什么位置,我的出错了

问题描述 C#开发ActiveX控件调用dll文件时,dll文件放在什么位置,我的出错了 通过c#谢了一个很简单的Activex控件,调用dll文件(dll文件是c++写的,并且dll文件不是com组件),在普通的容器中调用动态库都没问题,但是通过activex时就会出错,请问这是问什么,请留言,也可以加我qq:574225218 解决方案 在dll文件中调用VBA的命令 解决方案二: 是在IE中测试出错么?尝试把浏览器的安全等级设置全部调到最低,在客户端安装.net framework并且运行

datagridview-VS2010从datagirdview控件设置数据来源时自动建立的dataset有什么用?

问题描述 VS2010从datagirdview控件设置数据来源时自动建立的dataset有什么用? 相应的建立了这些: 数据库名+dataset(这是个类,如testDataSet) 表名+bindingsource 表名+tableadapter 包含了哪些功能?

devexpress-DevExpress控件在导出Excel时怎么分成Sheet表来导出

问题描述 DevExpress控件在导出Excel时怎么分成Sheet表来导出 DevExpress控件在导出Excel时用的是 Printingsystem的导出ExportToXls方法导出的,只能将整个界面按一个Excel工作表来导出!! 界面上有三个grid(每一个加载一个界面作为数据控件),我想要做的是在导出的时候,每一个控件导出一个工作表,在一个Excel工作薄里面,,导出报表的格式按,控件显示的格式来,不知道各位大神有什么办法没有,,小弟在这里跪求了,,,谢谢每一位出主意的好心人