Schaltflächen per Code anlegen

Im Beitrag Schaltflächen-Assistent (www.access-im-unternehmen.de/1308) zeigen wir, wie Sie das Grundgerüst eines Schaltflächen-Assistenten definieren. Was Sie mit dem Schaltflächen-Assistenten anfangen können, zeigen wir Ihnen im vorliegenden Beitrag. Wir wollen zunächst das Anlegen bestimmter Standardschaltflächen erlauben. Die erste sind einfache OK- und Abbrechen-Schaltflächen. Diese Aufgabe kostet in jedem Formular, das sie neu erstellen, ein paar Minuten. Zeit, die Sie sich sparen können – indem Sie einmalig Zeit in die Entwicklung eines passenden Steuerelement-Assistenten investieren.

Ziel des Assistenten

Das Ziel des Assistenten ist das Anlegen einer neuen OK-Schaltfläche. Dies soll folgende Eigenschaften umfassen:

  • Schaltfläche mit einem Icon (zum Beispiel grüner Haken) und dem Text OK als Beschriftung
  • Einstellen einiger Eigenschaften wie Rahmenart, Hintergrundfarbe, Größe
  • Hinzufügen einer Ereignisprozedur, die das Formular schließt oder alternativ andere Aktionen ausführt

Grundgerüst des Steuerelement-Assistenten

Das Grundgerüst des Assistenten haben wir bereits im oben genannten Beitrag beschrieben. Dieses nutzen wir als Basis für die im vorliegenden Beitrag beschriebenen Techniken.

Beim Starten des Steuerelement-Assistenten soll als Erstes ein Formular angezeigt werden, mit dem der Benutzer einige Einstellungen vornehmen kann, bevor er das Anlegen der Schaltfläche bestätigt. Dieses Formular soll auch eine Vorschau der zu erstellenden Schaltfläche anzeigen.

Formular zum Anpassen der zu erstellenden Schaltfläche

Für dieses Formular, das frmButtonWizardOK heißen soll, stellen wir zunächst einige Eigenschaften ein. Die Eigenschaften Datensatzmarkierer, Navigationsschaltflächen, Trennlinien und Bildlaufleisten sollen den Wert Nein erhalten, die Eigenschaft Automatisch zentrieren den Wert Ja.

Außerdem soll das Formular selbst eine OK-Schaltfläche sowie eine Abbrechen-Schaltfläche enthalten, damit der Benutzer die vorgenommenen Änderungen direkt anwenden oder auch verwerfen kann. Danach sieht das Formular wie in Bild 1 aus.

Erster Entwurf des Formulars zum Einstellen von Schaltflächen-Eigenschaften

Bild 1: Erster Entwurf des Formulars zum Einstellen von Schaltflächen-Eigenschaften

Beispiel-Schaltfläche

Nun wollen wir ja mit dem Formular festlegen, wie eine zu erstellende OK-Schaltfläche aussehen soll. Dazu fügen wir Steuerelemente hinzu, mit denen wir die wichtigsten Einstellungen vornehmen. Diese haben wir in Bild 2 bereits hinzugefügt.

Formular mit Steuerelementen zum Einstellen der Schaltflächeneigenschaften

Bild 2: Formular mit Steuerelementen zum Einstellen der Schaltflächeneigenschaften

Dies sind die Steuerelemente:

  • txtBeschriftung: Nimmt die Beschriftung für das Steuerelement entgegen.
  • txtName: Enthält den Namen für das Steuerelement.
  • cboBilder: Zeigt die Namen der im Add-In verfügbaren Bilder an. Diese Bilder werden in der Tabelle MSysResources gespeichert.
  • chkTransparent: Gibt an, ob der Hintergrund transparent angezeigt werden soll.
  • cboBeschriftungAnzeigen: Erlaubt die Auswahl der verschiedenen Anordnungen von Bild und Beschriftung oder auch nur die Anzeige eines Bildes.
  • txtAbstandBildSchrift: Erlaubt das Einfügen von ein bis drei Leerzeichen zwischen Bild und Beschriftung.
  • txtBildbreite: Breite des Bildes in Pixel
  • txtBildhoehe: Höhe des Bildes in Pixel
  • cboEreignisprozeduren: Dient der Auswahl der Anweisungen der Ereignisprozedur für die Schaltfläche.
  • cmdEreignisprozedurenBearbeiten: Öffnet das Formular zum Bearbeiten der Ereignisprozeduren.

