1. 程式人生 > 其它 >C# winform介面閃屏問題解決方法

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); } }