C# winform界面闪屏问题解决方法

登录以及切换界面时,界面不停闪烁的问题

将下面代码添加到窗体代码中:

   protected override CreateParams CreateParams  //防止界面闪烁
   {
       get
       {
            CreateParams paras = base.CreateParams;
            paras.ExStyle |= 0x02000000;
            return paras;
       }
   }

重载消息发送函数操作,禁掉每次重绘清除画布

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

 

使用Form的双缓存可以减少闪屏,但效果不明显,可以在Form的Load事件里添加以下代码

1 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
2 this.SetStyle(ControlStyles.DoubleBuffer, true);
3 this.SetStyle(ControlStyles.UserPaint, true);
4 this.SetStyle(ControlStyles.ResizeRedraw, true);

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)
      {
               // 此处书写过滤消息代码
      }

 

窗体背景闪烁的问题

封装 Panel 类

/// <summary>
/// 加强版 Panel
/// </summary>
class PanelEnhanced : Panel
{
    /// <summary>
    /// OnPaintBackground 事件
    /// </summary>
    /// <param name="e"></param>
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        // 重载基类的背景擦除函数,
        // 解决窗口刷新,放大,图像闪烁
        return;
    }

    /// <summary>
    /// OnPaint 事件
    /// </summary>
    /// <param name="e"></param>
    protected override void OnPaint(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);
    }
}

将之前我们建立窗体中的 Panel 容器换为我们新封装的 PanelEnhanced 容器,将程序的背景图片放到里面,再运行程序,程序背景闪烁的问题就完美解决

 

/// <summary>/// 加强版 Panel/// </summary>classPanelEnhanced : Panel { /// <summary>/// OnPaintBackground 事件/// </summary>/// <param name="e"></param>protected override void OnPaintBackground(PaintEventArgs e) { // 重载基类的背景擦除函数,// 解决窗口刷新,放大,图像闪烁return; } /// <summary>/// OnPaint 事件/// </summary>/// <param name="e"></param>protected override void OnPaint(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); } }
posted @ 2022-05-15 20:11  淮雨清青  阅读(2451)  评论(0编辑  收藏  举报