COM-Add-In: Ereignisprozedur zur Laufzeit anzeigen

Bei unserer Arbeit mit Access passiert es immer wieder, dass wir schnell prüfen wollen, was eine durch ein bestimmtes Ereignis ausgelöste Prozedur überhaupt erledigt. Dann muss man in den Entwurf wechseln, einen Haltepunkt setzen, wieder den Formularentwurf aktivieren und dann das Ereignis auslösen. Wir wäre es mit einem Add-In, mit dem Sie die Ereignisse des aktuell markierten Steuerelements direkt anzeigen könnten Ein solches COM-Add-In wollen wir in diesem Beitrag entwickeln und vorstellen. Das ist ein perfekter Anwendungszweck für die neue Entwicklungsumgebung twinBASIC, die wir in Ausgabe 3/2021 im Detail vorgestellt haben.

Debuggen schwer gemacht

Kennen Sie das auch Sie geben testweise während der Entwicklung einer Anwendung Daten ein oder betätigen eine Schaltfläche, und es geschieht einfach nicht das, was Sie gerade erwarten. Also geht es ans Debuggen. Wechseln in die Entwurfsansicht des Formulars, dort das betreffende Steuerelement anklicken, damit seine Eigenschaften im Eigenschaftenblatt erscheinen, die passende Ereignisprozedur auswählen und auf die Schaltfläche mit den drei Punkten klicken (siehe Bild 1).

Üblicher Weg zum Anzeigen der Ereignisprozedur eines Steuerelements

Bild 1: Üblicher Weg zum Anzeigen der Ereignisprozedur eines Steuerelements

Der VBA-Editor erscheint und zeigt die durch das Ereignis ausgelöste Prozedur an. Hier setzen wir dann einen Haltepunkt, um den Prozedurablauf gleich im Detail ansehen zu können (siehe Bild 2).

Setzen eines Haltepunktes in der ersten Zeile einer Ereignisprozedur

Bild 2: Setzen eines Haltepunktes in der ersten Zeile einer Ereignisprozedur

Damit sind die Arbeiten im VBA-Editor vorerst erledigt und wir können zum Access-Fenster zurückkehren. Dort wechseln wir im aktuellen Formular wieder in die Formularansicht und führen den Vorgang erneut aus.

Gegebenenfalls ist es hierzu sogar noch notwendig, das Formular zu schließen und es anschließend über das Ribbon oder von einem anderen Formular aus erneut zu öffnen, damit die benötigte Datenkonstellation wieder vorhanden ist.

Wenn Sie das kennen, wissen Sie: Das ist anstrengend und wirkt irgendwie aufwendiger, als es sein muss. Das haben wir uns auch gedacht und ein COM-Add-In entwickelt, dass es beim Entwickeln einer Anwendung Folgendes erlaubt: Sie markieren einfach das zu untersuchende Steuerelement und wählen per Ribbon-Befehl aus allen Ereignissen der aktuellen Situation das zu untersuchende aus, welches dann automatisch im VBA-Editor angezeigt wird.

Debuggen, die leichte Version

Nun schauen wir uns erst einmal an, was wir am Ende des Beitrags für eine Lösung erhalten. Wenn Sie nach der Installation des COM-Add-Ins ein Steuerelement markieren, können Sie einfach das Ribbon-Menü Ereignisprozeduren anzeigen in der Gruppe Steuerelemente des Tabs amvAccessTools anzeigen. Hier finden Sie ganz oben die Ereignisprozeduren für das aktuelle Hauptformular, in diesem Fall Form_Load. Darunter zeigt die Liste für dieses Beispiel die drei Ereignisprozeduren für das Steuerelement ctlTreeView (siehe Bild 3).

Anzeige der Ereignisprozedur per Ribbon-Befehl

Bild 3: Anzeige der Ereignisprozedur per Ribbon-Befehl

Wählen Sie einen dieser Einträge aus, erscheint der VBA-Editor und die ausgewählte Prozedur wird markiert angezeigt (siehe Bild 4). Wenn Sie ein Steuerelement in einem Unterformular selektieren, werden auch noch die Ereignisprozeduren des Unterformulars in der Liste angezeigt. Für weitere Verschachtelungsebenen ist die Lösung in der hier vorgestellten Form jedoch nicht ausgelegt.

Anzeige und Markierung der Ereignisprozedur

Bild 4: Anzeige und Markierung der Ereignisprozedur

Programmieren des COM-Add-Ins

Das COM-Add-In programmieren wir mit dem neuen Tool twinBASIC, das wir im Beitrag twinBASIC – VB/VBA mit moderner Umgebung (www.access-im-unternehmen.de/1303) im Detail vorgestellt haben. Hier erfahren Sie auch, wie Sie twinBASIC installieren. Wie Sie ein COM-Add-In grundsätzlich programmieren, beschreibt der Beitrag twinBASIC – COM-Add-Ins für Access (www.access-im-unternehmen.de/1306).

