Rendering di un controllo Windows Form

Il rendering fa riferimento al processo di creazione di una rappresentazione visiva sullo schermo di un utente. Windows Form usa GDI (la nuova libreria grafica di Windows) per il rendering. Le classi gestite che forniscono l'accesso a GDI si trovano nello spazio dei System.Drawing nomi e nei relativi sottonome.

I seguenti elementi sono coinvolti nel rendering dei controlli:

  • Funzionalità di disegno fornita dalla classe System.Windows.Forms.Controlbase .

  • Elementi essenziali della libreria grafica GDI.

  • Geometria dell'area di disegno.

  • Procedura per liberare risorse grafiche.

Funzionalità di disegno fornite dal controllo

La classe Control di base fornisce funzionalità di disegno tramite il relativo Paint evento. Un controllo genera l'evento ogni volta che deve aggiornarne la Paint visualizzazione. Per altre informazioni sugli eventi in .NET Framework, vedere Gestione e generazione di eventi.

La classe di dati evento per l'evento Paint , PaintEventArgs, contiene i dati necessari per disegnare un controllo , ovvero un handle per un oggetto grafico e un oggetto rettangolo che rappresenta l'area in cui disegnare. Questi oggetti vengono visualizzati in grassetto nel frammento di codice seguente.

Public Class PaintEventArgs  
   Inherits EventArgs  
   Implements IDisposable  
  
   Public ReadOnly Property ClipRectangle() As System.Drawing.Rectangle  
      ...  
   End Property  
  
   Public ReadOnly Property Graphics() As System.Drawing.Graphics  
      ...  
   End Property  
   ' Other properties and methods.  
   ...  
End Class  
public class PaintEventArgs : EventArgs, IDisposable {  
public System.Drawing.Rectangle ClipRectangle {get;}  
public System.Drawing.Graphics Graphics {get;}  
// Other properties and methods.  
...  
}  

Graphics è una classe gestita che incapsula la funzionalità di disegno, come descritto nella discussione di GDI più avanti in questo argomento. ClipRectangle è un'istanza della Rectangle struttura e definisce l'area disponibile in cui un controllo può disegnare. Uno sviluppatore di controlli può calcolare l'oggetto ClipRectangle usando la ClipRectangle proprietà di un controllo, come descritto nella discussione della geometria più avanti in questo argomento.

Un controllo deve fornire la logica di rendering eseguendo l'override del OnPaint metodo che eredita da Control. OnPaint ottiene l'accesso a un oggetto grafico e a un rettangolo da disegnare attraverso Graphics e le ClipRectangle proprietà dell'istanza PaintEventArgs passata.

Protected Overridable Sub OnPaint(pe As PaintEventArgs)  
protected virtual void OnPaint(PaintEventArgs pe);  

Il OnPaint metodo della classe di base Control non implementa alcuna funzionalità di disegno, ma richiama semplicemente i delegati di evento registrati con l'evento Paint . Quando si esegue l'override OnPaintdi , è in genere necessario richiamare il OnPaint metodo della classe di base in modo che i delegati registrati ricevano l'evento Paint . Tuttavia, i controlli che disegnano l'intera superficie non devono richiamare la classe di base , OnPaintperché questo introduce sfarfallio. Per un esempio di override dell'eventoOnPaint, vedere Procedura: Creare un controllo Windows Form che mostra lo stato di avanzamento.

Nota

Non richiamare direttamente dal controllo; richiamare OnPaint invece il Invalidate metodo (ereditato da Control) o un altro metodo che richiama Invalidate. Il Invalidate metodo a sua volta richiama OnPaint. Il Invalidate metodo viene sottoposto a overload e, a seconda degli argomenti forniti a Invalidatee, un controllo ridisegna alcune o tutte le relative aree dello schermo.

La classe base Control definisce un altro metodo utile per il disegno, ovvero il OnPaintBackground metodo .

Protected Overridable Sub OnPaintBackground(pevent As PaintEventArgs)  
protected virtual void OnPaintBackground(PaintEventArgs pevent);  

OnPaintBackground disegna lo sfondo (e quindi la forma) della finestra ed è garantito che sia veloce, mentre OnPaint disegna i dettagli e potrebbe essere più lento perché le singole richieste di vernice vengono combinate in un evento Paint che copre tutte le aree che devono essere ridisegnate. È possibile richiamare l'oggetto OnPaintBackground se, ad esempio, si desidera disegnare uno sfondo colorato a sfumatura per il controllo.

