Udostępnij przez


Malowanie i rysowanie na kontrolkach

Niestandardowe malowanie kontrolek jest jednym z wielu skomplikowanych zadań ułatwianych przez Windows Forms. Podczas tworzenia kontrolki niestandardowej dostępnych jest wiele opcji obsługi graficznego wyglądu kontrolki. Jeśli tworzysz kontrolkę niestandardową, to znaczy kontrolkę, która dziedziczy po Control, używasz kodu do renderowania jej graficznej reprezentacji.

Jeśli tworzysz kontrolkę złożoną, czyli kontrolkę dziedziczoną z jednej z UserControl, możesz zastąpić standardową graficzną reprezentację i dostarczyć własny kod graficzny.

Jeśli chcesz udostępnić renderowanie niestandardowe dla istniejącej kontrolki bez tworzenia nowej kontrolki, obsłuż zdarzenie Paint, które umożliwia rysowanie na kontrolce.

Następujące elementy są zaangażowane w renderowanie kontrolek:

  • Funkcje rysunku udostępniane przez klasę System.Windows.Forms.Controlbazową .
  • Podstawowe elementy biblioteki grafiki GDI.
  • Geometria regionu rysunku.
  • Procedura zwalniania zasobów graficznych.

Rysunek dostarczony przez kontrolkę

Klasa Control podstawowa udostępnia funkcje rysowania za pośrednictwem jego Paint zdarzenia. Kontrolka Paint zgłasza zdarzenie za każdym razem, gdy musi zaktualizować swój wyświetlacz i zakończyła jego rysowanie. Aby uzyskać więcej informacji na temat zdarzeń na platformie .NET, zobacz Obsługa i zgłaszanie zdarzeń.

Klasa danych dla zdarzenia PaintPaintEventArgs przechowuje informacje potrzebne do rysowania kontrolki. Obejmuje ona uchwyt do obiektu grafiki oraz prostokąt reprezentujący obszar do rysowania.

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 jest klasą zarządzaną, która hermetyzuje funkcje rysowania, zgodnie z opisem w dalszej części tego artykułu. Jest to wystąpienie struktury ClipRectangle, które definiuje dostępny obszar, w którym kontrolka może rysować. Deweloper kontrolki może obliczyć ClipRectangle przy użyciu właściwości ClipRectangle kontrolki, zgodnie z opisem w dalszej części tego artykułu.

OnPaint

Kontrolka musi zapewnić logikę renderowania, przesłaniając metodę OnPaint dziedziczoną z Control klasy. OnPaint uzyskuje dostęp do obiektu graficznego i prostokąta do rysowania poprzez właściwości Graphics i ClipRectangle wystąpienia PaintEventArgs przekazanego do metody.

Poniższy kod używa System.Drawing przestrzeni nazw:

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

Metoda OnPaint klasy bazowej Control nie implementuje żadnej funkcji rysowania, ale jedynie wywołuje delegatów zarejestrowanych przy zdarzeniu Paint. Po zastąpieniu OnPaint, zazwyczaj należy wywołać metodę OnPaint klasy bazowej, aby zarejestrowani delegaci mogli otrzymać zdarzenie Paint. Jednak kontrolki, które malują całą powierzchnię, nie powinny wywoływać klasy bazowej OnPaint, ponieważ wprowadza to migotanie.

Uwaga / Notatka

Nie należy wywoływać OnPaint bezpośrednio z kontrolki; zamiast tego wywołaj metodę Invalidate (dziedziczoną z klasy Control) lub inną funkcję, która wywołuje metodę Invalidate. Metoda Invalidate z kolei wywołuje metodę OnPaint. Metoda Invalidate jest przeciążona i, w zależności od argumentów dostarczonych do Invalidatee, ponownie rysuje część lub cały jej obszar ekranu.

Kod w metodzie OnPaint kontrolki zostanie wykonany, gdy kontrolka zostanie po raz pierwszy narysowana i za każdym razem, gdy zostanie odświeżona. Aby upewnić się, że kontrolka jest ponownie rysowana przy każdej zmianie rozmiaru, dodaj następujący wiersz do konstruktora kontrolki:

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

OnPaintBackground

Klasa bazowa Control definiuje inną metodę OnPaintBackground, która jest przydatna do rysowania.

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

OnPaintBackground maluje tło (i w ten sposób kształt) okna i gwarantuje szybkość, podczas gdy OnPaint maluje szczegóły i może być wolniejsze, ponieważ poszczególne żądania farby są łączone w jedno Paint zdarzenie, które obejmuje wszystkie obszary, które muszą być ponownie rysowane. Możesz wywołać metodę OnPaintBackground , jeśli na przykład chcesz narysować tło w kolorze gradientu dla kontrolki.

Chociaż OnPaintBackground ma nomenklaturę podobną do zdarzenia i przyjmuje ten sam argument co OnPaint metoda, OnPaintBackground nie jest to prawdziwa metoda zdarzenia. Brak zdarzenia PaintBackground i OnPaintBackground nie wywołuje delegatów zdarzeń. Podczas zastępowania OnPaintBackground metody klasa pochodna nie musi wywoływać OnPaintBackground metody klasy bazowej.

GDI+ Podstawy

Klasa Graphics udostępnia metody rysowania różnych kształtów, takich jak okręgi, trójkąty, łuki i wielokropek oraz metody wyświetlania tekstu. System.Drawing Przestrzeń nazw zawiera przestrzenie nazw i klasy, które hermetyzują elementy graficzne, takie jak kształty (okręgi, prostokąty, łuki i inne), kolory, czcionki, pędzle itd.

Geometria regionu rysunku

Właściwość ClientRectangle kontrolki określa prostokątny region dostępny dla kontrolki na ekranie użytkownika, podczas gdy ClipRectangle właściwość PaintEventArgs określa obszar, który jest malowany. Kontrolka może wymagać malowania tylko części dostępnego obszaru, tak jak w przypadku zmiany małej części ekranu kontrolki. W takich sytuacjach deweloper kontroli musi obliczyć rzeczywisty prostokąt do rysowania i przekazać go do Invalidate. Przeciążone wersje Invalidate, które przyjmują Rectangle lub Region jako argument, używają go do wygenerowania właściwości ClipRectangle dla PaintEventArgs.

Zwalnianie zasobów graficznych

Obiekty graficzne są kosztowne, ponieważ używają zasobów systemowych. Takie obiekty obejmują wystąpienia klasy System.Drawing.Graphics, wystąpienia klas System.Drawing.Brush, System.Drawing.Pen, i innych klas graficznych. Ważne jest, aby utworzyć zasób graficzny tylko wtedy, gdy jest potrzebny i zwolnić go zaraz po zakończeniu korzystania z niego. Jeśli utworzysz wystąpienie typu, który implementuje interfejs IDisposable, wywołaj jego metodę Dispose po zakończeniu pracy z nim, aby zwolnić zasoby.

Zobacz także

Niestandardowe kontrolki