17.5 Eigene Steuerelemente entwerfen
Egal, ob Sie ein Benutzersteuerelement entwerfen und sich dabei der Vorlage UserControl bedienen oder ob Sie sich an den objektorientierten Ansatz erinnern und ein vorhandenes sichtbares Steuerelement ableiten, in einem Punkt gleichen sich beide Verfahren: Die Grundlage bildet immer mindestens ein vorhandenes Steuerelement.
Natürlich können Sie auch ein Steuerelement von Grund auf entwickeln. Dann müssen Sie aber auch alles selbst in die Hand nehmen und codieren, womit insbesondere das vollständige Neuzeichnen gemeint ist.
Auch wenn selbst entworfene Steuerelemente nicht auf vorhandene sichtbare Steuerelemente aufbauen, wird uns ein nicht unwesentlicher Teil der Codierung abgenommen, denn alle Steuerelemente haben eine gemeinsame Basisklasse, in der die elementarsten Eigenschaften und Methoden vordefiniert sind: Control. Um davon zu profitieren, leiten Sie ganz einfach die Klasse ab. Angenommen, das neue Steuerelement soll ein Label sein, das die Beschriftung in vertikaler Ausrichtung anzeigt, so kann die Klasse folgendermaßen definiert sein:
Public Class VerticalLabel : Inherits Control
...
End Class
Die Ableitung von Control bewirkt, dass ein leerer Clientbereich auf der Form gezeichnet wird. Da das Steuerelement aber eine grafische Präsentation haben soll – in unserem Beispiel eine vertikale Textausrichtung –, müssen wir diese selbst zeichnen. Wir wissen, dass das Paint-Ereignis immer dann ausgelöst wird, wenn eine Komponente sich selbst neu zeichnen muss. Daher überschreiben wir die von Control geerbte Methode OnPaint, die die installierten Ereignishandler aufruft, und implementieren darin den erforderlichen Code.
Beim Zeichnen müssen wir berücksichtigen, dass die Beschriftung von unten nach oben ausgerichtet ist. Das bedeutet, wir müssen sie drehen. In Kapitel 15, »Grafiken mit GDI+«, haben Sie die dazu passende Methode kennengelernt: RotateTransform, deren positive Drehrichtung im Uhrzeigersinn ist. Doch um welchen Punkt soll gedreht werden? Wenn wir die Schrift von unten nach oben ausrichten wollen, ist der Drehpunkt der linke untere Eckpunkt des Steuerelements. Da alle Komponenten links oben ihren Ursprungspunkt haben, ist eine Verschiebung mit TranslateTransform unumgänglich.
Das Neuzeichnen des Benutzersteuerelements ist auch notwendig, wenn zur Entwurfszeit die Größe eines VerticalLabel-Objekts in einer Form verändert wird. Deshalb wird mittels Programmcode durch Aufruf von Invalidate im Resize-Ereignishandler das Paint-Ereignis ausgelöst. Bei der Instanziierung mittels Doppelklick in der Toolbox zeichnen sich Steuerelemente in einer vordefinierten Standardgröße in ihren Container. Diese legen wir in der Methode InitializeComponent fest. Sie ist 25 Pixel breit und 100 Pixel hoch.
Als wir weiter oben EllipseLabel entwickelt haben, konnten wir den Text im konstituierenden Label-Steuerelement speichern. Diese Möglichkeit haben wir jetzt nicht. Stattdessen müssen wir ein Feld auf Klassenebene deklarieren, das diese Aufgabe übernimmt. Das Feld soll lblText heißen und ist, um den Konventionen eines guten objektorientierten Ansatzes zu folgen, als Private deklariert. Die Eigenschaft Text veröffentlicht das Feld.
'...\Steuerelemente\Eigene\VerticalLabel.vb |
Public Class VerticalLabel : Inherits Control Public Sub New() InitializeComponent() End Sub Private Sub InitializeComponent() Me.Size = New Size(25, 100) ' Festlegen der Standardgröße im Designer End Sub Private Sub Neu(sender As Object, e As EventArgs) Handles Me.Resize Invalidate() End Sub Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs) Dim lblColor As Color = Color.Empty Dim txtColor As Color = MyBase.ForeColor MyBase.OnPaint(e) ' Rahmen zeichnen e.Graphics.FillRectangle(New SolidBrush(lblColor), 0, 0, Width, Height) ' Ursprungspunkt versetzen und drehen e.Graphics.TranslateTransform(0, Height) e.Graphics.RotateTransform(270) ' Text in das Steuerelement zeichnen e.Graphics.DrawString(lblText, Me.Font, New SolidBrush(txtColor), 0, 0) End Sub ' Veröffentlichen der Eigenschaft 'Text' Dim lblText As String Public Overrides Property Text() As String Get Return lblText End Get Set(ByVal value As String) lblText = value Invalidate() End Set End Property End Class
Ich hoffe, ich habe Ihnen Appetit auf mehr gemacht. Die gezeigten Beispiele sind bewusst einfach gehalten und kratzen nur an der Oberfläche.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.