Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einführung
2 Grundlagen der Sprachsyntax
3 Klassendesign
4 Weitere Datentypen
5 Multithreading
6 Collections und LINQ
7 Eingabe und Ausgabe
8 Anwendungen: Struktur und Installation
9 Code erstellen und debuggen
10 Einige Basisklassen
11 Windows-Anwendungen erstellen
12 Die wichtigsten Steuerelemente
13 Tastatur- und Mausereignisse
14 MDI-Anwendungen
15 Grafiken mit GDI+
16 Drucken
17 Entwickeln von Steuerelementen
18 Programmiertechniken
19 WPF – Grundlagen
20 Layoutcontainer
21 WPF-Steuerelemente
22 Konzepte von WPF
23 Datenbankverbindung mit ADO.NET
24 Datenbankabfragen mit ADO.NET
25 DataAdapter
26 Offline mit DataSet
27 Datenbanken aktualisieren
28 Stark typisierte DataSets
A Anhang: Einige Übersichten
Stichwort

Jetzt Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual Basic 2008 von Andreas Kuehnel, Stephan Leibbrandt
Das umfassende Handbuch
Buch: Visual Basic 2008

Visual Basic 2008
3., aktualisierte und erweiterte Auflage, geb., mit DVD
1.323 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1171-0
Pfeil 17 Entwickeln von Steuerelementen
Pfeil 17.1 Entwicklungsszenarien
Pfeil 17.2 Testen eines Steuerelements
Pfeil 17.3 Steuerelemente mit UserControl
Pfeil 17.3.1 Definition eines Benutzersteuerelements
Pfeil 17.3.2 Eigenschaften eines Benutzersteuerelements
Pfeil 17.3.3 Attribute eines Benutzersteuerelements
Pfeil 17.3.4 Ereignisse eines Benutzersteuerelements
Pfeil 17.3.5 Bereitstellen einer Toolbox-Bitmap
Pfeil 17.3.6 Code für EllipseLabel
Pfeil 17.4 Ein Steuerelement von einem vorhandenen ableiten
Pfeil 17.5 Eigene Steuerelemente entwerfen


Rheinwerk Computing - Zum Seitenanfang

17.3 Steuerelemente mit UserControl Zur nächsten ÜberschriftZur vorigen Überschrift

Um aus einem oder mehreren vorhandenen Steuerelementen ein neues Steuerelement zu erzeugen, müssen Sie ein Projekt vom Typ Windows Forms-Steuerelementbibliothek anlegen (siehe Abbildung 17.2). Dazu sollten Sie der Projektmappe einen anderen Namen geben als dem Projekt des Steuerelements. Wenn Sie später zu Testzwecken der Projektmappe eine Windows-Anwendung hinzufügen, erleichtern Sie sich die Entwicklungsarbeit durch eine klare Trennung der jeweiligen Projektdateien.

Abbildung 17.2 Projekttyp Windows Forms-Steuerelementbibliothek


Hinweis
Wenn Sie einem Projekt direkt ein eigenes Steuerelement hinzufügen, ist es nur in diesem Projekt nutzbar – andere Projekte bleiben außen vor. Nur als Bibliothek können andere Projekte es nutzen.


Die Entwicklungsumgebung zeigt im Designer eine Ansicht, die an eine Form ohne Rahmen und Titelleiste erinnert. Dies ist bereits das neue Steuerelement, obwohl es weder spezifische Fähigkeiten noch eine optisch erkennbare Oberfläche hat. Die angezeigte Fläche dient dazu, die Steuerelemente aufzunehmen, aus denen sich das neue Steuerelement zusammensetzt.

Der Klassenname und damit auch der Typ des Steuerelements lautet zunächst UserControl1. Wenn Sie sich jetzt die Toolbox ansehen, werden Sie feststellen, dass eine weitere Lasche angezeigt wird: Eigene Benutzersteuerelemente. (Dazu müssen Sie gegebenenfalls das Projekt über das Menü Erstellen neu übersetzen.) In dieser Lasche wird bereits das neue Steuer-element deaktiviert angezeigt (gegebenenfalls müssen Sie über das Kontextmenü der Lasche alle Elemente anzeigen lassen). Die Typangabe UserControl1 wird übernommen und sollte deshalb durch eine passendere ersetzt werden.

Die Implementierung des Benutzersteuerelements muss während der Entwicklungsphase natürlich dauernd getestet werden. Dazu sollte die Projektmappe von Anfang an durch ein Projekt des Typs Windows Forms-Anwendung ergänzt werden. Damit dieses und nicht die Steuerelementbibliothek gestartet wird, müssen Sie noch im Kontextmenü der Windows-Anwendung Als Startprojekt festlegen auswählen.


