Måla och rita på kontroller

Anpassad målning av kontroller är en av de många komplicerade uppgifter som underlättas av Windows Forms. När du redigerar en anpassad kontroll har du många tillgängliga alternativ för att hantera kontrollens grafiska utseende. Om du redigerar en anpassad kontroll, dvs. en kontroll som ärver från Control, använder du kod för att återge dess grafiska representation.

Om du skapar en sammansatt kontroll, som ärver från någon UserControl av de befintliga Windows Forms-kontrollerna, kan du åsidosätta den grafiska standardrepresentationen och ange din egen grafikkod.

Om du vill tillhandahålla anpassad återgivning för en befintlig kontroll utan att skapa en ny kontroll hanterar Paint du händelsen som gör att du kan rita över en kontroll.

Följande element ingår i kontrollåtergivningen:

  • Ritningsfunktionen som tillhandahålls av basklassen System.Windows.Forms.Control.
  • De viktigaste elementen i GDI-grafikbiblioteket.
  • Ritningsregionens geometri.
  • Proceduren för att frigöra grafikresurser.

Ritning som tillhandahålls av kontrollen

Basklassen Control tillhandahåller ritfunktioner via sin Paint-händelse. En kontroll genererar Paint händelsen när den behöver uppdatera sin visning och har gjort sin ritning. Mer information om händelser i .NET finns i Hantera och höja händelser.

Händelsedataklassen för händelsen Paint, PaintEventArgs, innehåller de data som behövs för att rita en kontroll – ett handtag till ett grafikobjekt och en rektangel som representerar regionen som ska ritas in.

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 är en hanterad klass som kapslar in ritningsfunktioner, enligt beskrivningen i diskussionen om GDI senare i den här artikeln. ClipRectangle är en instans av Rectangle struktur och definierar det tillgängliga område där en kontroll kan rita. En kontrollutvecklare kan beräkna ClipRectangle med hjälp av egenskapen ClipRectangle för en kontroll, enligt beskrivningen i diskussionen om geometri senare i den här artikeln.

OnPaint

En kontroll måste tillhandahålla renderingslogik genom att åsidosätta den OnPaint metod som den ärver från Control. OnPaint får åtkomst till ett grafikobjekt och en rektangel för att rita i genom egenskaperna Graphics och ClipRectangle hos den PaintEventArgs-instans som skickats till det.

Följande kod använder System.Drawing namnområde:

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

Metoden OnPaint för basklassen Control implementerar inte någon ritningsfunktion utan anropar bara de händelsedelegater som är registrerade med händelsen Paint. När du åsidosätter OnPaintbör du vanligtvis anropa basklassens metod OnPaint så att händelsen Paint kan tas emot av registrerade ombud. Kontroller som målar hela ytan bör dock inte anropa basklassens OnPaint, eftersom detta introducerar flimmer.

Anmärkning

Anropa inte OnPaint direkt från din kontroll. anropa i stället metoden Invalidate (ärvd från Control) eller någon annan metod som anropar Invalidate. Metoden Invalidate anropar i sin tur OnPaint. Metoden Invalidate är överbelastad och, beroende på argumenten som angetts för Invalidatee, ritar om en del av eller hela dess skärmområde.

Koden i OnPaint-metoden för kontrollen körs när kontrollen först ritas och när den uppdateras. För att säkerställa att din kontroll ritas om varje gång den ändrar storlek lägger du till följande rad i konstruktorn för din kontroll:

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

OnPaintBackground

Basklassen Control definierar en annan metod som är användbar för ritning, OnPaintBackground-metoden.

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

OnPaintBackground målar bakgrunden (och på så sätt formen) av fönstret och garanteras vara snabb, medan OnPaint målar detaljerna och kan vara långsammare eftersom enskilda färgförfrågningar kombineras till en Paint händelse som täcker alla områden som måste ritas om. Du kanske vill anropa OnPaintBackground om du till exempel vill rita en toningsfärgad bakgrund för kontrollen.

Även om OnPaintBackground har en händelseliknande nomenklatur och använder samma argument som metoden OnPaint, är OnPaintBackground inte en sann händelsemetod. Det finns ingen PaintBackground händelse och OnPaintBackground anropar inte händelsedelegater. När du åsidosättar metoden OnPaintBackground krävs ingen härledd klass för att anropa OnPaintBackground-metoden för basklassen.

Grunderna i GDI+

Klassen Graphics innehåller metoder för att rita olika former, till exempel cirklar, trianglar, bågar och ellipser och metoder för att visa text. Det System.Drawing namnområdet innehåller namnrymder och klasser som kapslar in grafikelement som former (cirklar, rektanglar, bågar och andra), färger, teckensnitt, penslar och så vidare.

Geometri för ritningsområdet

Egenskapen ClientRectangle för en kontroll anger den rektangulära region som är tillgänglig för kontrollen på användarens skärm, medan egenskapen ClipRectangle för PaintEventArgs anger det område som är målat. En kontroll kan bara behöva måla en del av dess tillgängliga område, vilket är fallet när en liten del av kontrollens visning ändras. I sådana situationer måste en kontrollutvecklare beräkna den faktiska rektangeln för att dra in och skicka den till Invalidate. De överlagrade versionerna av Invalidate som tar en Rectangle eller Region som argument använder det argumentet för att generera egenskapen ClipRectangle för PaintEventArgs.

Frigör grafikresurser

Grafikobjekt är dyra eftersom de använder systemresurser. Sådana objekt omfattar instanser av klassen System.Drawing.Graphics och instanser av System.Drawing.Brush, System.Drawing.Penoch andra grafikklasser. Det är viktigt att du bara skapar en grafikresurs när du behöver den och släpper den när du är klar med den. Om du skapar en instans av en typ som implementerar IDisposable-gränssnittet anropar du dess Dispose-metod när du är klar med den för att frigöra resurser.

Se även

Anpassade kontroller