Natürlich hätten wir noch einige weitere Eigenschaften aufnehmen können, aber das würde den Rahmen dieses Beitrags sprengen.

Wichtig: Option Compare Binary statt Option Compare Database

In einer Prozedur dieses Formulars wollen wir Umlaute in Vokale umwandeln. Die Replace-Funktion ändert bei Verwendung von Option Compare Database im Kopf des Moduls ä in ae, aber auch Ä in ae. Damit Ä in Ae geändert wird, stellen wir im Klassenmodul des Formulars frmButtonWizard die Anweisung Option Compare Binary ein:

Option Compare Binary
Option Explicit

Hinzufügen einer Beschriftung

Das Eintragen einer Beschriftung ist der erste Schritt. Hierbei sollen direkt einige Aktionen erfolgen. Zum einen wollen wir dem Benutzer die Arbeit abnehmen, den Namen der Schaltfläche einzutragen.

Daher soll dieser dynamisch basierend auf der Beschriftung generiert werden – mehr dazu weiter unten. Außerdem soll die Größe der Vorschau immer direkt an die enthaltene Beschriftung, gegebenenfalls mit Icon, angepasst werden.

Da wir die Beschriftung auch noch in anderen Prozeduren benötigen, legen wir für diese eine modulweit deklarierte Variable namens strBeschriftung an:

Dim strBeschriftung As String

Danach können wir in die Ereignisprozedur einsteigen, die aufgerufen wird, wenn der Benutzer den Text im Textfeld txtBeschriftung anpasst. Das löst mit der Eingabe eines jeden Zeichens die Prozedur aus Listing 1 aus.

Private Sub txtBeschriftung_Change()
     Dim strText As String
     Dim lngPosLeer As Long
     strText = Me!txtBeschriftung.Text
     strText = Trim(strText)
     strBeschriftung = strText
     Me!cmdBeispiel.Caption = strText
     lngPosLeer = InStr(1, strText, " ")
     Do While Not lngPosLeer = 0
         strText = Left(strText, lngPosLeer - 1) & UCase(Mid(strText, lngPosLeer + 1, 1)) & Mid(strText, lngPosLeer + 2)
         lngPosLeer = InStr(lngPosLeer + 1, strText, " ")
     Loop
     strText = UmlauteErsetzen(strText)
     Me!txtName = "cmd" & strText
     GroesseOptimieren
End Sub

Listing 1: Ereignisprozedur, die beim Ändern der Beschriftung ausgelöst wird

Die Prozedur erfasst zunächst den aktuellen Text im Textfeld, und zwar über die Eigenschaft Text. Diese unterscheidet sich vom üblicherweise abgefragten Wert des Textfeldes, weil der Wert oder die Eigenschaft Value immer den zuletzt bestätigten Wert liefert. Text hingegen liefert den aktuell angezeigten Text. Der Text landet in der Variablen strText, den wir danach mit der Trim-Funktion von führenden und folgenden Leerzeichen befreien. Dann tragen wir den aktuellen Wert von strText in die Variable strBeschriftung ein, die wir später in weiteren Prozeduren abfragen. Außerdem landet die Beschriftung aus strText in der Eigenschaft Caption der Beispielschaltfläche cmdBeispiel, damit der Text direkt angezeigt wird.

CamelCase für den Schaltflächennamen

Danach folgen die Schritte, in denen wir den Namen für die Schaltfläche aus dem aktuellen Text für die Beschreibung ableiten. Der Schaltflächenname soll aus dem Präfix cmd plus der Beschriftung bestehen, wobei wir aus der Beschriftung die Leerzeichen entfernen, neue Wörter in der CamelCase-Notation schreiben und Umlaute in die entsprechenden Vokale umwandeln. Aus Jetzt löschen wird also der Schaltflächenname cmdJetztLoeschen.

