Renderowanie formantu formularzy systemu Windows

Renderowanie odnosi się do procesu tworzenia reprezentacji wizualnej na ekranie użytkownika. Formularze systemu Windows używają interfejsu GDI (nowej biblioteki grafiki systemu Windows) do renderowania. Klasy zarządzane, które zapewniają dostęp do interfejsu System.Drawing GDI, znajdują się w przestrzeni nazw i jej podnazwach.

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.

Funkcje rysowania udostępniane przez kontrolkę

Klasa Control podstawowa udostępnia funkcje rysowania za pośrednictwem jego Paint zdarzenia. Kontrolka Paint wywołuje zdarzenie za każdym razem, gdy musi zaktualizować jego ekran. Aby uzyskać więcej informacji na temat zdarzeń w programie .NET Framework, zobacz Obsługa i podnoszenie zdarzeń.

Klasa danych zdarzenia dla Paint zdarzenia PaintEventArgs, przechowuje dane potrzebne do rysowania kontrolki — uchwyt do obiektu graficznego i prostokątny obiekt reprezentujący region do rysowania. Te obiekty są wyświetlane pogrubioną czcionką w poniższym fragcie kodu.

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

Kontrolka musi zapewnić logikę renderowania, przesłaniając metodę OnPaint dziedziczącą z Controlklasy . OnPaint uzyskuje dostęp do obiektu graficznego i prostokąta do rysowania za pomocą Graphics właściwości i ClipRectangle przekazanych PaintEventArgs do niego właściwości wystąpienia.

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

Metoda OnPaint klasy bazowej Control nie implementuje żadnych funkcji rysowania, ale jedynie wywołuje delegatów zdarzeń zarejestrowanych w Paint zdarzeniu. Po zastąpieniu OnPaintmetody zazwyczaj należy wywołać OnPaint metodę klasy bazowej, aby zarejestrowani delegaci otrzymywali Paint zdarzenie. Jednak kontrolki, które malują całą powierzchnię, nie powinny wywoływać klasy bazowej OnPaint, ponieważ wprowadza to migotanie. Aby zapoznać się z przykładem zastąpienia OnPaint zdarzenia, zobacz Instrukcje: tworzenie kontrolki Formularze systemu Windows pokazującej postęp.

Uwaga

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

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

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

OnPaintBackground maluje tło (a tym samym kształt) okna i gwarantuje szybkość, podczas gdy OnPaint maluje szczegóły i może być wolniejsza, 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 jest wymagana do wywołania 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, a także metody wyświetlania tekstu. System.Drawing Przestrzeń nazw i jej przestrzenie podrzędne zawierają klasy, które hermetyzują elementy graficzne, takie jak kształty (okręgi, prostokąty, łuki i inne), kolory, czcionki, pędzle itd. Aby uzyskać więcej informacji na temat interfejsu GDI, zobacz Using Managed Graphics Classes (Używanie zarządzanych klas grafiki). Podstawowe elementy interfejsu GDI zostały również opisane w temacie How to: Create a Windows Forms Control That Show Progress (Jak utworzyć kontrolkę Formularzy systemu Windows, która pokazuje postęp).

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 faktycznie malowany. (Pamiętaj, że malowanie odbywa się w metodzie Paint zdarzenia, która przyjmuje PaintEventArgs wystąpienie jako argument). 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, aby narysować obiekt i przekazać go do Invalidateelementu . Przeciążone wersje Invalidate elementu , które przyjmują Rectangle argument lub Region jako argument, używają tego argumentu do wygenerowania ClipRectangle właściwości PaintEventArgs.

Poniższy fragment kodu pokazuje, jak FlashTrackBar kontrolka niestandardowa oblicza prostokątny obszar do narysowania. Zmienna client określa ClipRectangle właściwość . Pełny przykład można znaleźć w temacie How to: Create a Windows Forms Control That Show Progress (Instrukcje: tworzenie kontrolki formularzy systemu Windows pokazującej postęp).

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)

Zwalnianie zasobów graficznych

Obiekty graficzne są kosztowne, ponieważ używają zasobów systemowych. Takie obiekty obejmują wystąpienia System.Drawing.Graphics klasy, a także wystąpienia System.Drawing.Brushklasy , System.Drawing.Peni 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 typ, który implementuje interfejs, wywołaj jego Dispose metodę po zakończeniu IDisposable pracy z nim, aby zwolnić zasoby.

Poniższy fragment kodu pokazuje, jak kontrolka niestandardowa FlashTrackBar tworzy i zwalnia Brush zasób. Aby uzyskać pełny kod źródłowy, zobacz Instrukcje: tworzenie kontrolki formularzy systemu Windows, która pokazuje postęp.

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

Zobacz też