Wir starten mit dem aktuellen Beispielprojekt für ein COM-Add-In für Access, das Sie im Download zu diesem Beitrag in der Zip-Datei twinBASIC_myCOMAddin.zip finden.

Projekt öffnen

Nachdem Sie Visual Studio Code und twinBASIC wie im oben genannten Beitrag installiert haben, öffnen Sie das Projekt durch einen Doppelklick auf die Datei myCOMAddin.code-workspace.

Projektelemente umbenennen

Als Erstes nehmen wir einige Änderungen bezüglich der Benennung von Projekt, Klasse et cetera vor. Dazu öffnen Sie die durch einen Mausklick auf den Eintrag Settings im Projekt-Explorer die Einstellungen des Projekts.

Hier sehen Sie ganz oben die beiden Einträge Project: Name und Project: Description. Diese passen Sie wie in Bild 5 an. Wichtig: Merken Sie sich den Namen, den Sie für das Projekt vergeben, hier amvEreignisprozedurAnzeigen, – diesen benötigen wir gleich noch. Wichtig: Betätigen Sie auf jeden Fall die Tastenkombination Strg + S, um die Änderungen zu speichern!

Anpassen der Benennung von Elementen

Bild 5: Anpassen der Benennung von Elementen

Klassenname ändern

Dann schauen wir uns die Klasse des Projekts an, was wir durch einen Klick auf den Eintrag HelloWorld.twin erreichen. Diesen Eintrag ändern wir, indem wir seinen Kontextmenü-Befehl Umbenennen aufrufen und dann etwa die Bezeichnung EreignisprozedurenAnzeigen.twin eingeben.

Auch im Code der Klasse stellen wir den Namen wie folgt um:

Class EreignisprozedurAnzeigen
     Implements IDTExtensibility2
      ...

Verweise auf Bibliotheken anlegen

Schließlich benötigen wir für die nachfolgende Programmierung noch Verweise auf ein paar weitere Bibliotheken. Diese legen wir wieder im Bereich Settings an. Hier fügen wir im Bereich COM Type Library / ActiveX References die beiden folgenden Verweise hinzu:

  • Microsoft Access 16.0 Object Library
  • Microsoft Visual Basic for Applications Extensibility 5.3

Der Bereich sollte danach wie in Bild 6 aussehen.

Hinzufügen von Verweisen

Bild 6: Hinzufügen von Verweisen

COM-Add-In für Access vorbereiten

Die Klasse EreignisprozedurAnzeigen enthält nun bereits einige grundlegende Elemente. Zum Beispiel legt die Zeile Implements IDTExtensibility2 fest, dass die Klasse die angegebene Schnittstelle implementiert. Das bedeutet, dass wir die für die Schnittstelle vorgegebenen Ereignisprozeduren anlegen müssen.

Die wichtigste Ereignisprozedur ist in unserem Fall OnConnection. Wenn Sie Access öffnen, startet es die in der Registry angegebenen COM-Add-Ins (mehr zur Registrierung weiter unten). Dabei wird direkt OnConnection aufgerufen und der Parameter Application liefert einen Verweis auf die aufrufende Anwendung, in diesem Fall Access. Den Inhalt dieses Parameters schreiben wir direkt in die zuvor deklarierte Variable objApplication, die mit dem Datentyp Access.Application deklariert ist.

Außerdem implementiert die Klasse eine weitere Schnittstelle namens IRibbonExtensibility. Diese wird benötigt, um vom COM-Add-In aus Ribbon-Anpassungen vorzunehmen. Hier müssen wir zusätzlich noch die Eigenschaft WithDispatchForwarding voranstellen:

[WithDispatchForwarding]
Implements IRibbonExtensibility

Schließlich benötigen wir noch eine Objektvariable, mit der wir die Ribbon-Erweiterung referenzieren können:

Public objRibbon As IRibbonUI

Das Grundgerüst der Klasse haben wir in Listing 1 abgebildet.

Class EreignisprozedurAnzeigen
     Implements IDTExtensibility2
     [WithDispatchForwarding]
     Implements IRibbonExtensibility
     
     Private objApplication As Access.Application
    
     Sub OnConnection(ByVal Application As Object, ByVal ConnectMode As ext_ConnectMode, _
             ByVal AddInInst As Object, ByRef custom As Variant()) Implements IDTExtensibility2.OnConnection
         Set objApplication = Application
     End Sub
     
     Sub OnDisconnection(ByVal RemoveMode As ext_DisconnectMode, ByRef custom As Variant()) _
         Implements IDTExtensibility2.OnDisconnection
     End Sub
     
     Sub OnAddInsUpdate(ByRef custom As Variant()) Implements IDTExtensibility2.OnAddInsUpdate
     End Sub
     
     Sub OnStartupComplete(ByRef custom As Variant()) Implements IDTExtensibility2.OnStartupComplete
     End Sub
     
     Sub OnBeginShutdown(ByRef custom As Variant()) Implements IDTExtensibility2.OnBeginShutdown
     End Sub
     ...