Dazu ermitteln wir zuerst die Position des ersten Leerzeichens und speichern diese in der Variablen lngPosLeer. Ist diese nicht 0, kommt also mindestens ein Leerzeichen in der Beschriftung vor, steigen wir in eine Do While-Schleife ein.

Diese stellt den Wert in strText neu zusammen, und zwar aus den Zeichen bis zum ersten Leerzeichen (Left(strText, lngPosLeer – 1)), dem ersten Buchstaben des Wortes nach dem Leerzeichen als Großbuchstaben (UCase(Mid(strText, lngPosLeer + 1, 1))) sowie dem Rest des Textes nach diesem Buchstaben (Mid(strText, lngPosLeer + 2)).

Aus Jetzt alles schließen wird dann JetztAlles schließen. Danach prüfen wir innerhalb der Do While-Schleife, ob es noch ein Leerzeichen im Ausdruck gibt. Das ist bei unserem Beispiel der Fall, also ist lngPosLeer noch nicht 0 und wir durchlaufen die Do While-Schleife ein zweites Mal. Danach hat strText den Inhalt JetztAllesSchließen.

Damit verlässt die Prozedur die Schleife und ruft die Funktion UmlauteErsetzen auf, die wie folgt aussieht:

Public Function UmlauteErsetzen(ByVal strText As String)  As String
     strText = Replace(strText, "ä", "ae")
     strText = Replace(strText, "ö", "oe")
     strText = Replace(strText, "ü", "ue")
     strText = Replace(strText, "Ä", "Ae")
     strText = Replace(strText, "Ö", "Oe")
     strText = Replace(strText, "Ü", "Ue")
     strText = Replace(strText, "ß", "ss")
     UmlauteErsetzen = strText
End Function

Die Funktion ersetzt alle Umlaute durch Vokale und ß durch ss, was in unserem Beispiel zum Ergebnis JetztAllesSchliessen führt. Dem stellt die Ereignisprozedur noch das Präfix cmd voran: cmdJetztAlles-Schliessen. Schließlich wird die Prozedur GroesseOptimieren aufgerufen, welche die Größe der Beispielschaltfläche anpasst.

Die Prozedur GroesseOptimieren schauen wir uns weiter unten an, da diese noch weitere Steuerelemente berücksichtigt, die wir noch nicht erstellt haben. In Bild 3 sehen Sie einen Zwischenstand.

Zwischenergebnis nach der Eingabe der Beschriftung

Bild 3: Zwischenergebnis nach der Eingabe der Beschriftung

Namen der Schaltfläche ändern

Wenn Sie den nun automatisch aus der Beschriftung der Schaltfläche abgeleiteten Namen ändern möchten, können Sie dies problemlos tun. Beachten Sie nur, dass dieser bei erneuter Änderung der Beschriftung wieder von der Beschriftung abgeleitet wird. Sie können bei Bedarf eine Option einbauen, welche die nachträgliche Änderung des Namens verhindert, wenn dieser einmal festgelegt wurde. Wir wollen es an dieser Stelle allerdings nicht zu kompliziert machen.

Bild auswählen

Bei der Bereitstellung der Bilder wollen wir eine eingebaute Funktion von Access nutzen. Dabei können Sie in der Entwurfsansicht eines Formulars den Ribbon-Befehl Entwurf|Steuerelemente|Bild einfügen|Durchsuchen… nutzen, um Bilder zur Datenbank hinzuzufügen (siehe Bild 4).

Auswählen von Bildern für die aktuelle Datenbank

Bild 4: Auswählen von Bildern für die aktuelle Datenbank

Diese können wir beim Programmieren der .accda-Datenbank zunächst nutzen, um ein paar als Icon zu verwendende Bilddateien in der Datenbank zu speichern. Die Bilder landen dann in einem Anlagefeld in der Tabelle MSysResources.

Diese Tabelle verwenden wir in der Abfrage für die Datensatzherkunft des Kombinationsfeldes cboBilder als Datenquelle. Und wir setzen noch einen drauf, denn wir wollen auch einen Eintrag mit dem Text anzeigen. Daher benötigen wir eine UNION-Abfrage, deren SQL-Anweisung wie folgt aussieht:

SELECT 0 AS ID, "<Kein Bild>" AS Name, "" AS Type FROM MSysResources UNION SELECT Id, Name, Type FROM MSysResources WHERE Type="img"

Dies liefert ein Ergebnis wie in Bild 5.

Datensatzherkunft für das Kombinationsfeld cboBilder

Bild 5: Datensatzherkunft für das Kombinationsfeld cboBilder

Für das Kombinationsfeld cboBilder stellen wir die Eigenschaften Spaltenanzahl auf 2 und Spaltenbreiten auf 0cm ein. Danach können Sie mit dem Kombinationsfeld die Bilder wie in Bild 6 auswählen. Das funktioniert für den Moment, später werden wir hier noch nachjustieren müssen.

Auswahl von Bildern mit dem Kombinationsfeld cboBilder

Bild 6: Auswahl von Bildern mit dem Kombinationsfeld cboBilder

Das Aktualisieren des Kombinationsfeldes löst das Ereignis Nach Aktualisierung mit der folgenden Ereignisprozedur aus. Diese ruft zwei Prozeduren auf: BildEinstellen, um das neue Bild festzulegen, und die bereits oben einmal aufgerufene Prozedur GroesseOptimieren. Diese soll die Größe an den geänderten Inhalt anpassen:

Private Sub cboBilder_AfterUpdate()
     BildEinstellen
     GroesseOptimieren
End Sub

Die Prozedur BildEinstellen prüft, ob das Kombinationsfeld cboBilder den Wert 0 hat, was dem Text entspricht. In diesem Fall stellt es die Eigenschaft Picture der Beispielschaltfläche auf eine leere Zeichenkette ein. In allen anderen Fällen weist die Prozedur der Eigenschaft Picture den Namen des Bildes aus der Tabelle MSysResources zu, also beispielsweise ok oder close:

Private Sub BildEinstellen()
     If Me!cboBilder = 0 Then
         Me!cmdBeispiel.Picture = ""
     Else
         Me!cmdBeispiel.Picture = Me!cboBilder.Column(1)
     End If
End Sub

Hintergrund transparent schalten

Das Kontrollkästchen chkTransparent soll die Eigenschaft BackStyle entweder auf den Wert 0 einstellen (transparent) oder auf den Wert 1 (ausgefüllt).

Dies wird direkt nach dem Wählen eines neuen Wertes auf die Beispielschaltfläche angewendet:

Private Sub chkTransparent_AfterUpdate()
     If Me!chkTransparent Then
         Me!cmdBeispiel.BackStyle = 0
     Else
         Me!cmdBeispiel.BackStyle = 1
     End If
End Sub

Beschriftungsanzeige einstellen

Das Kombinationsfeld cboBeschriftungAnzeigen erlaubt es, einen der sechs vorgesehenen Werte für die Eigenschaft Anordnung der Bildbeschriftung vorzunehmen. Die sechs Werte tragen wir direkt in die Eigenschaft Datensatzherkunft des Kombinationsfeldes ein:

"0";"Keine Beschriftung";"1";"Standard";2;"Beschriftung oben";3;"Beschriftung unten";4;"Beschriftung links";5;"Beschriftung rechts"

Damit nur die Texte und nicht die Zahlen angezeigt werden und die Liste überhaupt korrekt verarbeitet wird, legen Sie die Eigenschaft Herkunftstyp auf Wertliste, Spaltenanzahl auf 2 und Spaltenbreiten auf 0cm fest.

Nach der Auswahl eines der Werte wird der passende Zahlenwert der VBA-Eigenschaft PictureCaptionArrangement zugewiesen. Anschließend erfolgt der obligatorische Aufruf der Prozedur GroesseOptimieren:

Private Sub cboBeschriftungAnzeigen_AfterUpdate()
     Me!cmdBeispiel.PictureCaptionArrangement =  Me!cboBeschriftungAnzeigen
     GroesseOptimieren
End Sub

Abstand zwischen Bild und Schrift einstellen

