2010-07-20 76 views
20

我有一個應用程序,它有一噸的控件。而且它有大量的閃爍,特別是在啓動時。在Windows窗體應用程序中閃爍

我將此fix加到它。

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

這很好 - 閃爍減少了一個相當不可思議的數額。但是,副作用是當我將鼠標移到或點擊它們(它們仍然可以工作)時,窗口右上角的最小化,最大化和關閉按鈕不會生成動畫。這給了應用程序一個懸掛的感覺。

如何保留WS_EX_COMPOSITED,同時仍保留最大化,最小化和關閉按鈕的可用性?

這發生在Windows XP上。正如@fallenidol指出的,這在Windows 7上不是問題。

+5

完美的問題(我想要這個功能,我試過這個解決方案,我如何用這個新的約束來實現這個功能)。 – 2010-07-20 01:34:32

+0

順便說一句,我試着在Windows 7上運行的測試應用程序中進行修復,最大化,最小化和關閉按鈕似乎仍然具有動畫效果。 – pmcilreavy 2010-07-21 07:21:53

+0

@fallenidol。這很好。我所有的客戶都在XP上。 – AngryHacker 2010-07-21 16:37:27

回答

11

我想通了。訣竅是在顯示錶單後刪除WS_EX_COMPOSITED標誌。在我的博客的完整說明和代碼:

How to get rid of flicker on Windows Forms applications

+0

非常棒..爲我工作 – Marshal 2011-03-31 07:00:14

+0

很好的文檔。感謝那。 Upvoted。 – C4u 2014-11-26 10:52:47

+0

@Hossein是的,博客現在停下來......希望這個月會在某個時候恢復。 – AngryHacker 2016-08-07 19:02:07

0

您應該嘗試標準的Windows窗體控件屬性,名爲DoubleBuffered。 http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx

+0

這隻適用於每個控件。我提供的示例強制在表單上的每個控件上進行雙緩衝。 – AngryHacker 2010-07-20 07:43:37

+0

您可以在應用程序的開始處使用反射來填充每個控件的此屬性。 – Kru 2010-07-20 07:51:14

+0

我不能爲不公開此屬性的第三方控件執行此操作。 – AngryHacker 2010-07-21 16:32:59

4

請嘗試下面的代碼。這應該在主窗體以及您擁有的任何其他自定義用戶控件中進行。

 // Enable double duffering to stop flickering. 
     this.SetStyle(ControlStyles.DoubleBuffer, true); 
     this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
     this.SetStyle(ControlStyles.UserPaint, true); 
     this.SetStyle(ControlStyles.SupportsTransparentBackColor, false); 
     this.SetStyle(ControlStyles.Opaque, false); 
     this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 
     this.SetStyle(ControlStyles.ResizeRedraw, true); 
+0

我發佈的代碼的全部內容是,您只需執行一次,而不是針對每個用戶控件(其中有數百個+第三方控件)。 – AngryHacker 2010-07-20 15:53:33

+3

這是其他人看到此頁面的另一種選擇,他們可能無法訪問整個應用程序,而只是單獨開發用戶控件。 下次您正在開發單個用戶控件時,您可以使用上面的代碼片段。那麼你可能不會在有數百個閃爍控制的情況下結束。 – pmcilreavy 2010-07-21 07:18:25

5

我知道這個問題是有點老了,但遲到總比不到好。我使用了你鏈接的原始示例來創建一個在調整大小時切換它的示例,然後將其切換回來以便完美地繪製其他所有內容。希望它可以幫助其他人尋找解決這個問題的方法。正如OP所知道的,DoubleBuffering單獨的屬性不能解決閃爍的問題。

這裏有一個變通停止閃爍時,用戶改變形式,但沒有搞亂如的DataGridView,的NumericUpDown等控制繪圖前提是你的窗體名稱是「Form1的」:

int intOriginalExStyle = -1; 
bool bEnableAntiFlicker = true; 

public Form1() 
{ 
    ToggleAntiFlicker(false); 
    InitializeComponent(); 
    this.ResizeBegin += new EventHandler(Form1_ResizeBegin); 
    this.ResizeEnd += new EventHandler(Form1_ResizeEnd); 
} 

protected override CreateParams CreateParams 
{ 
    get 
    { 
     if (intOriginalExStyle == -1) 
     { 
      intOriginalExStyle = base.CreateParams.ExStyle; 
     } 
     CreateParams cp = base.CreateParams; 

     if (bEnableAntiFlicker) 
     { 
      cp.ExStyle |= 0x02000000; //WS_EX_COMPOSITED 
     } 
     else 
     { 
      cp.ExStyle = intOriginalExStyle; 
     } 

     return cp; 
    } 
} 

private void Form1_ResizeBegin(object sender, EventArgs e) 
{ 
    ToggleAntiFlicker(true); 
} 

private void Form1_ResizeEnd(object sender, EventArgs e) 
{ 
    ToggleAntiFlicker(false); 
} 

private void ToggleAntiFlicker(bool Enable) 
{ 
    bEnableAntiFlicker = Enable; 
    //hacky, but works 
    this.MaximizeBox = true; 
} 
+0

好點。我在我的應用中使用過這些代碼,但忽略將其添加到我的博客條目中。將在幾天內更新。 – AngryHacker 2011-06-29 16:45:33

0

我剛剛遇到這個帖子,意識到它有點老了。然而,我的表單與我的表單有相同的問題,並且發現(對於XP,無論如何),一個不雅的解決方案似乎並沒有啓用視覺樣式。

+0

作爲一個後續行動,當我重寫OnPaintBackground時,我似乎沒有閃爍問題。如果我不想繪製背景,我將調用e.Graphics.Clear([適當的顏色])並返回,否則調用基本事件方法。正如我所說,這似乎是爲了緩解這個問題。但是,我想知道可能會產生什麼樣的不可預見的後果。 – Tebc 2012-12-10 15:01:45

+0

正確。只要表單的最小大小屬性設置爲當前大小,上述覆蓋似乎就會起作用。 – Tebc 2012-12-10 15:11:37