Hinweis
Die Deklaration Implements UserControl finden Sie in dem vom Designer generierten Teil der partiellen Klasse.



Rheinwerk Computing - Zum Seitenanfang

17.3.1 Definition eines Benutzersteuerelements Zur nächsten ÜberschriftZur vorigen Überschrift

Wir wollen uns im Folgenden die Entwicklung eines Benutzersteuerelements an einem konkreten Beispiel ansehen. Das neue Steuerelement soll relativ einfach sein und das herkömmliche Label erweitern. Um den angezeigten Text wird eine Ellipse in einem beliebigen Farbton gezeichnet. Das neue Steuerelement, dessen Typbezeichner EllipseLabel lautet, löst unter anderem das Click-Ereignis aus, wenn sich der Mauszeiger in der Ellipse befindet.

Grafische Oberfläche

Die Steuerelemente, aus denen sich ein Benutzersteuerelement zusammensetzt, werden als konstituierende Steuerelemente bezeichnet. Unser neues Steuerelement enthält nur eines, nämlich ein Label, das beliebig auf der Oberfläche positioniert werden darf. Zur Laufzeit wird dessen Beschriftung zentral im Steuerelement angezeigt. Das können wir aber nur mittels Programmcode erreichen, weil zur Entwurfszeit weder die Abmessungen des EllipseLabel-Objekts noch die Textlänge bekannt ist. Allerdings muss die Eigenschaft AutoSize=True gesetzt werden, um sicherzustellen, dass sich die Abmessung des Labels automatisch der Beschriftung anpasst.

Konstituierende Steuerelemente sind Komponenten des Benutzersteuerelements, auf die ein Entwickler (also derjenige, der das fertige Steuerelement einsetzt) keinen Zugriff haben sollte. Die Sichtbarkeit ist daher meistens Private. Soll das Benutzersteuerelement später möglicherweise abgeleitet werden, muss das Label auch in der abgeleiteten Klasse sichtbar sein und der Modifizierer Protected sein.

Public Class EllipseLabel 
  Protected TextLabel As Label 
  ... 
End Class

Die gefüllte Ellipse soll an den vier Rändern des Steuerelements anstoßen. Wie bei anderen Komponenten auch ist das Ereignis Paint des Benutzersteuerelements der richtige Ort für alle Zeichenoperationen. Mit der Methode FillEllipse zeichnen wir die Ellipse. Die Farbfüllung wird durch die Referenz fillColor vom Typ SolidBrush beschrieben und auf Klassenebene festgelegt. Die Standardfarbe ist Blau.

Protected fillCol As New SolidBrush(Color.Blue)

Im Paint-Ereignis des Benutzersteuerelements wird auch die Zeichenfolge des Labels ausgerichtet. Dazu werden zuerst die Koordinaten des Ursprungspunktes ermittelt, die anschließend der Eigenschaft Location als Point-Referenz übergeben werden.

Private Sub Grafik(sender As Object, e As PaintEventArgs) Handles Me.Paint 
  Dim g As Graphics = e.Graphics 
  g.FillEllipse(fillCol, 0, 0, ClientSize.Width, ClientSize.Height) 
  Dim x As Integer = (ClientSize.Width – TextLabel.ClientSize.Width) / 2 
  Dim y As Integer = (ClientSize.Height – TextLabel.ClientSize.Height) / 2 
  TextLabel.Location = New Point(x, y) 
End Sub

Nun soll das Benutzersteuerelement zum ersten Mal in der Windows-Testanwendung ausprobiert werden. Voraussetzung ist eine Kompilierung (Menü Erstellen). Anschließend ergänzen Sie die Projektmappe um ein Windows Forms-Projekt und geben den Verweis auf das Steuerelementprojekt an. Dazu aktivieren Sie unter Verweis hinzufügen die Registerkarte Projekte, in der das Projekt des Benutzersteuerelements bereits aufgeführt ist.

Wenn Sie das Benutzersteuerelement aus der Toolbox in die Form der Windows Forms-Anwendung ziehen, werden zwar die Ellipse und die Beschriftung des Labels angezeigt, eine Größenänderung hat aber zur Folge, dass nicht der gesamte Bereich des Benutzersteuerelements neu gezeichnet wird, sondern nur der neu hinzugekommene (zu sehen zum Beispiel bei angedockter Ellipse). Vermeiden lässt sich dieser Effekt mit der Einstellung True der Eigenschaft ResizeRedraw des Benutzersteuerelements, zum Beispiel im Load-Ereignis.