Wenn Sie einer Schaltfläche ein Icon und einen Text zuweisen, kann es sein, dass der Platz zwischen beiden Elementen etwas zu klein ist. Dann bietet es sich an, dem Text ein oder mehrere Leerzeichen voranzustellen. Das erledigen wir mit dem Kombinationsfeld cboAbstandBildSchrift, das die Werte 0;1;2;3 als Wertliste anzeigt. Nach der Auswahl eines Wertes mit diesem Feld feuert das Ereignis Nach Aktualisierung und löst die folgende Ereignisprozedur aus:

Private Sub cboAbstandBildSchrift_AfterUpdate()
     Dim strLeerzeichen As String
     strLeerzeichen = Space(Me!cboAbstandBildSchrift)
     Me!cmdBeispiel.Caption =  strLeerzeichen & strBeschriftung
     GroesseOptimieren
End Sub

Die Prozedur speichert eine Zeichenkette mit der dem Zahlenwert entsprechen Menge Leerzeichen in der Variablen strLeerzeichen. Dann fügt sie diese vor der Beschriftung aus strBeschriftung ein und weist das Ergebnis der Eigenschaft Caption der Beispielschaltfläche zu. Schließlich ruft auch diese Prozedur die Routine GroesseOptimieren auf.

Bildgröße eingeben

Wir könnten theoretisch die zu verwendenden Bilder analysieren und die Größe per Code ermitteln. Das ist uns aber an dieser Stelle zu aufwendig, weshalb wir dem Benutzer selbst die Möglichkeit geben, die Bildabmessungen in die beiden Textfelder txtBildbreite und txtBildhoehe einzugeben.

Die Eingabe löst die folgenden Prozeduren aus, die jeweils die Routine GroesseOptimieren aufrufen:

Private Sub txtBildbreite_AfterUpdate()
     GroesseOptimieren
End Sub
Private Sub txtBildhoehe_AfterUpdate()
     GroesseOptimieren
End Sub

Fett dargestellte Beschriftung

Das Kontrollkästchen chkFetteSchrift gibt an, ob die Beschriftung der Schaltfläche fett angezeigt werden soll. Die Änderung des Wertes des Kontrollkästchens löst diese Prozedur aus, die das Format der Beschriftung der Beispielschaltfläche anpasst:

Private Sub chkFetteSchrift_AfterUpdate()
     Me!cmdBeispiel.FontBold = Me!chkFetteSchrift
     GroesseOptimieren
End Sub

Ereignisprozedur auswählen

Schließlich wollen wir dem Benutzer noch die Möglichkeit geben, den Inhalt der Ereignisprozedur, die durch das Ereignis Beim Klicken ausgelöst wird, festzulegen. Dazu haben wir eine Tabelle vorgesehen, um verschiedene Anweisungen zu speichern.

Diese Tabelle enthält die Felder Ereignis-prozedurID, Bezeichnung und Code und sieht im Entwurf wie in Bild 7 aus. Für das Feld Bezeichnung haben wir einen eindeutigen Index festgelegt, da jede Bezeichnung nur einmal vorkommen darf.

Entwurf der Tabelle zum Speichern der Prozedurinhalte

Bild 7: Entwurf der Tabelle zum Speichern der Prozedurinhalte

Für das Kombinationsfeld cboEreignisprozeduren legen wir die folgende Abfrage auf Basis der Tabelle tblEreignisprozeduren als Datensatzherkunft fest:

SELECT 0 AS EreignisprozedurID, ''<Keine Ereignisprozedur>'' AS Bezeichnung FROM tblEreignisprozeduren
UNION
SELECT EreignisprozedurID, Bezeichnung
FROM tblEreignisprozeduren
ORDER BY Bezeichnung;

Auch hier nutzen wir eine UNION-Abfrage, um einen zusätzlichen Eintrag zum Kombinationsfeld hinzuzufügen. Diese enthält den Wert 0 und den Text .

