2008-09-16 9 views

Antwort

81

Hier ist eine allgemeinere Version von Dummy's solution.

Wir können Reflektion verwenden, um die geschützte Eigenschaft DoubleBuffered zu erhalten, und dann kann sie auf true gesetzt werden.

Hinweis: Sie sollten pay your developer taxes und nicht use double-buffering if the user is running in a terminal services session (zum Beispiel Remote Desktop) Diese Hilfsmethode nicht auf doppelte Pufferung drehen, wenn die Person in Remote-Desktop ausgeführt wird.

public static void SetDoubleBuffered(System.Windows.Forms.Control c) 
{ 
    //Taxes: Remote Desktop Connection and painting 
    //http://blogs.msdn.com/oldnewthing/archive/2006/01/03/508694.aspx 
    if (System.Windows.Forms.SystemInformation.TerminalServerSession) 
     return; 

    System.Reflection.PropertyInfo aProp = 
     typeof(System.Windows.Forms.Control).GetProperty(
       "DoubleBuffered", 
       System.Reflection.BindingFlags.NonPublic | 
       System.Reflection.BindingFlags.Instance); 

    aProp.SetValue(c, true, null); 
} 
+0

Dieser Code löste mein Problem ohne jede Änderung. Vielen Dank! – Mykroft

+0

Komisch, würde ich denken, dass es noch wichtiger ist, beim Remotieren doppelt zu puffern, damit Sie nicht unnötig eine Reihe von Repaints über die Leitung senden? –

+11

Es ist genau das, was Sie nicht wollen. In einer Terminalsitzung kann das GDI-System Befehle senden (hier eine Linie zeichnen, hier einen Kreis zeichnen, hier ausfüllen usw.). Die doppelte Pufferung wird erreicht, indem Sie alles auf eine Bitmap zeichnen und dann mit GDI das gesamte Formular als Bitmap zeichnen. Das Senden einer unkomprimierten Bitmap über die Leitung ist * VIEL * langsamer als das Senden der ursprünglichen GDI-Befehle. –

10
public void EnableDoubleBuffering() 
{ 
    this.SetStyle(ControlStyles.DoubleBuffer | 
     ControlStyles.UserPaint | 
     ControlStyles.AllPaintingInWmPaint, 
     true); 
    this.UpdateStyles(); 
} 
18
System.Reflection.PropertyInfo aProp = typeof(System.Windows.Forms.Control) 
    .GetProperty("DoubleBuffered", System.Reflection.BindingFlags.NonPublic | 
    System.Reflection.BindingFlags.Instance); 
aProp.SetValue(ListView1, true, null); 

Ian hat einige weitere Informationen zu diesem Server auf einem Terminal.

+0

Dies funktioniert der Trick. Ich habe es zu einer generischen Hilfsfunktion gemacht und es hier gepostet. –

+0

Es ist nicht wirklich für * on * einen Terminalserver, da keiner meiner Kunden die Software von einer Remotedesktopsitzung aus ausführt. Aber Sie sollten Ihre Entwickler Steuern zahlen, und ich wollte nicht Code, der nicht bereits die Steuern enthalten löschte. –

1

Sie können die Steuerelemente auch in Ihre eigenen Klassen übernehmen und die Eigenschaft dort festlegen. Diese Methode ist auch gut, wenn Sie dazu neigen, viele Einstellungen vorzunehmen, die bei allen Steuerelementen gleich sind.

8

Eine Möglichkeit besteht darin, das spezifische Steuerelement, das Sie doppelt puffern möchten, zu erweitern und die DoubleBuffered-Eigenschaft im Steuerelement ctor festzulegen.

Zum Beispiel:

class Foo : Panel 
{ 
    public Foo() { DoubleBuffered = true; } 
} 
+0

Ich arbeite mit einem Eigentümer gezeichnet ListView in einer abgeleiteten Klasse. Das hat das Problem perfekt gelöst! –

+0

Ich weiß nicht, ob es irgendwelche Nachteile gibt, aber das hat perfekt funktioniert. Mein benutzerdefiniertes Steuerelement wurde zuvor von "Control" geerbt und ich habe es stattdessen so geändert, dass es von "Panel" erbte und DoubleBuffered auf "true" setzt. Ein zwei Zeilenwechsel. Bewegung ist glatt ... und die Geschwindigkeit, um ein einzelnes Update zu zeichnen, scheint auch viel schneller. –

4

Bevor Sie doppelte Pufferung versuchen, festzustellen, ob SuspendLayout()/ResumeLayout() Ihr Problem lösen.

+3

Suspend/ResumeLayout löst das Problem des Flackerns beim Malen nicht. –

0