Private Sub Laden(sender As Object, e As EventArgs) Handles MyBase.Load 
  ResizeRedraw = True 
End Sub

Soll das Benutzersteuerelement nach dieser Änderung erneut getestet werden, dürfen Sie nicht vergessen, es zuerst neu zu kompilieren, damit die Änderungen wirksam werden. Das Ergebnis ist jetzt schon erfreulicher, denn die Ellipse passt sich den Abmessungen des sie umgebenden rechteckigen Arbeitsbereichs automatisch an.

Feinschliff der grafischen Anzeige

Sehen wir uns die Instanz des Benutzersteuerelements in der Form kritisch an. Was sofort auffällt, ist, dass die Hintergrundfarbe des Labels der Hintergrundfarbe der Form entspricht. Das sollte natürlich nicht der Fall sein, denn die Farbe sollte sich der Farbe der umgebenden Ellipse anpassen. Außerdem tritt beim schnellen Verändern der Größe des EllipseLabel-Objekts ein unangenehmes Flimmern auf. Beide Effekte sollen nun beseitigt werden. In diesem Zusammenhang lernen wir eine neue Methode der Control-Klasse kennen, die uns bisher noch nicht begegnet ist: Es ist die geschützt definierte Methode SetStyle.


Protected Sub SetStyle(ByVal flag As ControlStyles, ByVal value As Boolean)

ControlStyles beeinflusst das Verhalten und die Darstellung eines Steuerelements. Es ist eine Enumeration, die über das Flags-Attribut verfügt. Die in Tabelle 17.1 gezeigten einzelnen Konstanten können bitweise miteinander kombiniert werden. Der zweite Parameter gibt an, ob die angeführten Formatbits gesetzt werden sollen (True) oder nicht (False).


Tabelle 17.1 Die Enumeration »ControlStyles«

Konstante Beschreibung

AllPaintingInWmPaint

Flimmerreduktion, nur sinnvoll mit UserPaint.

CacheText

Bessere Leistung bei erschwerter Textsynchronisierung.

ContainerControl

Element ist zugleich Steuerelementcontainer.

DoubleBuffer

Zeichenoperation wird vollständig gepuffert, wenn die Bits UserPaint und AllPaintingInWmPaint gesetzt sind.

EnableNotifyMessage

Dient zum Abfangen von Windows-Fenstermeldungen.

FixedHeight

Elementhöhe bleibt bei Skalierung erhalten.

FixedWidth

Elementbreite bleibt bei Skalierung erhalten.

Opaque

Gibt an, ob das Element nicht transparent ist.

OptimizedDoubleBuffer

Flimmerreduktion, sinnvoll in Kombination mit AllPaintingInWmPaint.

ResizeRedraw

Das Element wird bei einer Größenänderung neu gezeichnet.

Selectable

Das Element kann den Fokus erhalten.

StandardClick

Das Element implementiert das Standard-Click-Verhalten.

StandardDoubleClick

Das Element implementiert das Standard-DoubleClick-Verhalten, falls StandardClick nicht gesetzt ist.

SupportsTransparentBackColor

Das Element simuliert Transparenz.

UserMouse

Mausereignisse werden nicht vom Betriebssystem behandelt, sondern vom Elemernt.

UserPaint

Das Element zeichnet sich selbst, nicht das Betriebssystem.

UseTextForAccessibility

Die Text-Eigenschaft wird für Funktionen zur Barrierefreiheit verwendet.


Mit SetStyle werden die Formatbits festgelegt, und mit GetStyle kann bei Bedarf der Zustand eines bestimmten Bits abgerufen werden:


Protected Function GetStyle(ByVal flag As ControlStyles) As Boolean

Mit den Formatbits können wir sowohl das Flimmern vermeiden als auch das Neuzeichnen bei Größenänderung erzwingen, sodass die Zuweisung an ResizeRedraw entfällt. Zum Schluss wird noch die Hintergrundfarbe auf Color.Transparent festgelegt.

Private Sub Laden(sender As Object, e As EventArgs) Handles MyBase.Load 
  Me.SetStyle(ControlStyles.DoubleBuffer Or ControlStyles.UserPaint Or _ 
    ControlStyles.AllPaintingInWmPaint Or _ 
    ControlStyles.SupportsTransparentBackColor Or _ 
    ControlStyles.ResizeRedraw, True) 
  Me.BackColor = Color.Transparent 
End Sub

