Markieren Sie das Kontrollkästchen Englisch, um die englische Version dieses Artikels anzuzeigen. Sie können den englischen Text auch in einem Popup-Fenster einblenden, indem Sie den Mauszeiger über den Text bewegen.
Übersetzung
Englisch

Wiedergeben eines Windows Forms-Steuerelements

 

Als Rendering wird ein Prozess bezeichnet, durch den eine visuelle Repräsentation auf dem Bildschirm eines Benutzers erzeugt wird. Windows Forms verwendet zum Rendern GDI (die neue Windows-Graphikbibliothek). Die verwalteten Klassen, die den Zugriff auf GDI ermöglichen, befinden sich im System.Drawing-Namespace und in dessen untergeordneten Namespaces.

Die folgenden Elemente spielen beim Rendern von Steuerelementen eine Rolle:

  • Die Zeichnungsfunktionalität, die von der System.Windows.Forms.Control-Basisklasse bereitgestellt wird.

  • Die wichtigsten Elemente der GDI-Graphikbibliothek.

  • Die Geometrie des Bereichs, in dem gezeichnet wird.

  • Das Verfahren, mit dem Graphikressourcen freigegeben werden.

Die Control-Basisklasse stellt über das Paint-Ereignis Zeichnungsfunktionalität bereit. Ein Steuerelement löst das Paint-Ereignis immer dann aus, wenn seine Anzeige aktualisiert werden muss. Weitere Informationen über Ereignisse in .NET Framework finden Sie unter Behandeln und Auslösen von Ereignissen.

Die Ereignisdatenklasse für das Paint-Ereignis, PaintEventArgs, beinhaltet die Daten, die für das Zeichnen des Steuerelements benötigt werden – ein Handle eines Graphikobjekts und ein rechteckiges Objekt, das den Bereich darstellt, in dem gezeichnet wird. Diese Objekte sind im folgenden Codefragment fett dargestellt.

public class PaintEventArgs : EventArgs, IDisposable {
public System.Drawing.Rectangle ClipRectangle {get;}
public System.Drawing.Graphics Graphics {get;}
// Other properties and methods.
...
}

Graphics ist eine verwaltete Klasse, die Zeichnungsfunktionen kapselt. Dies wird im Abschnitt zu GDI weiter unten in diesem Thema beschrieben. ClipRectangle ist eine Instanz der Rectangle-Struktur und definiert den verfügbaren Bereich, in dem ein Steuerelement zeichnen kann. Der Entwickler eines Steuerelements kann ClipRectangle mithilfe der ClipRectangle-Eigenschaft eines Steuerelements berechnen. Dies wird weiter unten im Abschnitt zur Geometrie beschrieben.

Ein Steuerelement muss Renderlogik bereitstellen, indem die OnPaint-Methode, die es von Control erbt, überschrieben wird. OnPaint erhält mithilfe der Graphics-Eigenschaft und der ClipRectangle-Eigenschaft der übergebenen PaintEventArgs-Instanz Zugriff auf ein Graphikobjekt und ein Rechteck, in dem gezeichnet werden soll.

protected virtual void OnPaint(PaintEventArgs pe);

Die OnPaint-Methode der Basisklasse von Control implementiert keine Zeichnungsfunktionen, sondern ruft lediglich die Ereignisdelegaten auf, die mit dem Paint-Ereignis registriert sind. Beim Überschreiben von OnPaint sollten Sie im Normalfall die OnPaint-Methode der Basisklasse aufrufen, sodass registrierte Delegaten das Paint-Ereignis empfangen. Allerdings sollten Steuerelemente, die ihre gesamte Oberfläche zeichnen, nicht die OnPaint-Methode der Basisklasse aufrufen, um Flimmern zu vermeiden. Ein Beispiel zum Überschreiben des OnPaint-Ereignisses finden Sie unter Gewusst wie: Erstellen eines Windows Forms-Steuerelements, das den Fortschritt anzeigt.

System_CAPS_noteHinweis

Rufen Sie OnPaint nicht direkt über das Steuerelement auf, sondern über die von Control geerbte Invalidate-Methode oder eine andere Methode, die Invalidate aufruft. Die Invalidate-Methode ruft wiederum OnPaint auf. Die Invalidate-Methode wird überladen. Ein Steuerelement zeichnet abhängig von den für Invalidate angegebenen Argumenten seinen Bildschirmbereich teilweise oder vollständig neu.

Durch die Basisklasse von Control wird eine andere Methode definiert, die für das Zeichnen von Nutzen ist: die OnPaintBackground-Methode.

