Hover-Effekt für Schaltflächen

Von Internetseiten kennen Sie diesen Effekt längst: Wenn Sie mit der Maus über einen Link etwa in der Navigationsleiste fahren, wird die jeweils überfahrene Schaltfläche mit einem speziellen Effekt hervorgehoben – beispielsweise in einer anderen Farbe. Da wir doch nun in Access mittlerweile auch Schaltflächen komfortabel mit Icons ausstatten können, sollten ähnliche Effekte doch auch hier möglich sein Wir zeigen, ob und wie dies funktioniert.

Voraussetzungen

Der Teil dieses Beitrags, der das angezeigte Icon wechselt, setzt mindestens Access 2010 voraus.

Schriftart wechseln

Um die grundsätzliche Funktion der hier vorgestellten Technik zu demonstrieren, verwenden wir eine Formatierungsänderung, die in allen Access-Versionen verfügbar sein dürfte – der Wechsel von der Standardschriftbreite zur fetten Schrift. Dazu legen Sie einfach ein neues Formular in einer Beispieldatenbank an und fügen diesem eine Schaltfläche mit einem beliebigen Text hinzu. Die Eigenschaft Schriftbreite enthält in diesem Zustand der Schaltfläche natürlich den Wert Normal (s. Bild 1).

Beispielformular mit der zu bearbeitenden Schaltfläche

Bild 1: Beispielformular mit der zu bearbeitenden Schaltfläche

Nun soll die Schaltfläche ihren Inhalt beim Darüberfahren mit der Maus fett anzeigen. Sie ahnen es bereits: Die Ereigniseigenschaft Bei Mausbewegung der Schaltfläche spielt dabei eine Rolle. Machen wir uns als ans Werk und legen für diese Ereigniseigenschaft eine entsprechende Ereignisprozedur an. Durch Auswählen des Eintrags [Ereignisprozedur] und anschließendes Anklicken der Schaltfläche mit den drei Punkten zeigen Sie die neu erzeugte Ereignisprozedur direkt im VBA-Editor an (siehe Bild 2).

Anlegen einer Prozedur, die durch das Ereignis Bei Mausbewegung ausgelöst wird.

Bild 2: Anlegen einer Prozedur, die durch das Ereignis Bei Mausbewegung ausgelöst wird.

Diese Ereignisprozedur füllen Sie nun mit der folgenden Anweisung aus Listing 1 auf. Wechseln wir in die Formularansicht und probieren aus, ob die Prozedur funktioniert. Das Ergebnis: Es klappt! Allerdings mit zwei kleinen Schönheitsfehlern: Erstens wird die Schriftart beim Verlassen der Schaltfläche nicht wieder normal eingestellt, und zweitens flackert die Schaltfläche ständig, wenn man mit die Maus darüber bewegt.

Private Sub cmdBeispielschaltflaeche_MouseMove(Button As Integer, _
         Shift As Integer, X As Single, Y As Single)
     Me!cmdBeispielschaltflaeche.FontBold = True
End Sub

Listing 1: ändern der Eigenschaft Schriftbreite in Fett

Schaltfläche wieder normal darstellen

Ersteres ist schon ein kleines Problem: Die Schaltflächen von Access bieten nämlich kein Ereignis etwa namens Beim Verlassen et cetera. Was tun wir also Klar: Wir fragen ab, wann der Mauszeiger wieder den Bereich außerhalb der Schaltfläche kreuzt. Dabei handelt es sich in diesem Fall um den Detailbereich. Auch dieser liefert die Ereigniseigenschaft Bei Mausbewegung, sodass wir einfach den Detailbereich durch Anklicken markieren und die gewünschte Ereignisprozedur anlegen (s. Bild 3).

Per Ereignis abgreifen, wann der Mauszeiger die Schaltfläche verlässt

Bild 3: Per Ereignis abgreifen, wann der Mauszeiger die Schaltfläche verlässt

Die Prozedur finden Sie in Listing 2.

Private Sub Detailbereich_MouseMove(Button As Integer, Shift As Integer, _
         X As Single, Y As Single)
     Me!cmdBeispielschaltflaeche.FontBold = False
End Sub