Rheinwerk Computing - Zum Seitenanfang

17.3.2 Eigenschaften eines Benutzersteuerelements Zur nächsten ÜberschriftZur vorigen Überschrift

Das Benutzersteuerelement erbt von Control bereits eine stattliche Anzahl von Eigenschaften, wie im Eigenschaftsfenster der Hostanwendung zu sehen ist. Beispielsweise können wir das Steuerelement andocken und sogar die Schriftfarbe mit der Eigenschaft ForeColor ändern, ohne eine Zeile Programmcode schreiben zu müssen. Natürlich soll unser Steuerelement auch eigene, spezifische Eigenschaften aufweisen. Wir werden unser Steuerelement um zwei Eigenschaften erweitern. Die erste Eigenschaft ist Text und dient dazu, die Beschriftung zu ändern. Mit der zweiten, FillColor, kann der Anwender eine andere Füllfarbe der Ellipse festlegen.

Die Eigenschaft Text wird durch die Klasse Control an die Klasse UserControl vererbt. Wir müssen sie daher nur passend überschreiben. Was die Eigenschaft Text anzeigen soll, ist der Inhalt der Text-Eigenschaft des Label-Steuerelements, die jedoch nicht direkt von außen manipuliert werden kann, weil das konstituierende Steuerelement privat deklariert ist. Daher leiten wir die Aufrufe an die Eigenschaft Text des Benutzersteuerelements nur an den entsprechenden Accessor weiter.

Public Overrides Property Text() As String 
  Get 
    Return TextLabel.Text 
  End Get 
  Set(ByVal value As String) 
    TextLabel.Text = value 
  End Set 
End Property

Es erweist sich hier als vorteilhaft, dass wir die Eigenschaft AutoSize des Labels auf True gesetzt haben, denn bei einer Änderung der Zeichenfolge passt sich die Größe des Labels automatisch an. Das hat auch zur Folge, dass das Paint-Ereignis des Benutzersteuerelements aufgerufen und das Label neu zentriert wird.

Die Eigenschaft FillColor zum Ändern der Füllfarbe kann nicht von einer Eigenschaft des Labels profitieren. Weiter oben hatten wir deshalb die Variable fillCol vom Typ SolidBrush deklariert und eine blaue Füllfarbe zum Standard gemacht. Mit FillColor ermöglichen wir nun dem Anwender, die Farbe nach eigenen Vorstellungen festzulegen. Damit sich die Änderungen sofort in der Hostanwendung auswirken, müssen wir hier das Paint-Ereignis manuell auslösen.

Public Property FillColor() As Color 
  Get 
    Return fillCol.Color 
  End Get 
  Set(ByVal value As Color) 
    fillCol.Color = value 
    Invalidate() 
  End Set 
End Property

Nach diesen beiden Ergänzungen sollten wir das Steuerelement kompilieren und in der Hostanwendung testen. Dabei interessiert insbesondere das Eigenschaftsfenster der Steuerelement-instanz.

Die Eigenschaft FillColor bietet bei einer beabsichtigten Änderung sofort den bekannten Auswahldialog für Farben an. Das ist schon mehr, als zu vermuten war. Die Wahl einer Farbe ist sofort im Designer zu sehen. Es fallen aber auch noch zwei andere Dinge auf. Am Fußende des Eigenschaftsfensters wird normalerweise eine Kurzbeschreibung der markierten Eigenschaft angezeigt. Die Beschreibung von FillColor ist allerdings leer. Außerdem wird FillColor bei einer kategorisierten Eigenschaftsanzeige unter der Kategorie Sonstiges aufgeführt, obwohl die Kategorie Darstellung dazu besser geeignet wäre.

Die Eigenschaft Text werden Sie im Eigenschaftsfenster vergeblich suchen. Sie wird nicht angezeigt. Somit besteht bei dem augenblicklichen Entwicklungsstand auch keine Möglichkeit, die Beschriftung des Steuerelements im Eigenschaftsfenster zu ändern. Lassen Sie sich andererseits im Codeeditor die IntelliSense-Liste der EllipseLabel-Instanz anzeigen, können Sie der Eigenschaft einen anderen Wert zuweisen.

Einer dritten Eigenschaft sollten wir auch noch Beachtung schenken. Es ist BackColor. Voreingestellt ist Transparent, aber die Wahl einer anderen Hintergrundfarbe, die von der Hintergrundfarbe der Form abweicht, ist durchaus möglich. Das wollen wir abschalten.


Rheinwerk Computing - Zum Seitenanfang