Ich habe festgestellt, dass durch einfaches Festlegen der DoubleBuffered Einstellung auf dem Formular alle hier aufgeführten Eigenschaften automatisch festgelegt werden.

Jedoch; Ich habe festgestellt, dass die von Winforms bereitgestellte doppelte Pufferung weniger als großartig ist. This little gem of a code snippetwirklich macht einen Unterschied, ernsthaft es versuchen. Ich verbrachte eine lange Zeit Suche nach einer Lösung, die gearbeitet und fand schließlich, dass :-)

+0

Der Link ist tot ... –

+0

ja ich weiß ... Ich habe diesen Code verloren und konnte es nirgendwo anders im Internet finden ... sorry! – ljs

54

prüfen this thread

den Kern dieser Antwort Wiederholen Sie auf der WS_EX_COMPOSITED Stil Flagge auf dem Fenster drehen kann zu bekommen Sowohl die Form als auch alle ihre Steuerelemente sind doppelt gepuffert. Das Style Flag ist seit XP verfügbar. Es macht das Malen nicht schneller, aber das gesamte Fenster wird in einem Offscreen-Puffer gezeichnet und blitzschnell auf den Bildschirm geworfen. Damit es für die Augen des Benutzers ohne sichtbare Malartefakte sofort aussieht. Es ist nicht ganz störungsfrei, einige Renderer von visuellen Stilen können daran Fehler machen, besonders TabControl, wenn es zu viele Registerkarten hat. YMMV.

Fügen Sie diesen Code in das Formular Klasse:

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

Der große Unterschied zwischen dieser Technik und Double-Buffering Unterstützung des Winform ist, dass Winform-Version nur auf einer Steuerung arbeitet zur Zeit an. Sie werden immer noch jedes einzelne Steuerelement selbst sehen. Das kann auch wie ein Flickereffekt aussehen, besonders wenn das unlackierte Kontrollrechteck schlecht mit dem Hintergrund des Fensters kontrastiert.

+0

Wow ... über Nacht und Tag reden; großer Unterschied für mich mit dieser Methode. –

+1

404-ED. –

+4

+1 OMG. Unglaublich gut. Ich habe jede andere hier erwähnte Lösung ausprobiert, und ich flackerte immer noch wie Morsecode. Folgte der einfachen schwarzen Magie, die hier beschrieben wird, und nary einen Blip auf dem Bildschirm. DANKE! –

5

nobugz bekommt den Kredit für die Methode in seinem Link, ich bin nur Umbuchung. Fügen Sie diese Überschreibung der Form:

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

Das ist für mich am besten funktioniert, auf Windows 7 Ich war immer große schwarze Blöcke erscheinen, wenn ich eine Steuer schwere Form ändern. Die Steuerung springt jetzt stattdessen! Aber es ist besser.

+0

Dies ist das gleiche wie die Antwort von @Hans Passant, aber +1, um den Code hier zu setzen. –

+6

Ich bin nobugz, der Spitzname, den ich in den MSDN Foren benutzt habe. –

4

Erweiterungsmethode doppelte Pufferung zu aktivieren oder zu deaktivieren für Kontrollen

public static class ControlExtentions 
{ 
    /// <summary> 
    /// Turn on or off control double buffering (Dirty hack!) 
    /// </summary> 
    /// <param name="control">Control to operate</param> 
    /// <param name="setting">true to turn on double buffering</param> 
    public static void MakeDoubleBuffered(this Control control, bool setting) 
    { 
     Type controlType = control.GetType(); 
     PropertyInfo pi = controlType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); 
     pi.SetValue(control, setting, null); 
    } 
} 

Nutzung (zum Beispiel, wie Datagridview DoubleBuffered machen):

DataGridView _grid = new DataGridView(); 
// ... 
_grid.MakeDoubleBuffered(true); 
4

Das verursachte mir eine viel von Kummer für zwei Tage mit der Kontrolle eines Dritten, bis ich es aufgespürt habe.

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

Ich hatte vor kurzem eine Menge Löcher (Kot), wenn wieder Sizing/eine Kontrolle, die mehrere andere Steuerelemente neu erstellt.

versuchte ich WS_EX_COMPOSITED und WM_SETREDRAW aber nichts funktionierte, bis ich benutzen:

private void myPanel_SizeChanged(object sender, EventArgs e) 
{ 
    Application.DoEvents(); 
} 

einfach es passieren wollte.

0

vb.net Version dieser feine Lösung ....:

Protected Overrides ReadOnly Property CreateParams() As CreateParams 
    Get 
     Dim cp As CreateParams = MyBase.CreateParams 
     cp.ExStyle = cp.ExStyle Or &H2000000 
     Return cp 
    End Get 
End Property