Listing 2: Ursprüngliche Textbreite wiederherstellen

Um das zweite Problem mit dem Flackern kümmern wir uns weiter unten. Zunächst stellen wir uns die Frage: Was geschieht eigentlich, wenn wir dem dem Formular nun eine zweite Schaltfläche hinzufügen Dies betrachten wir im Formular frmHoverEffektZweiSchaltflaechen der Beispieldatenbank (s. Bild 4). Dieses enthält zwei Schaltflächen namens cmdBeispielschaltflaeche1 und cmdBeispielschaltflaeche2. Beide Schaltflächen erhalten eine Ereignisprozedur, die durch das Ereignis Bei Mausbewegung ausgelöst wird und die Schrift der jeweiligen Schaltfläche auf Fett einstellt.

Neues Formular, diesmal mit zwei Schaltflächen

Bild 4: Neues Formular, diesmal mit zwei Schaltflächen

Und auch die entsprechende Ereignisprozedur für den Detailbereich müssen wir anpassen. Es kann ja nun auch geschehen, dass nicht die erste, sondern die zweite Schaltfläche mit fetter Schrift dargestellt wird. Also stellen wir vorsichtshalber gleich beide Schaltflächen entsprechend ein – s. Listing 3.

Private Sub Detailbereich_MouseMove(Button As Integer, Shift As Integer, _
         X As Single, Y As Single)
     Me!cmdBeispielschaltflaeche1.FontBold = False
     Me!cmdBeispielschaltflaeche2.FontBold = False
End Sub

Listing 3: Ursprüngliche Textbreite für zwei Schaltfläche wiederherstellen

Auch das funktioniert wie gewünscht – zumindest, bis wir die beiden Schaltflächen direkt neben- oder übereinander platzieren, sodass der Detailbereich dazwischen nicht sichtbar ist (s. Bild 5). Dies ist zwar ungewöhnlich, aber wenn man wenig Platz hat oder eine Web-ähnliche Navigationsleiste erstellen möchte, kann eine solche Konstellation durchaus vorkommen.

Formular mit zwei direkt nebeneinander liegenden Schaltflächen

Bild 5: Formular mit zwei direkt nebeneinander liegenden Schaltflächen

Das Problem bei der Sache ist, dass beim Wechsel von der linken zur rechten Schaltfläche zwar die rechte Schaltfläche mit fetter Schrift dargestellt wird, die linke aber nicht in den Anfangszustand zurückversetzt wird. Der Grund ist leicht nachvollziehbar: Der Mauszeiger überstreift zwischenzeitlich nicht den Detailbereich, also werden die beiden Schaltflächen auch nicht auf normale Schriftstärke zurückgesetzt.

Das bedeutet, dass wir für die Ereignisprozedur beim überfahren der zweiten Schaltfläche die Schriftart der ersten Schaltfläche zurücksetzen müssen und umgekehrt (s. Listing 4). Das ist in diesem Rahmen zwar machbar, aber was geschieht, wenn Sie nicht nur zwei, sondern vielleicht 20 Schaltflächen auf einem Formular unterbringen Nein, das ist definitiv zu viel Aufwand. Sie müssten dann nicht nur für jede der 20 Schaltflächen je eine Ereignisprozedur für das Ereignis Bei Mausbewegung einrichten, sondern auch noch in jeder dieser Prozeduren die aktuelle Schaltfläche mit fetter Schrift versehen und die übrigen 19 Schaltflächen auf normale Schriftbreite einstellen. Und jede weitere Schaltfläche zieht die änderung der entsprechenden Ereignisprozedur aller vorhandenen Schaltflächen nach sich.

Private Sub cmdBeispielschaltflaeche2_MouseMove(Button As Integer, _
         Shift As Integer, X As Single, Y As Single)
     Me!cmdBeispielschaltflaeche1.FontBold = False
     Me!cmdBeispielschaltflaeche2.FontBold = True
End Sub

Listing 4: Aktuelle Schaltfläche mit fetter Schrift, vorherige Schaltfläche normal anzeigen

Hover-Effekt mit Klasse