17.3.3 Attribute eines Benutzersteuerelements Zur nächsten ÜberschriftZur vorigen Überschrift

Damit stehen wir vor einigen Problemen, die gelöst werden müssen. Das .NET Framework bietet dazu zahlreiche Attribute an, mit denen das Verhalten eines Benutzersteuerelements in der Hostanwendung beeinflusst werden kann. Tabelle 17.2 zeigt einige Attribute, die im Zusammenhang mit der Entwicklung eines Benutzersteuerelements besonders wichtig sind.


Tabelle 17.2 Attribute eines Benutzersteuerelements (Auszug)

Attribut Beschreibung

Browsable

Gibt an, ob eine Eigenschaft im Eigenschaftsfenster angezeigt wird.

Category

Gibt an, welcher Kategorie die Eigenschaft im Eigenschaftsfenster zugeordnet ist. Vordefinierte Kategorien können Sie durch eigene ergänzen.

Description

Am Fuß des Eigenschaftsfensters eingeblendeter Hilfetext

DefaultEvent

Standardereignis, auf dessen Handler beim Doppelklick auf das Steuerelement im Designer gesprungen wird

DefaultProperty

Standardeigenschaft, auf die beim Klick auf das Steuerelement im Designer gesprungen wird

DefaultValue

Standardwert einer Eigenschaft

EditorBrowsable

Gibt an, ob ein Klassenmitglied in der IntelliSense-Liste auftaucht.

RefreshProperties

Art der Aktualisierung des Designers bei einer Eigenschaftsänderung


Diese Liste dieser im Namensraum System.ComponentModel enthaltenen Attribute ist nicht vollständig, vermittelt aber schon einen Eindruck von der weitgehenden Kontrolle. Wir werden im Laufe dieses Kapitels weitere Attribute benutzen.

Anpassen der Eigenschaften von EllipseLabel

Wir versehen nun die drei Eigenschaften BackColor, FillColor und Text mit Attributen.

Fangen wir mit BackColor an. Diese Eigenschaft wird im Eigenschaftsfenster aufgelistet und ist damit leider auch editierbar. Zum Ausblenden reicht das Attribut Browsable bereits aus, aber dann kann auf die Eigenschaft immer noch über die IntelliSense-Liste des Codeeditors zugegriffen werden. Daher ist zusätzlich auch das Attribut EditorBrowsable erforderlich, dessen Konstruktor ein Argument vom Typ der Enumeration EditorBrowsableState übergeben wird. Von den drei Konstanten Advanced, Always und Never verwenden wir die letzte.

Da wir nun an der geerbten Verhaltensweise Änderungen vornehmen, muss die Eigenschaft BackColor überschrieben werden, auf die wir über MyBase zugreifen.

<EditorBrowsable(EditorBrowsableState.Never)> _ 
<Browsable(False)> _ 
Public Overrides Property BackColor() As Color 
  Get 
    Return MyBase.BackColor 
  End Get 
  Set(ByVal value As Color) 
    MyBase.BackColor = value 
  End Set 
End Property

FillColor wird wie gewünscht im Eigenschaftsfenster und in der IntelliSense-Liste angezeigt. Der Eigenschaft geben wir die beiden Attribute Category und Description. Bei Category darf die englische Bezeichnung der Kategorie verwendet werden, Sie können aber durchaus auch eine eigene Kategorie kreieren. An der Codeimplementierung von FillColor ändert sich nichts.

<Description("Legt die Füllfarbe der Ellipse fest")> _ 
<Category("Appearance")> _ 
Public Property FillColor() As Color 
  ... 
End Property

Im Eigenschaftsfenster wird die Eigenschaft Text nicht angezeigt, deshalb müssen wir das Attribut Browsable auf den Wert True setzen:

<Browsable(True)> _ 
Public Overrides Property Text() As String 
  ... 
End Property

Wird das Benutzersteuerelement jetzt kompiliert und die Hostanwendung gestartet, werden Sie mit einem neuen Problem konfrontiert: Die Einstellung der Eigenschaft Text wird nach dem Start nicht beibehalten, sondern nimmt die Einstellung der Text-Eigenschaft des Labels an. Anscheinend gewährleistet die von Control geerbte Eigenschaft Text nicht, dass die Zeichenfolge zur Laufzeit zur Verfügung steht. Die Kontrolle über die Speicherung von Werten gibt Ihnen das DesignerSerializationVisibility-Attribut.

