Delen via


Schilderen en tekenen op besturingselementen (Windows Forms .NET)

Aangepast schilderen van besturingselementen is een van de vele gecompliceerde taken die eenvoudig zijn gemaakt door Windows Forms. Bij het ontwerpen van een custom control zijn er veel opties beschikbaar om het grafische uiterlijk van uw besturingselement te beheren. Als u een aangepast besturingselement ontwerpt, dat wil gezegd, een besturingselement dat overneemt van Control, moet u code opgeven om de grafische weergave ervan weer te geven.

Als u een samengesteld besturingselement maakt, is dat een besturingselement dat wordt overgenomen van UserControl of een van de bestaande Besturingselementen van Windows Forms, kunt u de standaard grafische weergave overschrijven en uw eigen grafische code opgeven.

Als u aangepaste rendering wilt bieden voor een bestaand besturingselement zonder een nieuw besturingselement te maken, worden uw opties beperkter. Er zijn echter nog steeds een breed scala aan grafische mogelijkheden voor uw besturingselementen en toepassingen.

De volgende elementen zijn betrokken bij het weergeven van besturingselementen:

  • De tekenfunctionaliteit van de basisklasse System.Windows.Forms.Control.
  • De essentiële elementen van de GDI-grafische bibliotheek.
  • De geometrie van het tekengebied.
  • De procedure voor het vrijmaken van grafische resources.

Tekening geleverd door besturingselement

De basisklasse Control biedt tekenfunctionaliteit via de Paint gebeurtenis. Een besturingselement triggert de Paint-gebeurtenis wanneer het de weergave moet bijwerken. Zie Afhandeling en het genereren van gebeurtenissenvoor meer informatie over gebeurtenissen in .NET.

De gebeurtenisgegevensklasse voor de Paint gebeurtenis, PaintEventArgs, bevat de gegevens die nodig zijn voor het tekenen van een besturingselement: een ingang voor een grafisch object en een rechthoek die de regio vertegenwoordigt die moet worden getekend.

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 is een beheerde klasse die tekenfunctionaliteit inkapselt, zoals verderop in dit artikel wordt beschreven in de bespreking van GDI. De ClipRectangle is een exemplaar van de Rectangle structuur en definieert het beschikbare gebied waarin een besturingselement kan tekenen. Een besturingselementontwikkelaar kan de ClipRectangle berekenen met behulp van de eigenschap ClipRectangle van een besturingselement, zoals beschreven in de bespreking van geometrie verderop in dit artikel.

OnPaint

Een controle moet renderinglogica bieden door de OnPaint methode te overschrijven die het erft van Control. OnPaint krijgt toegang tot een grafisch object en een rechthoek om in te tekenen via de Graphics en ClipRectangle eigenschappen van het PaintEventArgs exemplaar dat aan hem is doorgegeven.

De volgende code maakt gebruik van de System.Drawing-naamruimte:

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

De OnPaint method van de basisklasse Control implementeert geen tekenfunctionaliteit, maar roept alleen de event-delegaten aan die zijn geregistreerd voor de Paint gebeurtenis. Wanneer u OnPaintoverschrijft, moet u doorgaans de OnPaint methode van de basisklasse aanroepen, zodat geregistreerde gemachtigden de Paint gebeurtenis ontvangen. Besturingselementen die hun hele oppervlak schilderen, moeten echter niet de OnPaintvan de basisklasse aanroepen, omdat dit flikkert.

Notitie

Roep OnPaint niet rechtstreeks vanuit uw besturingselement aan; Roep in plaats daarvan de Invalidate methode aan (overgenomen van Control) of een andere methode die Invalidateaanroept. De Invalidate methode roept op zijn beurt OnPaintaan. De methode Invalidate is overbelast en, afhankelijk van de argumenten die aan Invalidateeworden opgegeven, wordt een deel of al het schermgebied opnieuw getekend.

De code in de OnPaint-methode van uw besturingselement wordt uitgevoerd wanneer het besturingselement voor het eerst wordt getekend en telkens wanneer het wordt vernieuwd. Om ervoor te zorgen dat uw controle telkens opnieuw wordt getekend wanneer het formaat wordt gewijzigd, voegt u de volgende regel toe aan de constructor van uw controle:

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

OnPaintBackground

De basisklasse Control definieert een andere methode die handig is voor tekenen, de OnPaintBackground methode.

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

OnPaintBackground verft de achtergrond (en op die manier de vorm) van het venster en is gegarandeerd snel, terwijl OnPaint de details verft en langzamer kan zijn omdat afzonderlijke verfaanvragen worden gecombineerd tot één Paint gebeurtenis die alle gebieden omvat die opnieuw moeten worden getekend. U kunt de OnPaintBackground aanroepen als u bijvoorbeeld een kleurovergang als achtergrond voor uw controle wilt tekenen.

Hoewel OnPaintBackground een gebeurtenisachtige nomenclatuur heeft en hetzelfde argument als de methode OnPaint gebruikt, is OnPaintBackground geen echte gebeurtenismethode. Er is geen PaintBackground gebeurtenis en OnPaintBackground roept geen gedelegeerden voor gebeurtenissen aan. Bij het overschrijven van de OnPaintBackground methode is een afgeleide klasse niet vereist om de OnPaintBackground methode van de basisklasse aan te roepen.

GDI+ Basisbeginselen

De klasse Graphics biedt methoden voor het tekenen van verschillende vormen, zoals cirkels, driehoeken, bogen en weglatingstekens en methoden voor het weergeven van tekst. De System.Drawing naamruimte bevat naamruimten en klassen die grafische elementen inkapselen, zoals vormen (cirkels, rechthoeken, bogen en andere), kleuren, lettertypen, penselen enzovoort.

Geometrie van het tekengebied

De eigenschap ClientRectangle van een besturingselement specificeert de rechthoekige regio die beschikbaar is voor het besturingselement op het scherm van de gebruiker, terwijl de eigenschap ClipRectangle van PaintEventArgs het gebied specificeert dat is geverfd. Een besturingselement moet mogelijk slechts een deel van het beschikbare gebied schilderen, zoals het geval is wanneer een klein gedeelte van de weergave van het besturingselement verandert. In dergelijke situaties moet een ontwikkelaar voor bedieningselementen de werkelijke rechthoek berekenen om in te tekenen en deze doorgeven aan Invalidate. De overbelaste versies van Invalidate die een Rectangle of Region als argument hebben, gebruiken dat argument om de eigenschap ClipRectangle van PaintEventArgste genereren.

Grafische bronnen vrijmaken

Grafische objecten zijn duur omdat ze systeembronnen gebruiken. Dergelijke objecten omvatten exemplaren van de System.Drawing.Graphics klasse en exemplaren van System.Drawing.Brush, System.Drawing.Penen andere grafische klassen. Het is belangrijk dat u alleen een grafische resource maakt wanneer u deze nodig hebt en laat deze direct weer los zodra u klaar bent met het gebruik. Als u een exemplaar maakt van een type dat de IDisposable-interface implementeert, roept u de bijbehorende Dispose methode aan wanneer u hiermee klaar bent om resources vrij te maken.

Zie ook