Wir werden also, wie in so vielen Fällen, in denen eine undefinierte Anzahl von Steuerelementen mit bestimmten Ereignissen ausgestattet werden müssen, ein oder zwei Klassen anlegen, welche die benötigte Funktionalität bereithalben. Um es vorweg zu nehmen: Sie müssen dem Klassenmodul eines Formulars nur noch wenige Zeilen Code hinzufügen, um den gewünschten Hover-Effekt für beliebig viele Schaltflächen zu erzielen.

Das Beispiel für den Einsatz dieser Klassen finden Sie im Formular frmHoverEffekt_Fett_Klasse. Diese Formular besitzt zunächst zwei Schaltflächen, genau wie das Formular des vorherigen Beispiels. Legen Sie nun eine Ereignisprozedur für die Ereigniseigenschaft Beim Laden des Formulars an und hinterlegen Sie dafür den Code aus Listing 5. Zusätzlich fügen Sie noch die folgende Deklarationszeile zum Klassenmodul Form_frmHoverEffekt_Fett_Klasse hinzu (beziehungsweise zum Klassenmodul des betroffenen Formulars, wenn Sie die Funktion zu einem eigenen Formular hinzufügen möchten):

Private Sub Form_Load()
     Set objMouseOverForm = New clsMouseOverForm
     With objMouseOverForm
         Set .Form = Me
     End With
End Sub

Listing 5: Zuweisen der Funktionen der Klasse clsMouseOverForm zu einem Formular

Dim objMouseOverForm As clsMouseOverForm

Die Prozedur Form_Load erstellt eine neue Instanz der Klasse clsMouseOverForm und speichert den Verweis darauf in der Variablen objMouseOverForm. Die einzige weitere Anweisung teilt dem Objekt objMouseOverForm über die Eigenschaft Form mit, auf welches Formular sich die Klasse beziehen soll beziehungsweise die Schaltflächen welchen Formulars den Hover-Effekt erhalten sollen.

Diese Klasse erzeugen Sie im VBA-Editor über den Menüeintrag Einfügen|Klassenmodul. Speichern Sie die Klasse unter dem Namen clsMouseOverForm.

Instanzieren der Klasse

Wenn der Benutzer nun das Formular öffnet, löst dies automatisch die Ereignisprozedur Form_Load aus. Beim Instanzieren des neuen Objekts auf Basis der Klasse clsMouseOverForm geschieht noch nichts. Erst mit dem Zuweisen des Formulars zur Eigenschaft Form des Objekts objMouseOverForm wird eine Property Set-Prozedur der Klasse ausgelöst. Diese sieht wie in Listing 6 aus. Die Prozedur speichert zunächst einen Verweis auf das Formular in einer Variablen, die wie folgt im Kopf des Klassenmoduls clsMouseOverForm deklariert wird:

Dim WithEvents m_Form As Form
Public Property Set Form(frm As Form)
     Dim objMouseOverControl As clsMouseOverControl
     Dim ctl As control
     Set m_Form = frm
     Set frmDetail = m_Form.Section(0)
     With m_Form
         .OnMouseMove = "[Event Procedure]"
     End With
     With frmDetail
         .OnMouseMove = "[Event Procedure]"
     End With
     Set colControls = New Collection
     For Each ctl In m_Form.Controls
         Select Case ctl.ControlType
             Case acCommandButton
                 Set objMouseOverControl = New clsMouseOverControl
                 With objMouseOverControl
                     Set .Commandbutton = ctl
                     Set .Parent = Me
                 End With
                 colControls.Add objMouseOverControl
         End Select
     Next ctl
End Property

Listing 6: Zuweisen des Formulars und Einstellen einiger Eigenschaften

Die Deklaration mit dem Schlüsselwort WithEvents sorgt dafür, dass wir innerhalb des aktuellen Klassenformulars Ereignisprozeduren für das in dieser Variablen referenzierte Formular implementieren können. Das ist gerade einer der Tricks bei dieser Lösung: Sie sollen nicht zahlreiche Ereignisprozeduren zum formular hinzufügen, sondern nur die Klasse clsMouseOverForm instanzieren und diesem sagen, welches Formular mit den Ereignisprozeduren auszustatten ist – den Rest übernimmt die Klasse dann selbst.