Dem Konstruktor des Attributs muss eine der drei Konstanten der gleichnamigen Enumeration übergeben werden: Content, Hidden oder Visible. Mit Visible wird der Wert der Eigenschaft im vom Designer generierten Code gespeichert, mit Hidden wird dies unterdrückt (so ist es für die Eigenschaft Text in Control gesetzt), und mit Content wird zwar der Wert der Eigenschaft, aber nicht die Eigenschaft selbst serialisiert (Erfassung von Untereigenschaften, ungeeignet für primitive Datentypen).

Damit lautet die endgültige Fassung der Eigenschaft Text wie folgt:

<Browsable(True)> _ 
<DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _ 
Public Overrides Property Text() As String 
  ... 
End Property

Nachdem wir nun einige Klippen überwunden haben, ist es Zeit für einige positive Feststellungen. Ziehen wir das Steuerelement auf eine Form, wird automatisch ein Bezeichner vergeben, der der üblichen Namenskonvention entspricht: Dem Typ des Steuerelements folgt eine Zahl.

Von der Eigenschaft Text aller üblichen Steuerelemente her sind wir es gewohnt, dass, nachdem das Steuerelement auf die Form gezogen wurde, der Bezeichner des Steuerelements dem Inhalt der Text-Eigenschaft entspricht. Auch in dieser Hinsicht benötigen wir keinen weiteren Programmcode; das UserControl nimmt uns das automatisch ab.


Rheinwerk Computing - Zum Seitenanfang

17.3.4 Ereignisse eines Benutzersteuerelements Zur nächsten ÜberschriftZur vorigen Überschrift

Das Steuerelement soll nun auch ein Click-Ereignis bereitstellen. Standardmäßig wird das Ereignis bereits von Control geerbt und ausgelöst, wenn der Anwender auf das Steuerelement klickt. Dazu gehört natürlich auch der Bereich, der in der Hintergrundfarbe der Form angezeigt wird und streng genommen nicht dem Steuerelement zuzuordnen ist. Diesen Bereich auszusparen ist kein großes Problem. Dazu muss man nur untersuchen, ob die Farbe des Punktes, auf den geklickt wird, der Farbe des Benutzersteuerelements entspricht.

Da Click keine Mauskoordinaten bereitstellt, könnten wir uns die Bildschirmkoordinaten des Mauszeigers mit der statischen Methode MousePosition der Klasse Control besorgen und diese der Methode PointToClient übergeben, die die Bildschirmkoordinaten in Koordinaten der Komponente umrechnet.

Der Test, ob ein Punkt als Teil des Steuerelements betrachtet wird, kann wie folgt implementiert werden:

Private Function Treffer(ByVal x As Integer, ByVal y As Integer) As Boolean 
  Return (2 * x / Width – 1) ^ 2 + (2 * y / Height – 1) ^ 2 <= 1 
End Function

Nun können wir die geerbte Methode OnClick überschreiben. Liegt ein Treffer vor, wird der Aufruf an die Basiskomponente weitergeleitet.

Protected Overrides Sub OnClick(e As EventArgs e) 
  Dim pt As Point = Me.PointToClient(Control.MousePosition) 
  If Treffer(pt.X, pt.Y) Then base.OnClick(e) 
End Sub

Wir haben schon garantiert, dass das Click-Ereignis nicht im transparenten Bereich ausgelöst wird. Trotzdem weist dieser Ansatz noch zwei Lücken auf:

  • Trifft der Klick das konstituierende Steuerelement, ist nicht das UserControl, sondern das Label Empfänger des Click-Ereignisses.
  • Mausklicks in den transparenten Bereich sollten an die Hostanwendung weitergereicht werden.

Die Lösung des ersten Kritikpunkts ist nicht schwierig, denn dazu müssen wir das steuerelementinterne Click-Ereignis des Labels nur an die Methode OnClick des Benutzersteuerelements weiterleiten, die sich um die Verarbeitung des Ereignisses kümmert.

Private Sub Innen(sender As Object, e As EventArgs) Handles TextLabel.Click 
  Me.OnClick(e) 
End Sub

Der zweite Punkt ist etwas kniffliger. Einen Klick außerhalb der Ellipse können wir nicht direkt an die OnClick-Methode der Form weiterleiten, da die Methode geschützt und nicht von außerhalb aufrufbar ist. Ein anderer Weg führt über die Eigenschaft Region in Control.


Public Property [Region] As Region

Die Eigenschaft ordnet dem Steuerelement einen bestimmten Fensterbereich zu. Beschrieben wird der Fensterbereich durch ein Region-Objekt, dessen Konstruktor ein GraphicPath-Objekt erwartet. Letzteres definiert endgültig den Umriss des Fensterbereichs, der in unserem Beispiel eine Ellipse ist. Den Code dazu schreiben wir ergänzend im Paint-Ereignishandler des Benutzersteuerelements.

