2009-03-05 12 views
6

Utilizzando C# e. Rete 2.0, sto usando un modulo di forma irregolare (TransparencyKey, FormBorderStyle = Nessuno, ecc ...) e voglio consentire la modalità "normale" con bordi.Posso sospendere il ridisegno di un modulo fino a quando non ho eseguito tutti gli aggiornamenti?

posso cambiare il colore di nuovo di default da Lime cambio FormBorderStyle a FixedSingle cambio la TransparencyKey Colour.None

Unfortuanately questo sembra un pasticcio completo sullo schermo con l'immagine di saltare un paio di pixel in basso ea il lato e la forma verde lime.

Penso che questo sia causato dal ridimensionamento del modulo dopo ogni riga di codice, è possibile sospendere il disegno del modulo fino a quando non ho apportato le modifiche e quindi ridisegno il modulo una sola volta?

G

+1

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

risposta

8

NUOVA risposta: ignora il WndProc e blocca il messaggio WM_PAINT mentre applicate le nuove proprietà della finestra.

OLD risposta: Ignora il WndProc e blocca il messaggio WM_ERASEBKGND.

spiegazione di ciò che il codice qui sotto fa:

Quando regione di una finestra viene invalidata, Windows invia una serie di messaggi al controllo che si traducono in un appena dipinta di widget. Un messaggio iniziale in questa serie è WM_ERASEBKGND. Normalmente, in risposta a questo messaggio, il controllo si dipinge di un colore solido. Successivamente, in risposta al messaggio WM_PAINT (che di solito viene utilizzato da noi nell'evento OnPaint), viene eseguito il disegno corrente. Se questo disegno non è banale, ci sarà un ritardo prima che il widget venga aggiornato e otterrai uno sfarfallio fastidioso.

Guardando nuovamente il codice, ho chiaramente risolto un problema diverso. Prova questo nuovo esempio. Bloccherà il disegno del modulo/controllo se il flag bAllowPaint non è impostato.

Il NUOVO esempio:

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

L'esempio VECCHIO:

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

Potrebbe spiegare più in dettaglio cosa questo per favore? Capisco il concetto di override, ma cosa impedisce/fa questo codice? –

2

Prova la proprietà Form.DoubleBuffered. Impostalo su "true".

Inoltre, se il modulo contiene controlli figlio, impostare anche DoubleBuffered su true anche per quelli (e bambini e bambini, ecc. Lungo la linea).

Infine, chiamare SuspendLayout prima delle modifiche e ResumeLayout in seguito. Tieni presente che ciò influisce solo sul posizionamento dei controlli figlio. Se stai facendo un disegno personalizzato, la proprietà DoubleBuffered ti darà più valore per il dollaro.

0

un modo per inviare tutto l ' "immagine" del modulo per lo schermo in un unico passaggio è quello di abilita DoubleBuffer.

nel costruttore è possibile impostare il ControlStyles

VB.NET:

SetStyle(ControlStyles.DoubleBuffer, True) 
4

Si stanno modificando le proprietà che hanno un impatto piuttosto grande su un modulo. TransparencyKey e FormBorderStyle richiedono la modifica dei bit di stile della finestra. Windows non consente di modificare quei bit di stile. Windows Form li implementa distruggendo completamente la finestra e ricreandola da zero. Trucchetto pulito, ma richiede tempo e il modulo verrà ridipinto ogni volta che cambi lo stile. Causando l'effetto visivo spiacevole che vedi.

Prova questo: 1. impostare l'opacità a 0 così la forma diventa invisibile 2. Modificare BackColor, nessun problema 3. Modificare FormBorderStyle, finestra vengono ricreate 4. Modificare TransparencyKey, finestra vengono ricreate 5. Variazione Opacità a 1, la finestra viene ricreata, quindi visibile

ad esempio:

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

FYI: l'utilizzo di questo metodo non funziona in WPF. È possibile vedere ancora circa il 50% del flicker temporale. –

+0

Ovviamente, questo è il codice di Winforms. –

+0

Sto ancora cercando un modo per sospendere temporaneamente la verniciatura di una finestra WPF (cambiando la dimensione/posizione della finestra) ... –

2

Se tutto ciò fallisce, si potrebbe provare un po 'di hacking basso livello bloccando tutti i messaggi di disegno al form.

ATTENZIONE: non sto promuovendo l'uso di questo metodo, ma è possibile provarlo se lo si desidera. Mi ha aiutato in passato.

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

Questo codice si basa sulla seguente codice di supporto:

public class Win32 
{ 
    private Win32() { } 

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

Secondo msdn questo deve essere usato solo quando si trascina e rilascia: msdn.microsoft.com/en-us/library/windows/desktop/dd145034(v=vs.85).aspx –

Problemi correlati