Und wieder stellen wir die beiden Eigenschaften Spaltenanzahl und Spaltenbreiten auf die Werte 2 und 0cm ein. Wenn der Benutzer einen Eintrag im Kombinationsfeld auswählt, geschieht ausnahmsweise einmal nichts – die Ereignisprozedur wird erst beim Abschließen des Assistenten zur neu erstellten Schaltfläche hinzugefügt.

Mit der Schaltfläche cmdEreignisprozedurenBearbeiten soll der Benutzer ein Formular zum Verwalten der Ereignisprozeduren öffnen können. Es löst die Prozedur aus Listing 2 aus.

Private Sub cmdEreignisprozedurenBearbeiten_Click()
     Dim lngEreignisprozedurID As Long
     If Nz(Me!cboEreignisprozeduren, 0) = 0 Then
         DoCmd.OpenForm "frmEreignisprozeduren", WindowMode:=acDialog, datamode:=acFormAdd
     Else
         DoCmd.OpenForm "frmEreignisprozeduren", WindowMode:=acDialog, WhereCondition:="EreignisprozedurID = " _
             & Me!cboEreignisprozeduren, datamode:=acFormEdit
     End If
     If IstFormularGeoeffnet("frmEreignisprozeduren") Then
         lngEreignisprozedurID = Nz(Forms!frmEreignisprozeduren!EreignisprozedurID, 0)
         If Not lngEreignisprozedurID = 0 Then
             Me!cboEreignisprozeduren = lngEreignisprozedurID
         End If
         DoCmd.Close acForm, "frmEreignisprozeduren"
     End If
End Sub

Listing 2: Ereignisprozedur zum Anzeigen des Dialogs für die Verwaltung von Ereignisprozeduren

Die Prozedur prüft zunächst, ob der Eintrag ausgewählt ist, also der Wert 0. Falls ja, wird ein Formular namens frmEreignisprozeduren als modaler Dialog im Modus zum Hinzufügen eines Datensatzes geöffnet. Anderenfalls erfolgt das Öffnen mit DoCmd.OpenForm im Bearbeitungsmodus und eine WhereCondition übergibt den Primärschlüsselwert des aktuell im Kombinationsfeld cboEreignisprozeduren gewählten Eintrags als Kriterium an das Formular.

In beiden Fällen läuft die Prozedur durch das Öffnen des Formulars frmEreignisprozeduren als modaler Dialog erst dann weiter, wenn das Formular geschlossen oder unsichtbar gemacht wird. Dann prüft die Prozedur, ob das Formular noch geöffnet ist. Falls ja, übernimmt die Prozedur den aktuell im Formular angezeigten Datensatz in das Kombinationsfeld cboEreignisprozeduren. Falls kein Datensatz ausgewählt ist, geschieht nichts. Das Formular wird dann einfach geschlossen.

Wenn das Formular schon geschlossen ist, geht die aufrufende Prozedur davon aus, dass der Benutzer das Formular frmEreignisprozeduren mit der Abbrechen-Schaltfläche geschlossen hat. Das Kombinationsfeld wird dann ebenfalls nicht aktualisiert.

Ereignisprozeduren verwalten

Zum Verwalten der Ereignisprozeduren legen wir ein Formular namens frmEreignisprozeduren an (siehe Bild 8). Dieses binden wir an die Tabelle tblEreignisprozeduren und ziehen die beiden Felder Bezeichnung und Code in den Detailbereich der Entwurfsansicht. Außerdem fügen wir ein Kombinationsfeld namens cboSchnellauswahl hinzu. Dieses verwendet ebenfalls die Tabelle tblEreignisprozeduren als Basis für die Datensatzherkunft. In diesem Fall stellen wir eine Abfrage zusammen, welche die beiden Felder EreignisprozedurID und Bezeichnung enthält, wobei die Einträge aufsteigend nach der Bezeichnung sortiert werden.

Entwurf des Formulars frmEreignisprozeduren

Bild 8: Entwurf des Formulars frmEreignisprozeduren

Da das Kombinationsfeld nur die Bezeichnungen der Ereignisprozeduren anzeigen soll und nicht die Primärschlüsselwerte, stellen wir noch die Eigenschaften Spaltenanzahl auf 2 und Spaltenbreiten auf 0cm ein.

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