Private Sub Grafik(ByVal sender As Object, ByVal e As PaintEventArgs) _ 
Handles Me.Paint 
  ... 
  ' Festlegen des dem Steuerlement zugeordneten Fensterbereichs 
  Dim graphPath As New Drawing2D.GraphicsPath() 
  graphPath.AddEllipse(ClientRectangle) 
  Region = New Region(graphPath) 
End Sub

Standardereignis festlegen

Ein Doppelklick auf eine Komponente im Designer führt zum automatischen Erzeugen eines Ereignishandlers. Mit welchem Ereignis dieser verknüpft ist, hängt davon ab, welches Ereignis als Standardereignis der Komponente definiert ist. Bei einer Form ist es das Ereignis Load, bei einer Schaltfläche Click. Nehmen wir keine Änderungen vor, ist auch bei einem Benutzersteuerelement Load das Standardereignis. Mit dem Attribut DefaultEvent können wir ein anderes Ereignis festlegen. Das Attribut wird vor der Class-Deklaration angegeben.

<DefaultEvent("Click")> Public Class EllipseLabel 
  ... 
End Class

Rheinwerk Computing - Zum Seitenanfang

17.3.5 Bereitstellen einer Toolbox-Bitmap Zur nächsten ÜberschriftZur vorigen Überschrift

Bisher wird für das Steuerelement in der Toolbox nur die Standardbitmap eines UserControl-Steuerelements angezeigt. Das sieht natürlich nicht sehr professionell aus und soll nun durch eine steuerelementeigene Bitmap ersetzt werden.

Liegt eine Bitmap bereits vor, können Sie diese über das Kontextmenü des Projekts (Hinzu-fügenVorhandenes Element hinzufügen...) in das Benutzersteuerelementprojekt einbinden. Falls noch keine Bitmap vorliegt, können Sie auch die Bitmap direkt im Editor der Entwicklungsumgebung zeichnen. Auch hier müssen Sie den Weg über das Kontextmenü einschlagen, wählen dann allerdings HinzufügenNeues Element hinzufügen... Im sich öffnenden Dialogfenster wählen Sie die Vorlage Bitmap-Datei aus.

Die Größe der Toolbox-Bitmaps ist immer 16 × 16 Pixel. Die Anzahl der Farben ist nicht entscheidend, aber 256 ist meistens ausreichend. Ist die Bitmap fertiggestellt, müssen Sie noch zwei Dinge berücksichtigen:

  • Im Eigenschaftsfenster der Bitmap legen Sie die Eigenschaft Buildvorgang auf Eingebettete Ressource fest. Damit ist die Bitmap-Datei Teil des Kompilats der Anwendung.
  • Der Name der Bitmap-Datei sollte dem Klassennamen des Steuerelements entsprechen. Das können Sie gegebenenfalls auch im Eigenschaftsfenster umstellen.

Damit haben Sie alles vorbereitet. In einer Hostanwendung soll das eigene Steuerelement nun in der Lasche Alle Windows Forms der Toolbox angezeigt werden. Wählen Sie dazu aus dem Kontextmenü der Toolbox-Lasche Elemente auswählen. Daraufhin öffnet sich der Dialog Toolbox-Elemente auswählen (siehe Abbildung 17.3).

Abbildung 17.3 Hinzufügen eines Steuerelements

Klicken Sie hier zuerst auf die Schaltfläche Durchsuchen, und navigieren Sie anschließend zur DLL-Datei des Release-Zweigs der Steuerelementbibliothek. In der Toolbox der Hostanwendung wird das Steuerelement angezeigt, wie in Abbildung 17.4 zu sehen ist.

Abbildung 17.4 Toolbox mit EllipseLabel

Alternativ zum Einbinden einer Bitmap in die Projektmappe stellt das .NET Framework mit ToolboxBitmap auch ein Attribut zur Verfügung, um einem Benutzersteuerelement ein Symbol zuzuordnen. Dazu übergeben Sie dem Konstruktor des Attributs entweder die Zeichenfolge mit dem Namen der Bitmap-Datei, den Datentyp der Ressource oder den Datentyp samt Angabe des Dateinamens, wobei dieser dann sogar anders lauten darf als der Klassenname des Steuerelements.

<ToolboxBitmap("C:\test.bmp")> <DefaultEvent("Click")> _ 
Public Class EllipseLabel 
  ... 
