C# 控件闪烁问题的解决

勇哥说一下解决C#下控件闪烁的几个问题,如下:

  1.   listview和datagridview显示数据闪烁

  2.  自定义控件的显示闪烁

  3. listbox滚动条拖动闪烁

  4. 面板中控件过多的闪烁

  5. propertyGrid点击和修改项目缓慢的问题

  6. richtextbox控件的刷新显示问题


此类问题对于界面复杂规模比较大的程序感觉更明显。

另外勇哥的经验是你需要把程序拿到一个古董级别电脑上去复现上述问题及判断解决方案是否有效果。


 listview和datagridview显示数据闪烁


解决方法是使用双缓冲,见下面代码

public static class DoubleBufferDataGridView
{
    /// <summary>
    /// 双缓冲,解决闪烁问题
    /// </summary>
    /// <param name="dgv"></param>
    /// <param name="flag"></param>
    public static void DoubleBufferedDataGirdView(this DataGridView dgv, bool flag)
    {
        Type dgvType = dgv.GetType();
        PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
        pi.SetValue(dgv, flag, null);
    }
}

public static class DoubleBufferListView
{
    /// <summary>
    /// 双缓冲,解决闪烁问题
    /// </summary>
    /// <param name="lv"></param>
    /// <param name="flag"></param>
    public static void DoubleBufferedListView(this  ListView lv, bool flag)
    {
        Type lvType = lv.GetType();
        PropertyInfo pi = lvType.GetProperty("DoubleBuffered",
            BindingFlags.Instance | BindingFlags.NonPublic);
        pi.SetValue(lv, flag, null);
    }

}

//调用方法
public Form1()
{
    InitializeComponent();
    DataGridView1.DoubleBufferedDataGirdView(true);
}


自定义控件的显示闪烁


此法是解决在 winform中动态添加自定义控件时,可能会出现闪烁的问题。

例如往FlowLayoutPanel控件(容器控件)中添加自定义控件。


1. 在添加自定义控件的Form中添加如下代码:

开启界面双缓冲  解决窗体切换闪屏问题

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


2. 在自定义控件中添加如下代码:

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


listbox滚动条拖动闪烁


1. 禁止背景重绘消息

 protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x0014) // 禁掉清除背景消息
                return;
            base.WndProc(ref m);
        }


2. 使用控件的BeginUpdate 和 EndUpdate 方法


通过使用BeginUpdate 和 EndUpdate 方法,可以在对控件进行大数据填充时,

避免在应用这些更改时让控件经常重新绘制自身。

此类重新绘制会导致性能显著降低,并且用户界面闪烁且不反应。


BeginUpdate在许多控件里也可以隐式调用。

它就是控件的 AddRange 方法,使用它将自动为您调用 BeginUpdate 和 EndUpdate 方法。


面板中控件过多的闪烁


此法解决窗体中控件过多的闪烁


1. 开启界面双缓冲  解决窗体切换闪屏问题

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


2.  使用自定义的panel

public partial class MyPanel : Panel
    {
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //do not allow the background to be painted
        }

        /**#region 开启界面双缓冲  解决窗体切换闪屏问题
        //下面的代码许加在MDI窗体中
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;
                return cp;
            }
        }
        #endregion

        protected override void WndProc(ref Message m) {
            if (m.Msg == 0x0014) // 禁掉清除背景消息
               return;
            base.WndProc(ref m);
         }  **/  
 
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            // 使用双缓冲
            this.DoubleBuffered = true;

            // 背景重绘移动到此
            if (this.BackgroundImage != null)
            {
                e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                e.Graphics.DrawImage(
                    this.BackgroundImage,
                    new System.Drawing.Rectangle(0, 0, this.Width, this.Height),
                    0,
                    0, this.BackgroundImage.Width, this.BackgroundImage.Height, System.Drawing.GraphicsUnit.Pixel);
            }
            base.OnPaint(e);
        }
 
    }

3.  在ui底层重绘每次会清除画布,然后再全部重新绘制,这是导致闪烁最主要的原因之一。

下面方法是重载消息发送函数操作,禁掉这条消息。至于有什么副作用,各位见到后可以告诉勇哥。

       protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x0014) // 禁掉清除背景消息
                return;
            base.WndProc(ref m);
        }


propertyGrid点击和修改项目缓慢的问题


此问题请见贴子《C#的propertygrid控件,选择和修改项目时很慢


2022/4/6 注:

另外发现在mdi主窗体使用下面代码,也是造成propertygrid控件修改项目很慢的主要原因。(做梦也想不到会有影响)

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


richtextbox控件的刷新显示问题


此控件如果想更新内容,直接给text赋值就可以了。

但是如果你用定时器持续更新,是不是发现滚动条无法下拉?

其实是可以的,关键是你拉滚动条时不要把光标定位到richtextbox控件里面,因此,你需要点击面板上其它位置,让焦点不位于此控件就可以拉动滚动条了。




要注意的地方:


(1)不要在mdi主窗体使用下面代码

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

其后果就是当改变子窗体的大小时,(而这个窗体有一个容器,显示有动态载入的控件)有可能会让容器显示为空白。

或者有可能最小化再恢复窗体时出现这种空白的问题。





--------------------- 

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864