Anche se OnPaintBackground ha una nomenclatura simile a un evento e accetta lo stesso argomento del OnPaint metodo , OnPaintBackground non è un metodo di evento vero. Non esiste alcun PaintBackground evento e OnPaintBackground non richiama delegati di evento. Quando si esegue l'override del OnPaintBackground metodo, non è necessaria una classe derivata per richiamare il OnPaintBackground metodo della relativa classe di base.

Nozioni di base su GDI+

La Graphics classe fornisce metodi per disegnare varie forme, ad esempio cerchi, triangoli, archi e ellissi, nonché metodi per la visualizzazione del testo. Lo System.Drawing spazio dei nomi e i relativi sottonomespace contengono classi che incapsulano elementi grafici come forme (cerchi, rettangoli, archi e altri), colori, tipi di carattere, pennelli e così via. Per altre informazioni su GDI, vedere Uso di classi grafiche gestite. Le nozioni di base di GDI sono descritte anche in Procedura: Creare un controllo Windows Form che mostra lo stato di avanzamento.

Geometria dell'area di disegno

La ClientRectangle proprietà di un controllo specifica l'area rettangolare disponibile per il controllo sullo schermo dell'utente, mentre la ClipRectangle proprietà di PaintEventArgs specifica l'area effettivamente dipinta. Tenere presente che il disegno viene eseguito nel metodo dell'evento Paint che accetta un'istanza PaintEventArgs come argomento. Un controllo potrebbe dover disegnare solo una parte dell'area disponibile, come nel caso in cui una piccola sezione della visualizzazione del controllo cambia. In tali situazioni, uno sviluppatore di controlli deve calcolare il rettangolo effettivo per disegnare e passarlo a Invalidate. Le versioni di overload di Invalidate che accettano o RegionRectangle come argomento usano tale argomento per generare la ClipRectangle proprietà di PaintEventArgs.

Il frammento di codice seguente mostra come il FlashTrackBar controllo personalizzato calcola l'area rettangolare in cui disegnare. La client variabile indica la ClipRectangle proprietà . Per un esempio completo, vedere Procedura: Creare un controllo Windows Form che mostra lo stato di avanzamento.

Rectangle invalid = new Rectangle(
    client.X + min,
    client.Y,
    max - min,
    client.Height);

Invalidate(invalid);
Dim invalid As Rectangle = New Rectangle( _
    client.X + lmin, _
    client.Y, _
    lmax - lmin, _
    client.Height)

Invalidate(invalid)

Liberare risorse grafiche

Gli oggetti grafici sono costosi perché usano risorse di sistema. Tali oggetti includono istanze della System.Drawing.Graphics classe , nonché istanze di System.Drawing.Brush, System.Drawing.Pene altre classi grafiche. È importante creare una risorsa grafica solo quando è necessaria e rilasciarla non appena viene terminata l'uso. Se si crea un tipo che implementa l'interfaccia, chiamare il Dispose relativo metodo al termine dell'operazione IDisposable per liberare risorse.

Il frammento di codice seguente mostra come il FlashTrackBar controllo personalizzato crea e rilascia una Brush risorsa. Per il codice sorgente completo, vedere Procedura: Creare un controllo Windows Form che mostra lo stato di avanzamento.

private Brush baseBackground = null;
Private baseBackground As Brush
base.OnPaint(e);
if (baseBackground == null) {
    if (showGradient) {
        baseBackground = new LinearGradientBrush(new Point(0, 0),
                                                 new Point(ClientSize.Width, 0),
                                                 StartColor,
                                                 EndColor);
    }
    else if (BackgroundImage != null) {
        baseBackground = new TextureBrush(BackgroundImage);
    }
    else {
        baseBackground = new SolidBrush(BackColor);
    }
}
MyBase.OnPaint(e)

If (baseBackground Is Nothing) Then

    If (myShowGradient) Then
        baseBackground = New LinearGradientBrush(New Point(0, 0), _
                                                 New Point(ClientSize.Width, 0), _
                                                 StartColor, _
                                                 EndColor)
    ElseIf (BackgroundImage IsNot Nothing) Then
        baseBackground = New TextureBrush(BackgroundImage)
    Else
        baseBackground = New SolidBrush(BackColor)
    End If

End If
protected override void OnResize(EventArgs e) {
    base.OnResize(e);
    if (baseBackground != null) {
        baseBackground.Dispose();
        baseBackground = null;
    }
}
Protected Overrides Sub OnResize(ByVal e As EventArgs)
    MyBase.OnResize(e)
    If (baseBackground IsNot Nothing) Then
        baseBackground.Dispose()
        baseBackground = Nothing
    End If
End Sub

Vedi anche