Formulare zur Laufzeit analysieren

Wenn Sie selbst eine Anwendung programmieren und ein Formular nicht so funktioniert wie gewünscht, wissen Sie, wie die Steuer-elemente heißen, an welche Datenquellen sie gebunden sind und so weiter. Vielleicht ist die Entwicklung der Anwendung auch etwas länger her und Sie müssen sich erst wieder einarbeiten – oder Sie erhalten von einem Kunden eine Anwendung mit der Bitte, dort eine Funktion in einem Formular zu überprüfen. In den beiden letzteren Fällen ist es recht mühsam, zwischen Formular- und Entwurfsansicht zu wechseln, um Steuerelementnamen, Datenherkünfte und andere Informationen herauszufinden, die zur Lösung des Problems beitragen könnten. Der vorliegende Beitrag zeigt, wie Sie ein Formular schnell mithilfe eines zur Laufzeit hinzugefügten Kontextmenüs analysieren können, um schneller Lösungen zu finden.

Die üblichen Mittel, die einem zur Verfügung stehen, um Informationen über das Formular, die enthaltenen Steuer-elemente oder ihre Eigenschaften zu ermitteln, sind die Elemente der Screen-Klasse. Dieses bietet Eigenschaften wie ActiveForm für das Ermitteln eines Verweises auf das aktuelle Formular oder ActiveControl für das Ermitteln des aktuellen Steuerelements.

Den Namen des aktuellen Formulars können Sie so beispielsweise über das Direktfenster ermitteln, ohne in die Entwurfsansicht wechseln zu müssen. Dazu geben Sie den folgenden Befehl ein:

Debug.Print Screen.ActiveForm.Name

Vielleicht wollen Sie auch auf die Eigenschaften des aktuellen Steuer-elements zugreifen. Dann verwenden Sie ActiveControl:

Debug.Print Screen.ActiveControl.Name

Wenn Sie dann auf eine spezielle Eigenschaft des Formulars oder Steuerelements zugreifen wollen, die Sie nicht genau kennen, weil Sie diese sonst immer per IntelliSense eingeben, wird es allerdings schwierig, weil zumindest Screen.ActiveControl nur einige allgemeine Eigenschaften liefert.

Geplante Lösung

Was wir nun machen wollen, ist die Bereitstellung aller Eigenschaften eines Formulars oder Steuerelements über das Kontextmenü des jeweiligen Elements. Wenn der Entwickler also mit der rechten Maustaste auf ein Formular oder Steuer-element klickt, soll ein Kontextmenü erscheinen, das zusätzlich zu den eingebauten Befehlen noch weitere Einträge enthält – einen, der direkt den Namen des Elements anzeigt und einen, der in einem Untermenü alle Eigenschaften des Elements samt Werten liefert.

Das soll etwa wie in Bild 1 aussehen. Diese Kontextmenü-Einträge wollen wir für alle Elemente des Formulars liefern – also sowohl für das Formular selbst, für die Steuer-elemente als auch für die Elemente in Unterformularen, unabhängig davon, ob es sich um die Datenblatt- oder die Formularansicht handelt.

Anzeige der Eigenschaften per Kontextmenü

Bild 1: Anzeige der Eigenschaften per Kontextmenü

Realisierung

Im aufwendigsten Fall fügt man für jedes Formular und für jedes Steuer-element eine Ereignisprozedur hinzu, die durch das Ereignis Bei Maustaste ab ausgelöst wird.

In dieser Prozedur prüft man dann, ob der Benutzer die linke oder die rechte Taste gedrückt hat. Im Falle der rechten Maustaste soll dann das nun anzuzeigende Kontextmenü erweitert werden, und zwar um ein Element mit dem Namen des Formulars oder Steuerelements und mit einem Untermenü mit den Eigenschaften des Elements.

Allerdings müsste man das dann für alle Formulare und Steuer-elemente machen, die man untersuchen möchte – und das wollen wir nicht. Stattdessen arbeiten wir, wie schon des Öfteren, mit zwei Klassenmodulen, denen wir die Formulare und Steuer-elemente zuweisen und welche die notwendigen Ereignisprozeduren bereits enthalten.

Diese schauen wir uns nun an – zuerst das Klassenmodul, mit dem wir das Formular referenzieren und das die Kontextmenü-Befehle für dieses bereitstellt.

Klassenmodul für die Kontextmenüs in Formularen

Dieses Klassenmodul nennen wir clsForm.

Das Formular verwendet die folgenden Variablen:

Private WithEvents m_frm As Form
Private WithEvents m_Detail As Section
Public colControls As Collection
Private m_IsSubform As Boolean

Die beiden Variablen m_frm und m_Detail werden mit dem Schlüsselwort WithEvents ausgestattet, wodurch wir in dem Klassenmodul, in dem die Objekte deklariert sind, Ereignisprozeduren für diese Objekte implementieren können.

Die Klasse stellt eine öffentliche Eigenschaft namens Form zur Verfügung, die das mit den Kontextmenüs auszustattende Formular entgegennimmt und die wie folgt aussieht:

Public Property Set Form(frm As Form)
     Dim objControl As clsControl
     Dim ctl As Control
     Set m_frm = frm
     With m_frm
         .OnMouseDown = "[Event Procedure]"
     End With
     Set m_Detail = Form.Section(0)
     With m_Detail
         .OnMouseDown = "[Event Procedure]"
     End With
     Set colControls = New Collection
     For Each ctl In m_frm.Controls
         Set objControl = New clsControl
         With objControl
             .IsSubform = m_IsSubform
             Set .Control = ctl
             colControls.Add objControl
         End With
     Next ctl
End Property

Diese Property Set-Prozedur speichert zunächst den mit frm übergebenen Verweis auf das betreffende Formular in der Variablen m_frm. Dann stellt es für die Ereignis-eigenschaft Bei Maustaste ab (OnMouseDown) des Formulars den Wert Ereignisprozedur ein ([Event Procedure]). Danach ermittelt die Prozedur den Detailbereich des Formulars und referenziert diesen mit der Variablen m_Detail. Auch dafür stellt sie den Wert [Event Procedure] für die Eigenschaft OnMouseDown ein. Danach durchläuft die Methode die Steuerelemente im Formular und legt für jedes Steuer-element eine neue Instanz der Klasse clsControl, die wir weiter unten erläutern, an und weist der Eigenschaft Control dieses Objekts das aktuelle Steuer-element zu. Gegebenenfalls befinden wir uns gerade in einem Unterformular, dann wird noch der Wert True für die Eigenschaft IsSubform übergeben. Schließlich landen alle Objekte auf Basis der Klasse clsControl in der Collection colControls.

Rechter Mausklick auf Formular oder Detailbereich

Wenn der Benutzer mit der rechten Maustaste auf das Formular oder den Detailbereich klickt, löst er die Prozedur m_Detail_MouseDown aus. Diese legen Sie an, indem Sie im Codefenster der Klasse clsForm im linken Kombinationsfeld den Eintrag m_Detail und im rechten den Eintrag MouseDown auswählen (siehe Bild 2).

Anlegen einer Ereignisprozedur für eine Objektvariable

Bild 2: Anlegen einer Ereignisprozedur für eine Objektvariable

Dadurch wird eine Ereignisprozedur angelegt, die wir wie in Listing 1 ergänzen. Hier deklarieren wir zunächst zwei Variablen, um eine Menüleiste und eine Menüschaltfläche zu referenzieren.

Private Sub m_Detail_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
     Dim cbr As CommandBar
     Dim cbb As CommandBarButton
     If m_frm.CurrentView = acCurViewDatasheet Then
         Set cbr = CommandBars("Form DataSheetCell")
     Else
         If m_IsSubform Then
             Set cbr = CommandBars("Form View Subform")
         Else
             Set cbr = CommandBars("Form View popup")
         End If
     End If
     On Error Resume Next
     Do While Err.Number = 0
         cbr.Controls("Steuerelement-Infos anzeigen").Delete
     Loop
     On Error Resume Next
     Do While Err.Number = 0
         cbr.Controls("Eigenschaften").Delete
     Loop
     Set cbb = cbr.Controls.Add(msoControlButton, , , , True)
     With cbb
         If m_IsSubform Then
             .Caption = "Unterformular: " & m_frm.Name
         Else
             .Caption = "Formular: " & m_frm.Name
         End If
     End With
     PropertiesHinzufuegen cbr
End Sub

Listing 1: Prozedur beim Mausklick auf ein Formular

Kontextmenüs identifizieren

Nun folgen wichtige Schritte, in denen wir festlegen, welches Kontextmenü überhaupt mit unseren zusätzlichen Einträgen versehen werden soll. Access zeigt nämlich immer andere Kontextmenüs an, wenn Sie unterschiedliche Elemente mit der rechten Maustaste anklicken – und deren Namen wir durch den Aufruf einer bestimmten Prozedur ermitteln können. Diese sieht wie folgt aus:

