Domanda

Usando C # e .Net 2.0, sto usando una forma di forma irregolare (TransparencyKey, FormBorderStyle = None, etc ...) e voglio consentire "normale". modalità bordata.

Cambio il colore posteriore in default da Lime Cambio FormBorderStyle in FixedSingle Cambio il TransparencyKey in Colour.None

Sfortunatamente questo sembra un disastro completo sullo schermo con l'immagine che salta di alcuni pixel verso il basso e lateralmente e forma verde lime.

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

G

È stato utile?

Soluzione

NUOVA risposta: sovrascrive WndProc e blocca il messaggio WM_PAINT mentre applichi le nuove proprietà Window.

VECCHIA risposta: sovrascrive WndProc e blocca il messaggio WM_ERASEBKGND .

Spiegazione di cosa fa il codice seguente:

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

Guardando di nuovo il tuo codice stavo chiaramente risolvendo un problema diverso. Prova questo nuovo esempio. Bloccherà il disegno del modulo / controllo se il flag bAllowPaint non è impostato.

L'esempio NUOVO :

    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 OLD :

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

Altri suggerimenti

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

Inoltre, se il tuo modulo ha dei controlli figlio, imposta anche DoubleBuffered su true anche per quelli (e i figli dei bambini, ecc., lungo la linea).

Infine, chiama SuspendLayout prima delle modifiche e successivamente ResumeLayout. Tieni presente che ciò influisce solo sul posizionamento dei controlli figlio. Se stai eseguendo un disegno personalizzato, la proprietà DoubleBuffered ti farà guadagnare di più.

Stai 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. Trucco pulito, ma richiede tempo e il modulo verrà ridipinto ogni volta che cambi stile. Causando lo spiacevole effetto visivo che vedi.

Prova questo: 1. Impostare Opacità su 0 in modo che il modulo diventi invisibile 2. Cambia BackColor, nessun problema 3. Cambia FormBorderStyle, la finestra viene ricreata 4. Change TransparencyKey, la finestra viene ricreata 5. Cambia Opacità su 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;

Se tutto ciò non riesce, puoi provare un po 'di hacking di basso livello bloccando tutti i messaggi di disegno nel tuo modulo.

ATTENZIONE: non sto promuovendo l'uso di questo metodo, ma puoi provarlo se lo desideri davvero. 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 sul 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);
 }

Un modo per inviare tutta " immagine " del modulo sullo schermo in un solo passaggio è abilitare DoubleBuffer.

Nel costruttore è possibile impostare ControlStyles

VB.NET:

SetStyle(ControlStyles.DoubleBuffer, True)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top