End Class

Listing 1: Grundstruktur des COM-Add-Ins

Aufruf über das Ribbon    

Die Funktion des COM-Add-Ins soll, wie eingangs erwähnt, über einen Befehl beziehungsweise ein Menü im Ribbon bereitgestellt werden. Damit dieses erscheint, müssen wir die Ribbon-Erweiterung, die das COM-Add-In bereitstellt, über die ebenfalls beim Start des Add-Ins aufgerufene Funktion GetCustomUI zusammenstellen und als Rückgabewert dieser Funktion definieren.

In dieser stellen wir den kompletten XML-Ausdruck für die Ribbon-Erweiterung zusammen (siehe Listing 2).

Private Function GetCustomUI(ByVal RibbonID As String) As String _
     Implements IRibbonExtensibility.GetCustomUI
     Dim strXML As String
     strXML &= "<customUI xmlns=""http://schemas.microsoft.com/office/2006/01/customui"" onLoad=""OnLoad"">" & vbCrLf
     strXML &= "  <ribbon startFromScratch=""false"">" & vbCrLf
     strXML &= "    <tabs>" & vbCrLf
     strXML &= "      <tab id=""tabTest"" label=""amvAccessTools"">" & vbCrLf
     strXML &= "        <group id=""grpSteuerelemente"" label=""Steuerelemente"">" & vbCrLf
     strXML &= "          <dynamicMenu id=""dmnEvents"" label=""Ereignisprozeduren anzeigen""" _
         & " getContent=""GetContent"" imageMso=""CreateModule"" size=""large""/>" & vbCrLf
     strXML &= "        </group>" & vbCrLf
     strXML &= "      </tab>" & vbCrLf
     strXML &= "    </tabs>" & vbCrLf
     strXML &= "  </ribbon>" & vbCrLf
     strXML &= "</customUI>" & vbCrLf
     Return strXML
End Function

Listing 2: Diese Funktion setzt das Ribbon zusammen.

Dies liefert eine XML-Definition wie die folgende:

<customUI xmlns="http://schemas.microsoft.com/ office/2006/01/customui" onLoad="OnLoad">
     <ribbon startFromScratch="false">
     <tabs>
       <tab id="tabTest" label="amvAccessTools">
         <group id="grpSteuerelemente"  label="Steuerelemente">
           <dynamicMenu id="dmnEvents"  label="Ereignisprozeduren anzeigen"  getContent="GetContent"  imageMso="CreateModule" size="large"/>
         </group>
       </tab>
     </tabs>
   </ribbon>
</customUI>

Das Kernstück ist das dynamicMenu-Element, das mit der getContent-Callback-Funktion beim Aufklappen dynamisch die Ereignisprozeduren für die aktuell markierten Elemente zusammenstellen soll.

Die dazu notwendige Funktion schauen wir uns weiter unten an.

Ribbon per Variable referenzieren

Wichtig ist auch noch, dass wir für das Attribut onLoad des Elements customUI eine Callback-Funktion angeben, die beim ersten Laden des Ribbons ausgelöst wird.

Diese schreibt den mit dem Parameter ribbon gelieferten Verweis auf das Ribbon in die weiter oben deklarierte Variable objRibbon:

Sub OnLoad(ribbon As IRibbonUI)
     Set objRibbon = ribbon
End Sub

Warum benötigen wir dies Weil beim Öffnen des dynamicMenu-Elements die Callbackfunktion zum Zusammenstellen des Menüs nur einmal aufgerufen wird – außer, wir mach diese “ungültig”. Und dazu müssen wir eine Methode der Objektvariablen für das IRibbonUI-Objekt aufrufen.

dynamicMenu beim Aufklappen des Menüs füllen

Nun kommt der spannende Teil. Wie füllen wir das dynamicMenu-Element beim Aufklappen des Menüs Die erste Anmerkung ist für Programmierer, die bereits einmal dynamicMenu-Elemente unter Access verwendet haben.

Hier unter twinBASIC nutzen Sie eine etwas andere Syntax als unter VBA. Unter VBA lautet die erste Zeile der Callbackfunktion:

Sub GetContent(control As IRibbonControl, ByRef XMLString)

Unter twinBASIC verwenden wir die Deklaration wie unter VB6, die etwas anders aussieht:

Function GetContent(control As IRibbonControl) As String

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

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

Schreibe einen Kommentar