Public Sub ButtonMitNameZuKontextmenuesHinzufuegen()
     Dim cbr As CommandBar
     Dim cbb As CommandBarButton
     For Each cbr In CommandBars
         On Error Resume Next
         Set cbb = cbr.Controls.Add( msoControlButton, , , , True)
         cbb.Caption = cbr.Name
         If Not Err.Number = 0 Then
             Debug.Print cbr.Name
         End If
         On Error GoTo 0
     Next
End Sub

Die Prozedur durchläuft alle Einträge der CommandBars-Auflistung von Access und fügt jedem ein Element des Typs msoControlButton hinzu, also eine einfache Schaltfläche.

Die Beschriftung des jeweiligen Elements füllen wir mit dem Namen des aktuellen Kontextmenüs. Dadurch zeigt jedes Kontextmenü von nun an als letzten Eintrag seinen Namen an – wie am Beispiel eines Datenblatts zu erkennen (siehe Bild 3).

Anzeige des Kontextmenü-Namens im Kontextmenü

Bild 3: Anzeige des Kontextmenü-Namens im Kontextmenü

Kontextmenü im Kontext des jeweiligen Objekts anpassen

Dann prüfen wir, ob das aktuelle Formular in der Datenblattansicht angezeigt wird, was der Fall ist, wenn die Eigenschaft CurrentView den Wert acCurViewDatasheet liefert. In diesem Fall erstellen wir ein CommandBar-Objekt auf Basis des Menüs Form DataSheetCell.

Anderenfalls, also wenn das Formular nicht in der Datenblattansicht angezeigt wird, prüfen wir den Inhalt der Variablen m_IsSubform. Ist dieser True, befinden wir uns gerade in einem Unterformular. Dann zeigt der rechte Mausklick das Menü Form View Subform an, welches wir der Variablen cbr zuweisen. Ist es kein Unterformular, verwenden wir das Kontextmenü namens Form View Popup.

Danach löschen wir alle eventuell bereits aus vorherigen Anwendungen vorhandenen Schaltflächen mit den Beschriftungen Steuerelement-Infos anzeigen und Eigenschaften aus dem Kontextmenü. Das erledigen wir bei deaktivierter Fehlerbehandlung in jeweils einer Do While-Schleife, die verlassen wird, wenn ein Fehler aufgetaucht ist – und das geschieht, wenn das Löschen der genannten Elemente nicht mehr erfolgreich ist, weil kein passendes Element mehr gefunden werden konnte.

Dann fügen wir mit der Add-Methode der Controls-Auflistung der Menüleiste aus cbr ein neues Element zur Menüleiste hinzu und referenzieren dieses mit der Variablen cbb.

Für diese legen wir dann die Beschriftung fest, wobei diese wieder vom Wert der Variablen m_IsSubform abhängt. Weist diese den Wert True auf, haben wir ein Unterformular und geben den Text Unterformular gefolgt von einem Doppelpunkt und den aus m_frm.Name ermittelten Formularnamen an. Anderenfalls lautet der Text Formular: plus dem Formularnamen.

Schließlich rufen wir die Prozedur PropertiesHinzufuegen auf und übergeben dieser die Variable mit dem Verweis auf das CommandBar-Objekt.

Eigenschaften in Kontextmenü eintragen

Die Prozedur PropertiesHinzufuegen trägt die Eigenschaften des Formulars als Elemente des noch hinzuzufügenden Untermenüs Eigenschaften ein (siehe Listing 2). Sie erwartet eine Verweis auf das CommandBar-Objekt, dem das Untermenü hinzugefügt werden soll und deklariert die Variablen cbp (CommandBarPopup, für das Untermenü), prp (Property, für das Durchlaufen der Eigenschaften des Formulars) und cbb (CommandBarButton, für die anzulegenden Elemente im Untermenü).

Private Sub PropertiesHinzufuegen(cbr As CommandBar)
     Dim cbp As CommandBarPopup
     Dim prp As DAO.Property
     Dim cbb As CommandBarButton
     Set cbp = cbr.Controls.Add(msoControlPopup, , , , True)
     On Error Resume Next
     Do While Err.Number = 0
         cbr.Controls("Eigenschaften").Delete
     Loop
     On Error GoTo 0
     cbp.Caption = "Eigenschaften"
     For Each prp In m_frm.Properties
         Set cbb = cbp.Controls.Add(msoControlButton, , , , True)
         On Error Resume Next
         cbb.Caption = prp.Name & ": " & prp.Value
         On Error GoTo 0
     Next prp
End Sub

Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

Workplace

Jahresabonnement TestzugangOder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar