2009-03-05 5 views
6

Bei Verwendung von C# und .Net 2.0 verwende ich ein unregelmäßig geformtes Formular (TransparencyKey, FormBorderStyle = None, etc ...) und möchte den "normalen" umrandeten Modus zulassen.Kann ich das Neuzeichnen eines Formulars aussetzen, bis ich alle Aktualisierungen durchgeführt habe?

ich die Hintergrundfarbe ändern von Lime Ich wechsle zu FixedSingle Formborderstyle ich ändern, um die TransparencyKey zu Colour.None

Unfortuanately dies sieht ein komplettes Chaos auf dem Bildschirm mit dem Bild springt ein paar Pixel nach unten und auf dem Standard die Seite und die lindgrüne Form.

Ich denke, dies wird durch das Formular verursacht, das nach jeder Codezeile neu gezeichnet wird, ist es möglich, das Zeichnen des Formulars auszusetzen, bis ich meine Änderungen vorgenommen habe und dann das Formular nur einmal neu zeichnen?

G

+1

[WPF Version] (http://stackoverflow.com/q/22563416/2596334) –

Antwort

8

NEUE Antwort: Überschreiben Sie die WndProc und blockieren Sie die WM_PAINT-Nachricht, während Sie die neuen Fenstereigenschaften anwenden.

OLD Antwort: Überschreiben Sie die WndProc, und blockieren Sie die WM_ERASEBKGND Nachricht.

Erklärung dessen, was der folgende Code tut:

Wenn ein Bereich des Fensters für ungültig erklärt wird, sendet Windows eine Reihe von Nachrichten an das Steuerelement, das Widget in ein frisch gemalt führen. Eine frühe Nachricht in dieser Serie ist WM_ERASEBKGND. Normalerweise zeichnet das Steuerelement als Antwort auf diese Nachricht eine feste Farbe. Später, als Reaktion auf die Nachricht WM_PAINT (die normalerweise von uns im OnPaint-Ereignis konsumiert wird), wird die eigentliche Zeichnung erstellt. Wenn diese Zeichnung nicht trivial ist, wird es eine Verzögerung geben, bevor das Widget aktualisiert wird und Sie ein nerviges Flimmern bekommen.

Mit Blick auf Ihren Code wieder löste ich eindeutig ein anderes Problem. Probieren Sie dieses neue Beispiel aus. Wenn das bAllowPaint-Flag nicht gesetzt ist, wird das Bild des Formulars/Steuerelements blockiert.

Das NEW Beispiel:

private const int WM_PAINT = 0x000F; 

    protected override void WndProc(ref Message m) 
    { 
     if ((m.Msg != WM_PAINT) || 
      (bAllowPaint && m.Msg == WM_PAINT)) 
     { 
      base.WndProc(ref m); 
     } 
    } 

Das OLD Beispiel:

private const int WM_ERASEBKGND = 0x0014; 

    protected override void WndProc(ref Message m) 
    { 
     if (m.Msg != WM_ERASEBKGND) // ignore WM_ERASEBKGND 
     { 
      base.WndProc(ref m); 
     } 
    } 
+0

Können Sie näher erläutern, was diese geht das bitte? Ich verstehe das Konzept des Überschreibens, aber was verhindert dieser Code? –

2

die Form.DoubleBuffered Eigenschaft Versuchen. Setze es auf "wahr".

Wenn Ihr Formular über untergeordnete Steuerelemente verfügt, legen Sie DoubleBuffered für diese auch auf true (und untergeordnete Elemente für Kinder usw.) fest.

Zuletzt, rufen SuspendLayout vor Ihren Änderungen und ResumeLayout danach. Beachten Sie, dass dies sich nur auf die Platzierung von untergeordneten Steuerelementen auswirkt. Wenn Sie eine benutzerdefinierte Zeichnung ausführen, erhalten Sie mit der DoubleBuffered-Eigenschaft mehr Leistung.

0

Ein Weg, um all "Bild" des Formulars auf den Bildschirm in einem Schritt zu senden ist, Aktivieren Sie DoubleBuffer.

Im Konstruktor können Sie die Control

VB gesetzt.NET:

SetStyle(ControlStyles.DoubleBuffer, True) 
4

Sie ändern Eigenschaften, die eine ziemlich große Auswirkung auf ein Formular haben. TransparencyKey und FormBorderStyle erfordern das Ändern der Fensterstil-Bits. Windows lässt nicht zu, dass diese Stilbits geändert werden. Windows Forms implementiert sie, indem das Fenster vollständig zerstört und neu erstellt wird. Ordentlicher Trick, aber das braucht Zeit und die Form wird jedes Mal neu gezeichnet, wenn Sie den Stil ändern. Verursachen Sie den unangenehmen visuellen Effekt, den Sie sehen.

Try this: 1. Stellen Sie die Deckkraft auf 0, so dass die Form unsichtbar wird 2. Ändern Backcolor, kein Problem 3. Ändern Formborderstyle, Fenster 4. Ändern TransparencyKey neu erstellt wird, bekommt Fenster 5. Ändern Opazität neu erstellt 1 ist, wird Fenster, dann sichtbar

zum Beispiel neu erstellt:

this.Opacity = 0; 
    this.BackColor = Color.FromKnownColor(KnownColor.Control); 
    this.FormBorderStyle = FormBorderStyle.Sizable; 
    this.TransparencyKey = Color.Empty; 
    this.Opacity = 1; 
+0

FYI: die Verwendung dieser Methode funktioniert nicht in WPF. Ungefähr 50% des Zeitflackerns kann noch gesehen werden. –

+0

Natürlich ist dies Winforms-Code. –

+0

Ich bin immer noch auf der Suche nach einer Möglichkeit, ein WPF - Fenster temporär zu streichen (beim Ändern der Fenstergröße/- position) ... –

2

all Wenn das, Sie durch die Blockierung alle Farbe Nachrichten an Ihre Form könnten versuchen, einige Low-Level-Hacking ausfällt.

WARNUNG: Ich befürworte nicht die Verwendung dieser Methode, aber Sie können es versuchen, wenn Sie wirklich wollen. Es hat mir in der Vergangenheit geholfen.

Win32.LockWindowUpdate(this.Handle); 
try 
{ 
    //make your changes here 
} 
finally 
{ 
    //release the lock 
    Win32.LockWindowUpdate((IntPtr)0); 
} 

Dieser Code stützt sich auf die folgenden unterstützenden Code:

public class Win32 
{ 
    private Win32() { } 

    /// <summary> 
    /// Lock ore relase the wndow for updating. 
    /// </summary> 
    [DllImport("user32")] 
    public static extern int LockWindowUpdate(HWND hwnd); 
} 
+0

Laut msdn ist dies nur beim Ziehen und Ablegen zu verwenden: msdn.microsoft.com/en-us/library/windows/desktop/dd145034(v=vs.85).aspx –