2010-07-20 22 views
20

Mam aplikację, która ma mnóstwo kontroli. I ma ogromną ilość migotania, szczególnie przy starcie.Migotanie w aplikacji Windows Forms

Zastosowałem do tego fix.

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

To działało świetnie - migotanie zostało zredukowane o całkiem niewiarygodną ilość. Jednak efektem ubocznym jest to, że przyciski Minimalizuj, Maksymalizuj i Zamknij w prawym górnym rogu okna nie animują się, gdy przesuję mysz lub klikam (nadal działają). Dzięki temu aplikacja będzie czuć się swobodnie.

Jak zachować WS_EX_COMPOSITED, zachowując jednocześnie funkcjonalność przycisków Maksymalizuj, Minimalizuj i Zamknij?

Dzieje się tak w systemie Windows XP. Jak zauważył @fallenidol, nie jest to problemem w systemie Windows 7.

+5

Idealne pytanie (chcę tej funkcjonalności, próbowałem tej rozdzielczości, w jaki sposób osiągnąć tę funkcjonalność z tym nowym ograniczeniem). –

+0

BTW, próbowałem tej poprawki w aplikacji testowej działającej w systemie Windows 7, a przyciski Maksymalizuj, Minimalizuj i Zamknij nadal wydają się animować. – pmcilreavy

+0

@ fallenidol. Dobrze wiedzieć. Wszyscy moi klienci mają XP. – AngryHacker

Odpowiedz

0

Powinieneś wypróbować standardową właściwość sterowania formami okien zwaną DoubleBuffered. http://msdn.microsoft.com/en-us/library/system.windows.forms.control.doublebuffered.aspx

+0

Działa to tylko na zasadzie kontroli. Podany przeze mnie przykład wymusza podwójne buforowanie na każdej kontrolce w formularzu. – AngryHacker

+0

Możesz użyć refleksji na początku aplikacji, aby wypełnić tę właściwość każdej kontrolki. – Kru

+0

Nie mogę tego zrobić dla elementów sterujących innych firm, które nie ujawniają tej właściwości. – AngryHacker

4

Spróbuj następującego kodu. Powinno to nastąpić w głównym formularzu i dowolnych innych niestandardowych kontrolach użytkownika, które posiadasz.

 // 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

Cały wpis opublikowanego przeze mnie kodu jest taki, że robisz to jeden raz, a nie dla każdej kontrolki użytkownika (które są setkami + tony kontroli innych firm). – AngryHacker

+3

Jest to kolejna opcja dla innych osób widzących tę stronę, którzy mogą nie mieć dostępu do całej aplikacji i tylko rozwijają kontrolę użytkownika w izolacji. Następnym razem, gdy tworzysz formant pojedynczego użytkownika, możesz użyć mojego fragmentu kodu powyżej. Wtedy możesz nie skończyć w sytuacji, w której masz setki migających kontrolek. – pmcilreavy

5

Wiem, że to pytanie jest trochę stary, ale lepiej późno niż wcale. Użyłem twojego oryginalnego przykładu, który łączyłeś, aby wymyślić taki, który włącza go podczas zmiany rozmiaru, a następnie przełącza go, aby narysować wszystko inne idealnie. Mam nadzieję, że pomoże to innym w poszukiwaniu rozwiązania tego problemu. Jak wie OP, właściwości DoubleBuffering nie rozwiązują problemów z migotaniem.

Oto obejście zatrzymać migotanie gdy użytkownik zmienia rozmiar formularza, ale nie brudząc się rysunek kontroli, takich jak DataGridView, NumericUpDown itp warunkiem imię i nazwisko forma jest „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

Dobra uwaga. Mam ten kod w mojej aplikacji, ale zaniedbałem dodanie go do mojego wpisu na blogu. Zaktualizuje go za kilka dni. – AngryHacker

0

Natknąłem się na ten wpis i zdałem sobie sprawę, że jest trochę stary. Mam jednak ten sam problem z moją formą i odkryłem (w każdym razie dla XP) nieeleganckie rozwiązanie wydaje się nie pozwalać na wizualne style.

+0

W dalszej kolejności wydaje się, że nie mam problemu z migotaniem, gdy przesłonię OnPaintBackground. Jeśli nie chcę, aby tło było malowane, nazywam e.Graphics.Clear ([odpowiedni kolor]) i zwracam, w przeciwnym razie wywoływana jest metoda zdarzenia podstawowego. Jak już powiedziałem, "wydaje się" to łagodzić problem. Zastanawiam się jednak, jakie mogą być nieprzewidziane reperkusje. – Tebc

+0

Korekta. Wymienione powyżej zastąpienie działa tak długo, jak długo właściwość minimalnej wielkości formularza jest ustawiona na bieżący rozmiar. – Tebc

Powiązane problemy