Auf die gleiche Weise füllt die Property Set-Prozedur die Variable frmDetail mit einem Verweis auf den Detailbereich des Formulars. Diese deklariert die Klasse wie folgt:

Dim WithEvents frmDetail As Section

Den Verweis auf den Detailbereich erhalten wir über den Ausdruck m_Form.Section(0).

Die folgenden Anweisungen sorgen dafür, dass die Eigenschaft Bei Mausbewegung (OnMouseMove) des mit m_Form referenzierten Formulars mit dem Wert [Event Procedure] (im Eigenschaftsfenster [Ereignisprozedur]) gefüllt wird. Das Gleiche erledigt die Prozedur für den in frmDetail gespeicherten Detailbereich.

Anschließend kümmert sich die Prozedur um die im Formular enthaltenen Steuerelemente. Dazu instanziert sie zunächst ein Collection-Objekt, das mit der folgenden Variablen im Kopf des Klassenmoduls deklariert wird:

Dim colControls As Collection

Die Property Set-Prozedur Form durchläuft nun in einer For Each-Schleife alle Steuerelemente des referenzierten Formulars und weist das aktuellen Control-Objekt der Variablen ctl zu. Innerhalb der Schleife prüft die Prozedur die Eigenschaft ControlType des Steuerelements. Handelt es sich um eine Schaltfläche (ControlType = acCommandButton), führt die Prozedur weitere Anweisungen aus. Die erste erstellt ein neues Objekt auf Basis einer zweiten Klasse namens clsMouseOverControl. Die Details dieser Klasse besprechen wir weiter unten – zunächst schauen wir uns an, wie diese instanziert und bestückt wird.

Die Instanzierung erfolgt wie gewohnt über die New-Methode. Die Klasse clsMouseOverControl verfügt über eine Eigenschaft namens CommandButton, der Sie den Verweis auf das aktuell mit der For Each-Schleife durchlaufene und mit cmd referenzierte Steuerelement zuweisen. Außerdem bietet die Klasse eine weitere Eigenschaft namens Parent, der Sie einen Verweis auf die aktuelle Klasse, also clsMouseOverForm, zuweisen. Diese referenzieren Sie einfach mit dem Schlüsselwort Me. Das war es schon fast. Es fehlt jedoch noch ein entscheidender Schritt, bevor wir die nächste Schaltfläche auf die gleiche Weise in einer Instanz der Klasse clsMouseOverControl erstellen: Wir müssen das soeben erstellt Objekt objMouse-OverControl noch verewigen, damit es beim nächsten Schleifendurchlauf nicht einfach überschrieben wird. Dazu fügen wir die Objektvariable objMouseOverControl einfach mit der Add-Methode zum Collection-Objekt colControls hinzu!

Die Collection ist ja im allgemeinen Teil des Klassenmoduls clsMouseOverForm deklariert und bleibt somit solange erhalten wie die Instanz des Klassenmoduls selbst. Und da diese ja beim Laden des Formulars wiederum in der Variablen objMouseOverForm im Klassenmodul des Formulars gespeichert wird, bleiben die Elemente der Collection solange verfügbar, bis der Benutzer das Formular schließt.

Auf die gleiche Weise durchläuft die Prozedur alle Steuerelemente des Formulars und fügt für jede Schaltfläche eine neue Instanz der Klasse clsMouseOverControl zur Collection colControls hinzu.

Die Klasse clsMouseOverControl

Das waren die vorbereitenden Aktionen innerhalb der Klasse clsMouseOverForm. Bevor wir zu den Teilen des Codes kommen, welche die Aktionen bei der Benutzung des Formulars beschreiben, schauen wir uns einige Details der Klasse clsMouseOverControl an.

Zunächst einmal wäre da die Property Set-Prozedur, welche den Verweis auf das CommandButton-Objekt entgegen nimmt, dessen Ereignisse in der Klasse clsMouseOverControl implementiert werden sollen. Diese sieht wie in Listing 7 aus und schreibt den mit der Variablen cmd übergebenen Verweis in die lokale Variable m_cmd. Diese wird wie folgt im Kopf des Klassenmoduls clsMouseOverControl deklariert:

Dim WithEvents m_cmd As Commandbutton
Public Property Set Commandbutton(cmd As Commandbutton)
     Set m_cmd = cmd
     With m_cmd
         .OnMouseMove = "[Event Procedure]"
     End With
End Property

Listing 7: Zuweisen der Referenz auf die Schaltfläche

Anschließend trägt die Prozedur noch den Wert [Event Procedure] für die Eigenschaft OnMouseMove für dieses Steuerelement ein.

Die zweite Property Set-Prozedur nimmt den Verweis auf die Instanz der erzeugenden Klasse entgegen, die im Objekt objMouseOverForm gespeichert ist (s. Listing 8). Die Prozedur speichert den Verweis auf dieses Objekt in der Variablen m_Form:

Dim m_Parent As clsMouseoverForm
Public Property Set Parent(obj As clsMouseoverForm)
     Set m_Parent = obj
End Property

Listing 8: Zuweisen der Referenz auf die Klasse clsMouseOverForm

Funktion der beiden Klassen

Wir haben nun also in unserem Beispiel ein Objekt des Typs clsMouseOverForm (gespeichert in der Variablen objMouseOverForm im Klassenmodul des Formulars) und für jede Schaltfläche ein Objekt des Typs clsMouseOverControl (gespeichert in einer Collection in clsMouseOverForm).

Wenn der Benutzer nun mit der Maus über eine der Schaltflächen fährt, soll für diese die Schriftart auf Fett eingestellt werden. Gleichzeitig soll die Schrift auf allen übrigen Schaltflächen nicht fett erscheinen. Wenn die Maus eine Schaltfläche verlässt und nicht auf einer anderen Schaltfläche landet, sollen alle Schaltflächen nicht fett dargestellt werden.

Hier entsteht zunächst das Problem, dass wir beim überfahren einer Schaltfläche dafür sorgen müssen, dass keine der übrigen Schaltflächen mit fetter Schrift dargestellt wird.

Dazu gibt es zwei Möglichkeiten: Entweder wir durchlaufen alle übrigen Schaltflächen und stellen ihre Schriftart entsprechend ein, oder wir speichern jeweils einen Verweis auf die aktuell überfahrene Schaltfläche in einer Variablen. Wenn die Maus nun eine andere Schaltfläche überfährt, brauchen wir nur die Fett-Eigenschaft der zuvor in der Variablen gespeicherten Schaltfläche auf Nein einzustellen.

Wir wollen den letzten, möglicherweise etwas komplizierteren, aber schnelleren Weg einschlagen. Dazu deklarieren Sie in der Klasse clsMouseOverForm die folgende Variable, mit der ein Verweis auf das zuletzt überfahrene CommandButton-Objekt gespeichert werden soll:

Dim m_Aktiv As control

Danach fügen Sie der Klasse eine Property Set-Prozedur hinzu, mit der wir das aktive Steuerelement einstellen können:

Public Property Get ctlAktiv() As control
     Set ctlAktiv = m_Aktiv
End Property

Außerdem benötigen wir noch die Möglichkeit, dieses Steuerelement auszulesen. Dies bewerkstelligen wir mit einer entsprechenden Property Get-Prozedur, die wie folgt aussieht:

Public Property Set ctlAktiv(ctl As control)
     Set m_Aktiv = ctl
End Property

Damit gelangen wir direkt zu der Implementierung der Ereignisprozedur für das Ereignis Bei Mausbewegung in der Klasse clsMouseOverControl, die ja für alle Schaltflächen ausgelöst wird, wenn der Benutzer mit der Maus darüberfährt. Diese sieht wie in Listing 9 aus.

Private Sub m_cmd_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
     If m_Parent.ctlAktiv Is Nothing Or Not m_Parent.ctlAktiv Is m_cmd Then
         If Not m_Parent.ctlAktiv Is Nothing Then
             m_Parent.ctlAktiv.FontBold = False
         End If
         Set m_Parent.ctlAktiv = m_cmd
         m_cmd.FontBold = True
     End If
End Sub

Listing 9: Diese Prozedur wird beim überfahren einer Schaltfläche ausgelöst.

Die Prozedur prüft zunächst zwei Bedingungen per Or-Verknüpfung:

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar