Ereignisse in Klassen programmieren

Möchtest Du den gesamten Artikel lesen? Und vielleicht sogar den Artikel im PDF-Format und die Beispieldateien herunterladen? Dann hole Dir den Artikel gleich hier - völlig kostenlos!

Eines der wichtigsten Features vieler eingebauter Klassen in den Office-Anwendungen sind die Ereignisse. Damit können wir Ereignisprozeduren implementieren, mit denen wir beispielsweise auf das Anklicken von Schaltflächen, dem Öffnen oder Schließen von Dokumenten oder dem Wechseln eines Tabellenblatts in einem Excel-Arbeitsblatt reagieren können. Wenn man selbst Klassen programmiert, findet sich früher oder später ein Anlass, dieser ein eigenes Ereignis hinzuzufügen, dass durch eine bestimmte Aktion ausgelöst wird. Dieser Artikel zeigt, wir wie solche Ereignisse programmieren und auslösen und wie wir diese in Form von Ereignisprozeduren in den Klassen implementieren, welche das entsprechende Objekt instanziiert haben.

Ereignisse in Klassenmodulen

Wer schon einmal eine Ereignisprozedur beispielsweise für das Anklicken einer Schaltfläche, das Öffnen eines Word-Dokuments, das Markieren eines Ranges in Excel et cetera programmiert hat, kennt zumindest schon einmal die Verbraucherseite von Ereignissen.

Hier können wir zum Beispiel in Excel in der Klasse Tabelle1 eines Excel-Dokuments im Codefenster im linken Kombinationsfeld den Eintrag Worksheet auswählen, was im rechten Kombinationsfeld automatisch die Standardmethode SelectionChange selektiert. Dadurch wird automatisch die Ereignisprozedur Worksheet_SelectionChange angelegt, mit der wir in diesem Fall die Adresse des neu ausgewählten Bereichs im Direktbereich des VBA-Editors ausgeben (siehe Bild 1).

Ereignisprozedur beim Ändern der Markierung in einem Excel-Arbeitsblatt

Bild 1: Ereignisprozedur beim Ändern der Markierung in einem Excel-Arbeitsblatt

Nun schauen wir uns die andere Seite an, auf der wir Ereignisse definieren, die wir dann wiederum als Verbraucher nutzen können. Wozu aber überhaupt Ereignisse? Weil wir benutzerdefiniert auf bestimmte Ereignisse reagieren können wollen. Stellen wir uns beispielsweise vor, wir wollen den Benutzer unserer Klasse clsAdresse darüber informieren, wenn die Methode Leeren erfolgreich aufgerufen wurde. Dann können wir das einfach erledigen, indem wir der Methode Leeren eine entsprechende Meldung hinzufügen:

Public Sub Leeren()
     ...
     m_Land = ""
     MsgBox "Die Eigenschaften der Adresse wurden geleert.", _
         vbOKOnly + vbExclamation, "Adresse geleert"
End Sub

Rufen wir die Methode nun von einer anderen Prozedur aus auf, erscheint diese Meldung (siehe Bild 2).

Meldung beim Aufruf einer Methode

Bild 2: Meldung beim Aufruf einer Methode

Nun stellen wir uns vor, wir wollen die Meldung dieser Klasse nicht innerhalb der Klasse verdrahten, sondern dem Entwickler, der diese Klasse in seinem Code verwendet (meist wir selbst), die Möglichkeiten geben wollen, individuell auf dieses Ereignis zu reagieren.

Das ist ein Beispieleinsatzzweck für die Bereitstellung eines Ereignisses. Und das gelingt in zwei Schritten:

  • Als Erstes definieren wir das Ereignis mit dem Schlüsselwort Event, dem Namen des Ereignisses und gegebenenfalls den zu verwendenden Parametern.
  • Als zweites fügen wir in diesem Beispiel der Methode Leeren Code hinzu, der dieses Ereignis auslöst. Dabei verwenden wir das Schlüsselwort RaiseEvent und übergeben die Werte für die Parameter, welche das Verbraucher des Ereignisses erhalten soll.

In der Klasse fügen wir oben die Deklaration des Ereignisses ein:

Public Event NachDemLeeren()

Der Prozedur Leeren fügen wir am Ende den Befehl RaiseEvent hinzu und geben den Namen des Ereignisses als Parameter an:

Public Sub Leeren()
     ...
     RaiseEvent NachDemLeeren
End Sub

Dieses wird, wie in Bild 3 dargestellt, per IntelliSense angeboten. Dadurch geschieht nun erst einmal nichts. Wir können die obige Prozedur AdressblockLeeren starten und die Methode Leeren aufrufen, aber wir erhalten keinen sichtbaren Effekt. Das ist logisch, denn wir haben das Ereignis noch nicht implementiert.

Deklarieren und Auslösen eines Ereignisses

Bild 3: Deklarieren und Auslösen eines Ereignisses

Keine Ereignisprozeduren ohne das Schlüsselwort WithEvents

Der Schritt ist auch in dieser Konstellation nicht möglich, denn um die Ereignisse einer Klasse zu implementieren, müssen die Klasse, die das Ereignis enthält, mit einem bestimmten Schlüsselwort deklarieren. Dieses heißt WithEvents. Es gibt noch weitere Bedingungen: Diese Deklaration kann nicht innerhalb einer Prozedur erfolgen, sondern muss im Kopf des Moduls hinterlegt werden. Außerdem können wir das Schlüsselwort WithEvents nicht innerhalb von Standardmodulen verwenden, sondern nur in Klassenmodulen. Versuchen wir dies dennoch, erhalten wir direkt einen Kompilierfehler wie in Bild 4.

Fehler beim Versuch, WithEvents in einem Standardmodul zu verwenden

Bild 4: Fehler beim Versuch, WithEvents in einem Standardmodul zu verwenden

Warum aber benötigen wir dieses Schlüsselwort überhaupt? Wenn wir in Word auf die Ereignisse des Document-Objekts zugreifen oder in Access auf ein Form– oder Button-Element, können wir das auch einfach ohne WithEvents-Schlüsselwort erledigen.

Das ist dann allerdings reiner Zufall: Bei Word waren wir dann vermutlich im Klassenmodul zum Word-Dokument und in Access im Klassenmodul des Formulars, in dem sich auch die Schaltfläche befand, deren Ereignisse wir implementiert haben. Da es sich um das Klassenmodul des Objekts selbst handelt, stehen dort alle Ereignisse standardmäßig zur Verfügung.

Würden wir jedoch die Ereignisse dieses Word-Dokuments oder Access-Formulars von einem anderen Klassenmodul aus implementieren wollen, müssten wir dazu auch erst einmal eine Objektvariable anlegen, die wir mit dem Schlüsselwort WithEvents deklarieren. Und wir müssten diese auch noch mit einem Verweis auf das entsprechende Objekt versehen.

Genauso ist es bei der Klasse clsAdresse: Diese verwenden wir von einer anderen Klasse aus, also müssen wir die Objektvariable mit dem Schlüsselwort WithEvents versehen – und das gelingt wiederum nur in Klassenmodulen. Welche Art von Klassenmodul wir hier verwenden, spielt allerdings keine Rolle. Wir können die Klasse sowohl innerhalb des Klassenmoduls eines eingebauten Elements wie einem Word-Dokument, einem Excel-Workbook oder einem Access-Formular deklarieren, aber auch in einem anderen alleinstehenden Klassenmodul.

Damit Du die Beispiele dieses Artikels in allen Office-Anwendungen ausprobieren kannst, erstellen wir zu diesem Zweck ein neues Klassenmodul namens clsAdressenVerwalten.

Diese fügen wir die Deklaration der Objektvariablen ein, der wie die Instanz der Klasse clsAdresse zuweisen wollen:

Private WithEvents objAdresse As clsAdresse

Außerdem fügen wir eine Methode hinzu, die das Objekt erstellt und seine Eigenschaften füllt:

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

2 Kommentare

Schreibe einen Kommentar