winform加载1000个控件,不卡不闪屏。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了winform加载1000个控件,不卡不闪屏。相关的知识,希望对你有一定的参考价值。

有什么方法或思路,解决winform窗体加载大量控件的效率。

改变设计,无论多少个控件,用户能看到的就是处于当前屏幕/窗口可视区域内的控件
所以你只需要把可视区域的控件生成显示出来就可以
非可视区域的,就当作只是一个数据链表中的Item存放着就可以了

你了解了解列表控件中的虚列表,思想是一样的
用着显示的时候,再去更新显示也好,动态生成也好,总之,只显示可视区域内的东东
不可视区域的全都销毁或者隐藏
参考技术A 需要加载1000个控件的界面,本身设计就有问题 参考技术B 怎么会加载这么多的控件

WinForm Flicker闪屏解决方案

开发WinForm 程序时经常会遇到闪屏的问题,这会给用户造成很差的使用体验,所以必须妥善解决好这个问题。

首先,我们先要找出闪屏的原因,就我目前遇到的问题而言,其原因真是五花八门。

主要的原因有:使用了很多的组件导致加载缓慢,使用了性能差的组件(PictureBox、Button等)

所以,不论开发者的水平如何,微软给我们也挖了坑的。

 

对于控件太多造成的闪屏,其原因有两个:

1. 绘制控件时,Windows 会给控件发送两个消息。第一个是WM_ERASEBKGND消息,它会触发OnPaintBackground方法,绘制控件背景

第二个是WM_PAINT消息,它会触发 OnPaint()方法,绘制控件界面。当绘制很慢的时候,会先看到背景,然后才看到界面,这样造成闪烁。

解决方案:在构造方法中设置 ControlStyles 的OptimizedDoubleBuffer 和AllPaintingInWmPaint为True,完全启用双缓冲

启用双缓冲的首选方法是将该控件的 DoubleBuffered 属性设置为 true,这会产生同样的结果,原因不细说了。

 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
 this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

2. 有很多控件的窗体需要很长时间来绘制。特别是在它使用性能很差的PictureBox、Button等时。一旦你加上50多个的控件,闪屏就开始变得明显了。

窗体会先绘制其自身背景,并在控件所在地方留下"洞"。这些"洞"通常是白色的,当你使用Opacity 或Transparency是黑色的。

然后每个控件被绘制后,就填充在"洞"中。这种视觉效果是很丑陋的,而且在WinForm 中没有现成的解决方案。

双缓冲也不能解决它,因为它只适用于一个单一的控件,而不是一组复合控件。

解决方案:设置CreateParams的ExStyle为ExStyle  为 0x02000000 (WS_EX_COMPOSITED)。

设置了这个值之后XP(其他系统好像也可以,没有考证)会把窗体和它的子窗体都开启双缓冲

protected override CreateParams CreateParams { 
      get { 
        CreateParams cp = base.CreateParams; 
        cp.ExStyle |= 0x02000000; 
        return cp; 
      } 
 } 

这里有一些需要注意的地方:这种方式并不会加快绘制的过程。当发生绘制时,窗体只是停留在不可见的状态,当绘制完成后就会在屏幕上弹出。

这时窗体的Opacity or TransparencyKey 是不会起作用的,窗体的轮廓是可见的,在绘制区域会出现一个丑陋的黑色矩形框。

要解决这个问题,最好使用计时器来增加不透明度值到99%,以使其在绘制后可见,这样用户就不会看到黑色矩形了。

public partial class FormDemo : Form
    {
        private Timer Timer = null;
        public FormDemo()
        {
            InitializeComponent();
            Timer = new Timer() { Interval = 100 };
            Timer.Tick += new EventHandler(Timer_Tick);
            base.Opacity = 0;
            Timer.Start();
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            if (this.Opacity >= 1)
            {
                Timer.Stop();
            }
            else
            {
                base.Opacity += 0.2;
            }
        }
    }

 先写这么多,慢慢补充吧!

 

 

以上是关于winform加载1000个控件,不卡不闪屏。的主要内容,如果未能解决你的问题,请参考以下文章

C# winform chart 控件横坐标只显示固定个数值怎么设置,比如固定显示500或1000个数据?

wpf显示视频,image控件闪屏,使用winform控件实现

c#winform制作用户控件+传值给用户控件

winform 界面全屏

c# winform 窗口控件多,就会加载很慢???

winform如何用Timer实现将时间动态显示在窗体上?