End Class

Rheinwerk Computing - Zum Seitenanfang

17.3.6 Code für EllipseLabel topZur vorigen Überschrift

An dieser Stelle fasse ich den Code des Benutzersteuerelements zusammen. Die Verwendung ist einfach. Fügen Sie in einem eigenen Projekt Eigene.dll unter Verweise hinzu. Sie müssen das Steuerelement der Toolbox nur einmal hinzufügen, um es wie jedes andere Element der Toolbox verwenden zu können. Das EllipseLabel-Steuerelement wird auch nach einem Neustart der Entwicklungsumgebung angeboten.


'...\Steuerelemente\Eigene\EllipseLabel.vb

Imports System.ComponentModel 
<DefaultEvent("Click")> Public Class EllipseLabel

  ' Hintergrundellipse, Textausrichtung und Clientbereich 
  Private Sub Grafik(sender As Object, e As PaintEventArgs) Handles Me.Paint 
    Dim g As Graphics = e.Graphics 
    g.FillEllipse(fillCol, 0, 0, ClientSize.Width, ClientSize.Height) 
    Dim x As Integer = (ClientSize.Width – TextLabel.ClientSize.Width) / 2 
    Dim y As Integer = (ClientSize.Height – TextLabel.ClientSize.Height) / 2 
    TextLabel.Location = New Point(x, y) 
    ' Festlegen des dem Steuerelement zugeordneten Fensterbereichs 
    Dim graphPath As New Drawing2D.GraphicsPath() 
    graphPath.AddEllipse(ClientRectangle) 
    Region = New Region(graphPath) 
  End Sub

  ' Flimmerreduktion, Neuzeichnen bei Größenänderung und Transparenz 
  Private Sub Laden(sender As Object, e As EventArgs) Handles MyBase.Load 
    Me.SetStyle(ControlStyles.DoubleBuffer Or ControlStyles.UserPaint Or _ 
      ControlStyles.AllPaintingInWmPaint Or _ 
      ControlStyles.SupportsTransparentBackColor Or _ 
      ControlStyles.ResizeRedraw, True) 
    Me.BackColor = Color.Transparent 
  End Sub

  ' in das Eigenschaftsfenster übernehmen und persistent machen 
  <Browsable(True)> _ 
  <DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)> _ 
  Public Overrides Property Text() As String 
    Get 
      Return TextLabel.Text 
    End Get 
    Set(ByVal value As String) 
      TextLabel.Text = value 
    End Set 
  End Property

  ' Hilfetext festlegen und "bessere" Einordnung 
  Protected fillCol As New SolidBrush(Color.Blue) 
  <Description("Legt die Füllfarbe der Ellipse fest")> _ 
  <Category("Appearance")> _ 
  Public Property FillColor() As Color 
    Get 
      Return fillCol.Color 
    End Get 
    Set(ByVal value As Color) 
      fillCol.Color = value 
      Invalidate() 
    End Set 
  End Property

  ' Hintergrundfarbe ausblenden 
  <EditorBrowsable(EditorBrowsableState.Never)> _ 
  <Browsable(False)> _ 
  Public Overrides Property BackColor() As Color 
    Get 
      Return MyBase.BackColor 
    End Get 
    Set(ByVal value As Color) 
      MyBase.BackColor = value 
    End Set 
  End Property

  ' Test, ob ein Punkt innerhalb der Ellipse von EllipseLabel liegt 
  Private Function Treffer(x As Integer, y As Integer) As Boolean 
    Return (2 * x / Width – 1) ^ 2 + (2 * y / Height – 1) ^ 2 <= 1 
  End Function

  ' Den Klick an EllipseLabel weiterreichen 
  Private Sub Innen(sender As Object, e As EventArgs) Handles TextLabel.Click 
    Me.OnClick(e) 
  End Sub

  ' irgendein optischer Effekt, um Funktionsfähigkeit zu testen 
  Private Sub Klick(sender As Object, e As EventArgs) Handles MyBase.Click 
    Dim rnd As New Random() 
    FillColor = Color.FromArgb(rnd.Next(100, 200), 0, rnd.Next(100, 200)) 
  End Sub

End Class


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.

<< zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Visual Basic 2008
Visual Basic 2008
Jetzt Buch bestellen


 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Rheinwerk-Shop: Visual Basic 2012






 Visual Basic 2012


Zum Rheinwerk-Shop: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Rheinwerk-Shop: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Rheinwerk-Shop: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Rheinwerk-Shop: Windows Presentation Foundation






 Windows Presentation
 Foundation


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern