Disegno e disegno su controlli (Windows Form .NET)

Il disegno personalizzato dei controlli è una delle numerose attività complesse rese facili da Windows Form. Quando si crea un controllo personalizzato, sono disponibili molte opzioni per gestire l'aspetto grafico del controllo. Se si crea un controllo personalizzato, ovvero un controllo che eredita da Control, è necessario fornire il codice per eseguire il rendering della relativa rappresentazione grafica.

Importante

La documentazione di Desktop Guide per .NET 7 e .NET 6 è in fase di costruzione.

Se si crea un controllo composito, ovvero un controllo che eredita da UserControl o uno dei controlli Windows Form esistenti, è possibile eseguire l'override della rappresentazione grafica standard e fornire codice grafico personalizzato.

Se si desidera fornire rendering personalizzato per un controllo esistente senza creare un nuovo controllo, le opzioni diventano più limitate. Tuttavia, esistono ancora un'ampia gamma di possibilità grafiche per i controlli e le applicazioni.

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.

Disegno fornito 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, 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 rettangolo che rappresenta l'area in cui disegnare.

public class PaintEventArgs : EventArgs, IDisposable
{

    public System.Drawing.Rectangle ClipRectangle {get;}
    public System.Drawing.Graphics Graphics {get;}

    // Other properties and methods.
}
Public Class PaintEventArgs
    Inherits EventArgs
    Implements IDisposable

    Public ReadOnly Property ClipRectangle As System.Drawing.Rectangle
    Public ReadOnly Property Graphics As System.Drawing.Graphics

    ' Other properties and methods.
End Class

Graphics è una classe gestita che incapsula la funzionalità di disegno, come descritto nella discussione di GDI più avanti in questo articolo. 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 sulla geometria più avanti in questo articolo.

OnPaint

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.

Il codice seguente usa lo System.Drawing spazio dei nomi :

protected override void OnPaint(PaintEventArgs e)
{
    // Call the OnPaint method of the base class.
    base.OnPaint(e);

    // Declare and instantiate a new pen that will be disposed of at the end of the method.
    using var myPen = new Pen(Color.Aqua);

    // Create a rectangle that represents the size of the control, minus 1 pixel.
    var area = new Rectangle(new Point(0, 0), new Size(this.Size.Width - 1, this.Size.Height - 1));

    // Draw an aqua rectangle in the rectangle represented by the control.
    e.Graphics.DrawRectangle(myPen, area);
}
Protected Overrides Sub OnPaint(e As PaintEventArgs)
    MyBase.OnPaint(e)

    ' Declare and instantiate a drawing pen.
    Using myPen = New System.Drawing.Pen(Color.Aqua)

        ' Create a rectangle that represents the size of the control, minus 1 pixel.
        Dim area = New Rectangle(New Point(0, 0), New Size(Me.Size.Width - 1, Me.Size.Height - 1))

        ' Draw an aqua rectangle in the rectangle represented by the control.
        e.Graphics.DrawRectangle(myPen, area)

    End Using
End Sub

Il OnPaint metodo della classe 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.

Nota

Non richiamare direttamente dal controllo; invece, richiamare OnPaint 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, ridisegna alcune o tutte le relative aree dello schermo.

Il codice nel OnPaint metodo del controllo verrà eseguito al primo disegno del controllo e ogni volta che viene aggiornato. Per assicurarsi che il controllo venga ridisegnato ogni volta che viene ridimensionato, aggiungere la riga seguente al costruttore del controllo:

SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.ResizeRedraw, True)

Onpaintbackground

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

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

OnPaintBackground disegna lo sfondo (e in questo modo, 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 unico Paint evento 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 puntini di sospensione e metodi per la visualizzazione del testo. Lo System.Drawing spazio dei nomi contiene spazi dei nomi e classi che incapsulano elementi grafici come forme (cerchi, rettangoli, archi e altri), colori, tipi di carattere, pennelli e così via.

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 disegnata. 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.

Liberare risorse grafiche

Gli oggetti grafici sono costosi perché usano risorse di sistema. Tali oggetti includono istanze della System.Drawing.Graphics classe e delle 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'istanza di un tipo che implementa l'interfaccia IDisposable , chiamare il Dispose relativo metodo al termine dell'operazione per liberare risorse.

Vedi anche