Grafische Effekte mit dem SkinControl
von Herfried K. Wagner
Übersicht
Das Problem
Unter Microsoft Visual Basic besitzen alle Standardsteuerelemente eine rechteckige Grundfläche. Zur Anzeige von Grafiken können Image- oder PictureBox-Steuerelemente verwendet werden. In modernen Multimedia-Oberflächen werden oft anstelle von CommandButtons grafische Buttons verwendet, die beim Überfahren mit der Maus und beim Klick ihre Grafik wechseln.
Mit freundlichen Grüßen
Herfried K. Wagner Hirf@activevb.de
Funktion und Verwendung
Am einfachsten lässt sich der einleitend erwähnte Effekt erzielen, indem Image-Steuerelemente, in die transparente GIFs geladen werden, als Schaltflächen fungieren.Manchmal ist es jedoch notwendig, dass diese Schaltflächen unregelmässig geformt sind, da die Schaltflächen direkt nebeneinander liegen und die Grenze unregelmässig oder einfach nicht geradlinig horizontal oder vertikal verläuft. Vergleichbar ist das mit den unregelmässigen Regionen in ImageMaps bei HTML-Dokumenten. Beispielsweise könnte eine Landkarte mit ereignissensitiven Flächen für die einzelnen Länder nicht mit den Standardmöglichkeiten von Microsoft Visual Basic gestaltet werden, da die Länder unregelmässige (nicht rechteckige) Formen besitzen und daher nicht mit Image-Steuerementen darstellt werden können. | |
- Ein Lösungsweg wäre, die gesamte Landkarte in ein Image-Steuerelement zu laden, beim MouseDown die Mauskoordinaten auszuwerten und anschliessend je nach Koordinaten ein anderes Ereignis auszulösen. Dazu wäre es aber notwendig, eine Liste zu erstellen, in der für jeden Pixel angegeben wäre, welches Ereignis ausgelöst werden soll. Dieser Vorgang würde sehr viel Zeit und Systemressourcen in Anspruch nehmen und ist daher nicht einsetzbar.
- Es können sogenannte "Regions" verwendet werden, allerdings gestaltet sich die Verwendung schwierig, ausserdem können Ereignisse nur teilweise verarbeitet werden.
- Unter Microsoft Visual Basic kann bei einem Benutzersteuerelement mit folgenden Einstellungen eine unregelmässige Grundfläche erreicht werden:
- MaskColor = OLE_COLOR (Farbe, die in der MaskPicture-Grafik als transparent angenommen werden soll.)
- MaskPicture = Grafik in den von VB unterstützten Grafikformaten.
- Picture = Grafik, die am UserControl angezeigt werden soll (optional).
- Eine weitere Lösung bietet das hier vorgestellte Benutzersteuerelement SkinControl, das die Region des Steuerelements auf der Basis einer Bitmap erstellt. So können für alle Länder einzelne Bitmaps erstellt, der Picture-Eigenschaft des UserControls zugewiesen und über die Angabe einer Farbe, die als transparent angenommen werden soll, die unregelmässige Region hergestellt werden.
Nachteile: Maske wird langsam erstellt.
Vorteile: Einfacher zu implementieren.
Codebeschreibung
Das SkinControl-Benutzersteuerelement wurde unter VB6 erstellt, es kann sowohl direkt in die .exe eingebunden werden als auch als ActiveX-Steuerelement (OCX) genutzt werden.
Von Seiten des Steuerelements wird ein Grossteil der Standardereignisse und Eigenschaften unterstützt. Um die Funktionalität zum verändern der Form des Steuerelements zu erhalten, wurden folgende zusätzliche Eigenschaften implementiert:
Property | Datentyp | Standard | Beschreibung |
---|---|---|---|
ChangeMask | Boolean | True | Gibt zurück oder legt fest, ob bei einer Änderung des Inhalts der Picture-Eigenschaft die Form des Steuerelements neu festgelegt werden soll. Hinweis: Damit die ChangeMask-Eigenschaft ihre Wirkung zeigt, muss bereits eine Grafik geladen worden sein, anhand derer die Form des Steuerelements festgelegt wurde. |
MaskColor | OLE_COLOR | vbBlack | Gibt eine Farbe zurück oder legt sie fest, die in der Bitmap der Picture-Eigenschaft als transparent angenommen werden soll, d.h. es werden alle Pixel in der Grafik, die die gleiche Farbe besitzen wie die Farbe in der MaskColor-Eigenschaft, von der Region des Steuerelements entfernt. |
Picture | Picture | Nothing | Gibt eine Bitmap-Grafik zurück oder legt sie fest, die als Grundlage für die Form des Steuerelements dient und als Oberfläche angezeigt werden soll. Verwenden Sie für diese Eigenschaft nur Bitmap-Grafiken und keine Icons, GIFs und JPEGs sowie keine Meta-Dateien, da es zu einer fehlerhaften Darstellung des Steuerelements kommen kann. Die Funktion funktioniert nur mit unkomprimierten Bitmaps, auch RLE-komprimierte Bitmaps können nicht verwendet werden. |
Tabelle 1 : Properties
Die oben angeführten Eigenschaften können sowohl in der Entwicklungsumgebung als auch zur Laufzeit gesetzt werden.
Dem Steuerelement wurden auch (zur Laufzeit schreibgeschützte) Eigenschaften für hWnd und hDC hinzugefügt, damit das Steuerelement auch über das Win32-API modifiziert werden kann und Ereignisse ausgewertet werden können.
Property | Datentyp |
---|---|
EnabledChange(blnEnabled As Boolean) | Dieses Ereignis wird ausgelöst, wenn der Wert der Eigenschaft Enabled geändert wird. In blnEnabled wird der neue Wert der Enabled-Eigenschaft angegeben. Das Ereignis könnte beispielsweise verwendet werden, um eine Grafik für das deaktivierte Steuerelement anzuzeigen. |
Tabelle 2 : Propertys
Funktion RegionFromBitmap
Die Funktion RegionFromBitmap im Benutzersteuerelement ermittelt die transparente Region des Steuerelements und legt die Form des Steuerelements fest. Dazu wird die Bitmap in die PictureBox picSkin geladen und die Grafik anschliessend pixelweise mit der Farbe in der Eigenschaft MaskColor verglichen. Um die Farbe eines Pixels an einer bestimmten Position, die über x- und y-Koordinaten festgelegt wird, zu bestimmen, wird die GetPixel API-Funktion aus der gdi32.dll verwendet:
Private Declare Function GetPixel Lib "gdi32" (ByVal hDC As _ Long, ByVal X As Long, ByVal Y As Long) As Long
Listing 1: Die GetPixel-Funktion
Im Gegensatz zur GetPixel API-Funktion wird die SetPixel API-Funktion verwendet, um einen Pixel in einem Printer-Objekt zu setzen (diese Funktion arbeitet wesentlich schneller als die VB-eigene PSet-Funktion, noch schneller wäre die SetPixelV API-Funktion).
Beachten Sie, dass diese Funktion langsam arbeitet und es daher bei grösseren Bitmaps zu Verzögerungen kommen kann. Versuchen Sie deshalb, möglichst wenig SkinControl-Steuerelemente zu verwenden und stellen Sie nach Möglichkeit die ChageMask-Eigenschaft des Steuerelements auf False ein (es wird dadurch verhindert, dass die Form des Steuerelements beim Ändern der Picture-Eigenschaft neu berechnet werden muss, dieser Vorgang nimmt am meisten Zeit in Anspruch).
Erstellen der transparenten Region
Zum Erstellen der transparenten Region werden alle Pixel der Grafik mit der Maskenfarbe (MaskColor) verglichen, stimmen die beiden Farben überein, wird mit der CreateRectRgn API-Funktion eine Region mit der Grösse eines Pixels an der aktuellen Position erstellt und anschliessend über die CombineRgn API-Funktion der Gesamtregion hinzugefügt, die nach dem Abarbeiten der gesamten Bitmap über die SetWindowRgn API-Funktion aus der user32.dll entfernt wird. Anschliessend können nicht mehr verwendete Regionen mit der DeleteObject API-Funktion aus dem Speicher entfernt werden.
Private Declare Function DeleteObject Lib "gdi32" (ByVal _ hObject As Long) As Long Private Declare Function CreateRectRgn Lib "gdi32" (ByVal _ X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal _ Y2 As Long) As Long Private Declare Function CombineRgn Lib "gdi32" (ByVal _ hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal _ hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long Private Declare Function SetWindowRgn Lib "user32" (ByVal _ hWnd As Long, ByVal hRgn As Long, ByVal _ bRedraw As Long) As Long Private Const RGN_OR = 2
Listing 2: Deklarationen, um Objekte aus dem Speicher zu löschen
Beispiel Carsetup
In diesem Beispiel wurde das SkinControl nicht als ActiveX-Komponente in einer externen OCX angelegt, sondern es wurde direkt in das Programmprojekt importiert. Dadurch werden Kompatibilitätsprobleme während der Entwicklung vermieden und es ist das Registrieren der Komponente beim Endbenutzer nicht notwendig. Wenn das Steuerelement in mehreren Projekten eingesetzt werden soll, wäre es in Form einer OCX besser zu nutzen.
CarSetup zeigt eine Möglichkeit, wie das SkinControl in einer VB-Anwendung eingesetzt werden kann. Ziel ist es, in einer Grafik (Auto), durch Anklicken der einzelnen Teile diese zu verändern, wobei bei den ereignissensitiven Teilen der Hand-Mauszeiger und ein individueller ToolTipText angezeigt werden soll. | |
Wie in der Abbildung dargestellt, kann beim Anklicken der Autotür deren Farbe verändert werden. Dazu wurden Bitmaps, die die Tür in verschiedenen Farben darstellen, erstellt und in Image-Steuerelemente geladen (die Bitmaps könnten auch über eine Ressourcendatei eingebunden werden oder mit der Funktion LoadImage geladen werden), von wo aus die entsprechende Bitmap in die Picture-Eigenschaft des SkinControl-Steuerelements skcDoors eingefügt wird. In diesem Fall sollte die ChangeMask-Eigenschaft auf False eingestellt werden, da sich die Grösse der Tür nicht ändert. Im Beispiel CarSetup ist auch das Ändern der Reifen möglich, es kann zwischen Normal- und Spezialreifen gewechselt werden. Da in diesem Fall die Grösse der Reifen vom gewählten Reifentyp abhängig ist, sollte hier die ChangeMask-Eigenschaft auf True eingestellt werden.
SkinControl als Download [43.4 kB] [43400 Bytes]
Ihre Meinung
Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.