protected virtual void OnPaintBackground(PaintEventArgs pevent);

Mit OnPaintBackground wird der Hintergrund (und dadurch auch die Form) des Fensters gezeichnet und schnelles Vorgehen gewährleistet. Dagegen dient OnPaint dem Zeichnen von Details, wodurch diese Methode langsamer ist, da einzelne Anforderungen zum Zeichnen in einem Paint-Ereignis zusammengefasst werden, das alle erneut zu zeichnenden Bereiche abdeckt. Sie können OnPaintBackground z. B. dann aufrufen, wenn Sie für das Steuerelement einen Hintergrund mit Farbverlauf zeichnen möchten.

Obwohl OnPaintBackground Bezeichnungen verwendet, die der einer Ereignismethode ähnlich sind, und sie dasselbe Argument wie die OnPaint-Methode unterstützt, ist OnPaintBackground dennoch keine Ereignismethode. Es gibt kein PaintBackground-Ereignis, und von OnPaintBackground werden keine Ereignisdelegaten aufgerufen. Beim Überschreiben der OnPaintBackground-Methode ist es nicht notwendig, dass die abgeleitete Klasse die OnPaintBackground-Methode ihrer Basisklasse aufruft.

Die Graphics-Klasse stellt Methoden zum Zeichnen verschiedener Formen, z. B. von Kreisen, Dreiecken, Bögen und Ellipsen, sowie Methoden zum Anzeigen von Text zur Verfügung. Der System.Drawing-Namespace und seine untergeordneten Namespaces enthalten Klassen, die grafische Elemente wie Formen (Kreise, Rechtecke, Bögen u. a.), Farben, Schriftarten, Pinsel usw. umfassen. Weitere Informationen zu GDI finden Sie unter Verwenden von verwalteten Grafikklassen. Die wichtigsten Aspekte von GDI werden zudem unter Gewusst wie: Erstellen eines Windows Forms-Steuerelements, das den Fortschritt anzeigt beschrieben.

Die ClientRectangle-Eigenschaft eines Steuerelements legt den rechteckigen Bereich fest, der für das Steuerelement auf dem Bildschirm des Benutzers verfügbar ist, während die ClipRectangle-Eigenschaft von PaintEventArgs den Bereich festlegt, der tatsächlich gezeichnet wird. (Beachten Sie, dass das Zeichnen durch die Paint-Ereignismethode erfolgt, die eine PaintEventArgs-Instanz als Argument verwendet). Ein Steuerelement muss seinen verfügbaren Bereich möglicherweise nur teilweise zeichnen, z. B. dann, wenn nur ein kleiner Ausschnitt des angezeigten Steuerelements geändert wird. In solchen Fällen muss der Entwickler des Steuerelements das tatsächlich zu zeichnende Rechteck berechnen und es an Invalidate weitergeben. Die überladenen Versionen von Invalidate, die ein Rectangle oder einen Region als Argument verwenden, generieren hiermit die ClipRectangle-Eigenschaft von PaintEventArgs.

Im folgenden Codefragment wird gezeigt, wie das benutzerdefinierte Steuerelement FlashTrackBar den rechteckigen Bereich berechnet, in dem gezeichnet werden soll. Die client-Variable kennzeichnet die ClipRectangle-Eigenschaft. Ein vollständiges Beispiel finden Sie unter Gewusst wie: Erstellen eines Windows Forms-Steuerelements, das den Fortschritt anzeigt.

Rectangle invalid = new Rectangle(
    client.X + min, 
    client.Y, 
    max - min, 
    client.Height);

Invalidate(invalid);

Die Verwendung graphischer Objekte ist aufwendig, da diese Systemressourcen verwenden. Zu diesen Objekten gehören Instanzen der System.Drawing.Graphics-Klasse sowie Instanzen von System.Drawing.Brush, System.Drawing.Pen und anderen Graphikklassen. Es ist wichtig, dass Sie eine graphische Ressource nur bei Bedarf erstellen und diese wieder freigeben, sobald sie nicht mehr verwendet wird. Wenn Sie einen Typ erstellen, der die IDisposable-Schnittstelle implementiert, rufen Sie seine Dispose-Methode auf, sobald er nicht mehr verwendet wird, um Ressourcen freizugeben.

Im folgendem Codefragment wird gezeigt, wie durch das benutzerdefinierte FlashTrackBar-Steuerelement eine Brush-Ressource erstellt und wieder freigegeben wird. Den vollständigen Quellcode finden Sie unter Gewusst wie: Erstellen eines Windows Forms-Steuerelements, das den Fortschritt anzeigt.


  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
Anzeigen: