C# winform介面閃屏問題解決方法
登入以及切換介面時,介面不停閃爍的問題
將下面程式碼新增到窗體程式碼中:
protected override CreateParams CreateParams //防止介面閃爍 { get { CreateParams paras = base.CreateParams; paras.ExStyle |= 0x02000000; return paras; } }
過載訊息傳送函式操作,禁掉每次重繪清除畫布
protected override void WndProc(refMessage 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); } }