当前位置:首页 > C#编程 > C#/.net框架 > 正文内容

C# 控件闪烁问题的解决

Jorge2年前 (2022-05-08)C#/.net框架2410

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

  listview和datagridview显示数据闪烁

 自定义控件的显示闪烁

listbox滚动条拖动闪烁

面板中控件过多的闪烁

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

richtextbox控件的刷新显示问题


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

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


 listview和datagridview显示数据闪烁


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

C#
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中添加如下代码:

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

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


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

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


listbox滚动条拖动闪烁


1. 禁止背景重绘消息

C#
 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. 开启界面双缓冲  解决窗体切换闪屏问题

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


2.  使用自定义的panel

C#
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底层重绘每次会清除画布,然后再全部重新绘制,这是导致闪烁最主要的原因之一。

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

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


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


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


2022/4/6 注:

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

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


richtextbox控件的刷新显示问题


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

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

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




要注意的地方:


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

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

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

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





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

作者:hackpig

来源:www.skcircle.com

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



扫描二维码推送至手机访问。

版权声明:本文由7点博客发布,如需转载请注明出处。

本文链接:http://6dot.cn/?id=36

标签: .NET.NET框架
分享给朋友:

“C# 控件闪烁问题的解决” 的相关文章

C#的propertygrid控件,选择和修改项目时很慢

C#的propertygrid控件,选择和修改项目时很慢

C#的propertygrid控件是很强。可以实现类似Vitual Studio属性面板那样的效果。但是。。。。我们一直痛苦它在选择和修改项目的时候很慢。我的用法是使用控件的SelectObject来绑定数据。C# PgridMotionSpeed.SelectedObject ...

C# 当List.Find()返回一个结构体对象时,如何判断它为空?

C# 当List.Find()返回一个结构体对象时,如何判断它为空?

请看演示程序。我们知道List.Find() 如果找到则返回这个对象,找不到返回这个类型的缺省值。下面例子中,你无法这样写:            if(res1==null)        &nbs...

C#中使用RegisterWindowMessage进行进程之间进行通讯

C#中使用RegisterWindowMessage进行进程之间进行通讯

注:大家都知道在window里,进程之间通讯可以用消息通讯。但是有个较冷门的知识就是RegisterWindowMessage。一般的sendmessage和postmessage是需要在窗体程序间进行通讯,你得知道对方窗口的句柄。这个句柄每次启动程序时是系统分配的,每次不一样。有了这个Regist...

谈谈ObservableCollection观察者集合

谈谈ObservableCollection观察者集合

注:事件很常见,但有重复的代码量。如果你想简化一下事件的编程,而且是整个程序只使用一个像事件池一样的东西,可以尝试使用下文讲的ObservableCollection观察者集合来做到。ObservableCollection<T>类表示一个动态数据集合,在添加项,移除项或刷新整个列表时,...

索引器(C# 编程指南)

索引器(C# 编程指南)

 索引器允许类或结构的实例就像数组一样进行索引。 无需显式指定类型或实例成员,即可设置或检索索引值。 索引器类似于属性,不同之处在于它们的访问器需要使用参数。以下示例定义了一个泛型类,其中包含用于赋值和检索值的简单 get 和 set 访问器方法。&...

C# 当前不会命中断点 还没有为该文档加载任何符号

C# 当前不会命中断点 还没有为该文档加载任何符号

这个问题网上的经验大概如下:1。 清空方案,重新编译2。 删除项目bin目录下的东西,重新编译3。 解决相互引用的问题。4。 确保不是run的release5。把项目编译改为x866。 好像没发现其它的了。。。这些解决不了我们手上的项目的问题。我们的工程有几十个项目。我长话短说,解决方法是:引导项目...

发表评论

访客

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