Frage

Mit C # und .Net 2.0, ich bin mit einer unregelmäßig geformten Form (TransparencyKey, Formborderstyle = None, etc ...) und will "normal" grenzte Modus zu ermöglichen.

ich ändere die Hintergrundfarbe von Kalk auf dem Standard Ich wechsle zu FixedSingle Formborderstyle Ich wechsle die TransparencyKey zu Colour.None

Unfortuanately sieht dies ein komplettes Chaos auf dem Bildschirm mit dem Bild ein paar Pixel nach unten und zur Seite und Lindgrün Form springen.

Ich denke, das durch die Form verursacht wird nach jeder Zeile Code neu gezeichnet wird, ist es möglich, zeichnet die Form auszusetzen, bis ich meine Änderungen vorgenommen habe und dann einfach das Formular einmal neu zu zeichnen?

G

War es hilfreich?

Lösung

NEW Antwort. Die WndProc außer Kraft setzen und die WM_PAINT-Nachricht blockieren, während Sie die neuen Fenster Eigenschaften gelten

OLD Antwort. Überschreiben Sie die WndProc, und blockieren 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 einem frisch gemalt führen. Eine frühe Nachricht in dieser Serie ist WM_ERASEBKGND. Normalerweise wird in Reaktion auf diese Nachricht, malt die Steuerung selbst eine Farbe. Später, in Reaktion auf die Nachricht WM_PAINT die eigentliche Zeichnung (die in der Regel von uns in dem OnPaint Ereignisse verbraucht wird) erfolgt. Wenn diese Zeichnung nicht trivial ist, wird es eine Verzögerung geben, bevor das Widget wird aktualisiert und Sie werden ein störendes Flimmern bekommen.

Mit Blick auf Ihrem Code wieder war ich eindeutig ein anderes Problem zu lösen. Versuchen Sie, dieses neue Beispiel. Es wird das Bild von der Form / Kontrolle sperren, wenn die bAllowPaint Flag nicht gesetzt ist.

Das NEU 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);
        }
    }

Andere Tipps

Versuchen Sie, die Form.DoubleBuffered Eigenschaft. Legen Sie es auf 'true'.

Auch wenn Ihre Form alle untergeordneten Steuerelemente hat, auch als auch für diejenigen, auf true gesetzt DoubleBuffered (und Kindeskinder, usw., auf der ganzen Linie).

Schließlich ruft SuspendLayout bevor Sie die Änderungen und ResumeLayout danach. Denken Sie daran, dies wirkt sich nur auf die Platzierung von Kinder Kontrollen. Wenn Sie irgendeine Gewohnheit tun, um die Eigenschaft DoubleBuffered Zeichnung werden Sie mehr bang for the buck.

Sie ändern Eigenschaften, die einen ziemlich großen Einfluss auf eine Form haben. TransparencyKey und erfordern eine Änderung der Formborderstyle Bits Fensterstil. Windows erlaubt es nicht, diese Art Bits geändert werden. Windows Forms setzt sie durch vollständig aus dem Fenster zu zerstören und neu zu erstellen, es von Grund auf neu. Ordentlich Trick, aber das braucht Zeit, und die Form wird jedes Mal, wenn Sie den Stil neu gestrichen werden. Verursachende den unangenehmen visuellen Effekt, den Sie sehen.

Versuchen Sie folgendes: 1. Stellen Sie die Deckkraft auf 0, so wird die Form unsichtbar 2. Ändern Backcolor, kein Problem 3. Ändern Formborderstyle, Fenster neu erstellt wird 4. Ändern TransparencyKey, Fenster neu erstellt wird 5. Ändern Sie die Deckkraft auf 1, Fenster neu erstellt wird, dann sichtbar

Zum Beispiel:

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

Wenn das alles fehlschlägt, könnte man einige Low-Level-Hacking versuchen, indem sie alle malen Nachrichten an Ihre Form zu blockieren.

ACHTUNG: Ich bin nicht die Anwendung dieser Methode zu fördern, aber man kann 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ützungscode:

public class Win32
{
  private Win32() { }

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

Ein Weg, um all das „Bild“ des Formulars auf den Bildschirm in einem Schritt zu senden ist Double zu ermöglichen.

Im Konstruktor können Sie die Control gesetzt

VB.NET:

SetStyle(ControlStyles.DoubleBuffer, True)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top