|
|
VB6 erlaubt die Verwendung von Kassen, wenn auch nicht alle Funktionen unterstützt werden die zT. in anderen Sprachen enthalten sind (zB Vererbung.) Hier wird das Klassenmodell in VB6 beschrieben.
Einige Begriffe die man in Verbindung mit Klassen verwendet sind wichtig um die Beschreibungen zu verstehen. Um ein Überblick der verwendeten Begriffe zu erhalten sind sie hier kurz erklärt.
| Begriff | Bedeutung |
| Objekt-Orientiertes-Programmieren (OOP) | Ist der Oberbegriff für alles rund um Klassen und ihren Eigenschaften. Es bedeutet kurz gesagt das Programmstrukturen sich nicht nur um Daten und Prozeduren drehen, sondern um Objekte welche alles enthalten was sie benötigen um mit ihren Daten umgeben zu können, inklusive der Prozeduren, all dies wird in Objekten gekapselt. Und es bedeutet auch das Programme nicht mehr linear strukturiert sein müssen sondern Ereignisse dann behandelt werden wenn sie auftreten. |
| Klasse | Ist der Konstruktionsplan für Objekte, man könnte sie mit einem Type vergleichen mit dem Unterschied das nicht nur Daten sondern auch Prozeduren und noch mehr enthalten sein können. Eine Kasse enthält in sich alle Prozeduren die sie benötigt um mit den eigenen Daten umgehen zu können. |
| Objekt | Ist die verkörpert einer Klasse die aus dem Konstruktionsplan erstellt wurde und Speicher deklariert. Ähnlich wie von einem Type eine Variable deklariert werden kann, kann von einer Klasse ein Objekt deklariert werden. Ein Objekt kann die Struktur einer Klasse selbst abbilden, oder auf ein anderes Objekt verweisen. |
| Instanz | Wird aus einer Klasse ein Objekt erzeugt, wird dies Instanzieren genannt, ein Objekt ist dann eine Instanz der Klasse. |
| Referenz | Ein Objekt kann auch eine Referenz also ein Verweis (oder Stellvertreter) zu einem instanzierten Objekt sein, das bedeutet das viele Objekte als Reverenzen auf die gleiche Instanz eines Objekts verweisen können. Ändert sich der Wert in der Instanz ändert sich dieser auch für alle Reverenzen, die ja die Werte selbst nicht enthalten sondern auf diese nur verweisen. (In VB6 sind alle Objekte Referenzen, die Instanzen werden Intern automatisch organisiert.) |
| Kapselung | Anders als in Modulen sind da Public deklarierte Namen nicht einfach im gesamten Projekt sichtbar, sondern nur über des Objekts erreichbar. Namen können so besser abgegrenzt werden und Namensüberschneidungen verhindert werden. Public¦Friend bewirken das ein Name nach Außen sichtbar ist, sie bleiben aber an das Objekt gebunden. |
| Methoden (Method) | Sind die Prozeduren (Sub Function) die in einem Objekt dessen Eigenschaften bearbeiten. |
| Eigenschaften (Property) | Ist eine Schnittstelle für den Datenaustausch in und aus dem Objekt, die es auch ermöglicht zusätzliche Aktionen beim Schreiben und Lesen von Daten Auszuführen. |
| Ereignis (Event) | Objekte können Ereignisse auslösen, das bedeutet das ein im Objekt deklariertes Ereignis als Prozedur in einem anderen Codeteil ausgeführt wird als im Objekt selbst. zB beim drücken auf ein Knopf wird ein Ereignis ausgelöst das in einem Formular bearbeitet werden kann. |
| Überladung | Bedeutet das für eine Prozedur mehrere Varianten erlaubt sind, die zB. unterschiedliche Anzahl und Daten-Typen von Parametern erlauben. Das ermöglicht es unteranderem das eine Funktion für viele Daten-Typen gleichnamig verwendet werden kann. (Die Funktion Len() ist ein Beispiel, man kann Len() auf alle Datentypen anwenden, obwohl für jeden Daten-Type eine eigene Prozedur ausgeführt wird.) Leider unterstützt VB6 das Überladen von Prozeduren nicht. |
| Polymorphie | Dieser eigentlich unnötig komplizierte aber in OOP häufig benutze Begriff bedeuten soviel wie Vielgestaltigkeit, das heißt das ein Algorithmus nicht an eine bestimmten Daten-Typ gebunden ist. Mehrere Klassen können die selben Eigenschaften oder Methoden bereitstellen und beim Aufruf der Eigenschaft¦Methode muß nicht bekannt zu sein zu welcher Klasse das betreffende Objekt gehört. Dies erleichtert das Programmierer da es so möglich ist Algorithmen nur einmal zu entwickeln und sie dann vielfältig in anderen Objekten benutzen zu können. (Überladung von Prozeduren, oder der Variant und Object Daten-Typ sind auch eine Form der Polymorphie. Leider unterstützt auch hier VB6 Polymorphie nicht vollständig (nicht über Vererbung, nur über Schnittstelle), zB. gibt es in VB6 eine Reihe unterschiedlicher Listen-Formate, es gibt aber keine Möglichkeit sie untereinander austauschbar zu verwenden. Aber es werden dennoch einige polymorphe Eigenschaften unterstützt. |
| Vererbung | Bedeutet das eine Klasse Codes an andere Klassen vererben¦übertragen¦kopieren kann. so lassen sich Codes mit gleichen aufgaben in vielen Klassen verwenden ohne sie neu schreiben zu müssen. Vererbung kann auch mit der Polymorphie zusammenarbeitet und ermöglicht es so das nicht in jenem Klasse wiederholende Prozeduren immer wieder neu geschrieben werden müssen. Durch die Kapselung wäre sonst kein Austausch von Codes unter Klassen möglich, sie wären in den Klassen einsperren. Leider unterstützt VB6 Vererbung nicht, statteten wird eine Schnittstellen Kommunikation unterstützt welche aber weniger effizient ist. |
| Nicht-Linearität | Durch die Ereignis-Orientierte Programmierung ist ein Programm nicht mehr linear, in dem Sinne wie es Codes in einem Standard-Modul sind. Ein Beispiel sind Benutzeroberflächen, in einem Linearen Programm müsse eine Schleife und ein Select-Case prüfen ob eine Aktion ausgeführt wurde die eine Prozedur und Aktionen auslöst, zB. beim Klicken auf ein Knopf oder Menü. Durch Event fällt dies weg, die Aktion wird dann ausgeführt wenn sie eintritt. Die Struktur eines Programms läßt sich deshalb nicht mehr linear abbilden, die Ereignisse verändern die Daten in einem Objekt wenn sie eintreten und theoretisch könne sie das auch gleichzeitig. |
| Task, Multitasking | Prozeß oder Programm der in einer Multitasking Umgebung gleichzeitig mit anderen Tasks ausgeführt werden kann. Heutige Betriebsysteme verwenden alle Multithreading um mehrere Programme und Prozesse gleichzeitig laufen lassen zu können. |
| Thread, Multithreading | Ein Thread ist ein Programmteil (innerhalb eines Task) welcher von einem anderen unabhängig arbeiten kann. So ist es möglich das auch innerhalb eines Programms verschiedene Aufgaben gleichzeitig bearbeiten werden können. Besonders interessant in Multi-Prozessor Systemen, aber auch in Single-Prozessor Systemen kann es Beschleunigung bringen wenn unterschiedlich Hardware aufgaben gleichzeitig stattfinden können. Es kann Probleme geben wenn Threads gleichzeitig die selben Daten benutzen¦verändern deshalb müssen Thread voneinander abgegrenzt (das sich keine Daten überschneiden), oder synchronisiert (Treads nacheinander bearbeiten) werden. Da zusätzlich Management Aufgaben anfallen die den Code auch verlangsamen können muß sich der Entwickler überlegen für welche Codes Treads sinnvoll sind. (VB6 erlaubt leider kein Multithreading) |
Da in Objekten oft gleiche Aufgaben erfüllt und gleiche Daten bearbeitet werden müssen, ist es sinnvoll dies auch in alle Projekten gleich zu benennen. Auf diese Weise ist es viel leichter sich in Projekten zurecht zu finden, und da Objekte die Namen kapseln gibt es auch keine Probleme mit Namensüberschneidungen.
Das "_" Unterstrich-Zeichen kann zwar in Namen verwendet werden, könnte aber Konflikte mit Ereignisse auslösen, die den Unterstrich benutzen. (Siehe: Ereignis: Event)
Ansonsten gelten die gleichen Regeln wie auch bei der Benennung von Klassen Namen. (Siehe: Namensvergabe)
Hier eine Liste der gebräuchlichsten Namen in Klassen.
| Wort | Bedeutung |
| | |
| Methoden | |
| Add, AddItem | Fügt ein Element hinzu |
| Move, MoveItem | Verschiebt ein Element an eine andere Position |
| Remove, RemoveItem | Löscht ein Element |
| Clear | Löscht den gesamten Inhalt |
| | |
| Eigenschaften | |
| List | Der Inhalt der Liste |
| Item | Ein Element (aus einer Liste) |
| Index | Den Index auf eine Position in einer Liste |
| Count | Anzahl Elemente |
| Name | Name des Objekts¦Elemente |
| Caption | Titel, Sichtbarer Text des Objekts |
| Text | Text-Inhalt im Objekt |
| | |
| Ereignisse | |
| Initialize() | Tritt auf, wenn eine Instanz (Objekt) einer Klasse erstellt wird. |
| Terminate() | Tritt auf, wenn eine Instanz (Objekt) aus dem Speicher entfernt worden sind. (oder alle (Objekt-Verweise auf eine Instanz) |
| | |
| Load() | Tritt auf, wenn ein Objekt (Formular oder Steuerelement) geladen wird. |
| Unload(Cancel As Integer) | Tritt auf, unmittelbar bevor wenn ein Objekt (Formular oder Steuerelement) entfernt wird. |
| Activate() | Tritt auf, wenn ein Objekt (Formular oder Steuerelement) zum aktiven wird. |
| Deactivate() | Tritt auf, wenn ein Objekt (Formular oder Steuerelement) nicht mehr das aktive Fenster ist. |
Klassen-Module enthaten sozusagen ein Konstruktionsplan eines Objekts. Sie Enthalten alles was das Objekt braucht, also sowohl seine Dateien wie auch die Prozeduren (Methoden) um diese zu verwalten.
Von einer Klasse können beliebig viele Objekte erzeugt¦abgeleitet werden, Objekte sind sozusagen "Verkörperungen" einer Klasse.
Die Namen die Public sichtbar sind gehören zu der sogenannten Schnittstelle eines Objekts.
In VB6 ist es leider nicht möglich in einem Klassen- Modul mehrere Klassen unterzubringen. Ein Klassen- Modul gilt automatisch als eine Klasse.
| Name | Schlüsselworte | Beschreibung |
| Eigenschaften | Property (Get Let Set) | Sind die Daten die im Objekt gespeichert werden, welche über Eigenschaftsprozeduren ausgetauscht und bearbeitet werden können. |
| Methoden | Sub Function | Sind die Prozeduren die im Objekt verfügbar sind. |
| Ereignisse | Event RaiseEvent WithEvents | Sind Aktionen die vom Objekt ausgelöst werden können und in anderen Objekten außerhalb der Ereignisquelle eine Prozedur aufrufen. |
| Klassen-Modul | Standard-Modul |
| Von Klassen lassen sich unbegrenzt viele Objekte und damit auch deren Werte erzeugen. | In Modulen sind alle Werte nur einmal verfügbar. |
| Dadurch das Objekte instanziert werden müssen und auch wieder gelöscht werden können, existieren Prozeduren und Variablen nicht während der Ganzen Laufzeit. Ein Objekt kann auch Nothing oder Null enthalten. | Prozeduren und Variablen existieren in Modulen während der gesamten Laufzeit. |
| Public Namen ist in Objekt gekabbelt und können nur über dieses erreicht werden. | Public Namen sind im ganzen Projekt direkt sichtbar und können in allen Prozeduren verwendet werden. |
| In Klassen können Ereignisse ausgelöst werden, welche Prozeduren aufrufen. | In Modulen existieren Ereignisse nicht. |
| Klassen können bei der "Erzeugen" und "Zerstören" Initialisierungen und Terminationen ausführen. | Initialisierungen und Terminationen existiert in Standard-Modulen nicht. |
Einige Namen dürfen nicht verwendet werden da sie zu den zugrundeliegenden Schnittstellen "Unknown" und "Dispatch" gehören:
QueryInterface, AddRef, Release, GetTypeInfoCount, GetTypeInfo, GetIDsOfNames, Invoke
Public hat nicht die gleiche Wirkung wie Public in Modulen, Namen sind nicht im ganzen Projekt sichtbar, sondern durch die Kapselung nur über das Objekt erreichbar und nach Außen sichtbar.
Es ist leider nicht möglich Public sichtbare Namen in einer Klasse wie in einem Modul zu deklarieren. Global sichtbare Namen müssen außerhalb von Klassen in einem Modul deklariert werden.
Konstanzern können leider überhaupt nicht Public dekoriert werden. (Das liegt daran das VB6 nicht unterschiedet ob eine Klasse nur innerhalb eines Projekts sichtbar sein muß, oder über dies hinaus wie zB. in eine DLL OCX. In extern sichtbaren Namen die nur zur Laufzeit aufgelöst werden können, gibt es keine Konstanten da Werte immer abgeholt und in einer Variable übertragen werden müssen.)
| Schlüsselwort | Beschreibung |
| Public | Namen sind über das Objekt nach außen sichtbar für alle, auch außerhalb des Projekts. (In OCX DLL ActiveX usw. können Namen zugänglich sein.) |
| Friend | Namen sind über das Objekt nach außen sichtbar für alle Prozeduren in einem Projekt, nicht aber außerhalb des Projekts.). |
| Private | Namen sind nur innerhalb des Objekt unter den Prozeduren sichtbar (wie in Modulen auch.) |
In Gegensatz zu Modulen kommt noch das Schlüsselwort Friend hinzu, für Friend gelten zusätzliche Einschränkungen
Kann nur in Formular-Modulen und Klassen-Modulen verwendet werden.
Kann nur Prozedurnamen, nicht Variablen oder Typen verwendet werden.
Eine Friend- Prozedur kann nur zur Compilierungszeit (nicht zur Laufzeit) auflösbar sein. (Friend-Prozeduren sind dadurch schneller aufrufbar.)
Nicht sichtbar für den Controller einer Instanz des Objekts und dadurch außerhalb des Projekts nicht sichtbar und gehören deshalb nicht zur der Schnittstelle. (in eine DLL OCX Datei sind Friend-Prozeduren nach Außen nicht erreichbar.)
Sie sind deshalb auch nicht sichtbar in Objekten die als allgemeine "As Object" deklariert wurden, da diese polymorph und nur zur Laufzeit auflösbar sind. Um auf Friend deklarierte Namen zugreifen zu können müssen Objekte explizit mit Klassennamen deklariert werden um zur Compilierungszeit auflösbar zu sein.
Nützlich ist Friend auch in ActiveX Komponenten, weil so Prozeduren innerhalb der Komponenten sichtbar sein können aber nicht außerhalb, was sie besser kapseln kann als ein Public wenn sie nach Außen auch nicht erreichbar sein sollen.
Me gilt als Stellvertreter oder Verweis auf sich selbst, in das Objekt in dem sich das Me befindet. Es ist also sinnvoll immer dann wenn man eine interne Eigenschaft des Objekts ansprechen will dies nicht über den Namen zu tun sondern über das Schlüsselwort "Me". (zB. nicht "Form1.Unload" sondern "Me.Unload")
Es können auch in einer Klasse Public Variabeln deklariert werden, aber mit Propertys ( Eigenschaft) ist es möglich eine Schnittstelle für den Datenaustausch in und aus dem Objekt zu schaffen und so beim lesen und schrieben auf ein Property auch Codes auszuführen, (wie zB. eine Bereichsprüfung). Deshalb werden sie auch Eigenschaftsprozeduren genannt.
Sowohl für den Schreib- wie für den Lese-Vorgang wird separat in einer Eigenschaftsprozeduren Deklariert.
Wird die Schreib-Property (Let Set) weggelassen, gilt die Eigenschaft als Schreibgeschützt und kann außerhalb des Objektes nicht (direkt) geändert werden. So können anders als bei Variablen Werte nach Außen vor Veränderung geschützt werden.
(zB. wird die Anzahl in einer Liste nicht durch Count bestimmt sondern nur zurückgegeben, durch eingefügten und gelöschten von Elementen wird Count Intern geändert.)
Public deklarierte Variabeln werden von VB6 intern als Property behandelt. (Die Verarbeitung ist also auch nicht schneller.)
Der Unterschied zwischen Methoden (Prozeduren) und Property (Eigenschaftsprozeduren) ist manchmal garnicht so leicht da ja beide eine Prozedur ausführen. Am Ende zählt ob es sich eher um eine Funktion oder um Werte handelt, und dementsprechend sollte die Wahl zwischen den beiden Möglichkeiten getroffen werden.
| Ereignisprozedur | Auslöser | Beschreibung |
| Property Get | Var1 = Prob1 | Gibt den Wert einer Eigenschaft zurück. |
| | | |
| Property Let | Prob1 = Var1 | Legt den Wert einer Eigenschaft fest. |
| Property Set | Set Prob1 = Obj1 | Legt den Wert einer Objekteigenschaft fest (d.h. einer Eigenschaft, die eine Referenz auf ein Objekt enthält). |
'======== Class1 (Eine Klasse die Property enthält)
'-------- Deklaration
'-- Interne Propertys speichern
Private Type PropertysInternType
Prop1 As Long ' Variable Deklarieren
Prop2 As Class2 ' Objekt mit expliziter Klasse deklarieren (nur Objekte dieser Klasse sind übertragbar)
End Type
Private PropertysIntern As PropertysInternType
'-------- Code
'-- Variabeln-Property (Eigenschaftsprozeduren)
Public Property Get Prop1() As Long
'{... Code}
Prop1 = PropertysIntern.Prop1 ' der Wert wird zurückgegeben
End Property
Public Property Let Prop1(ByVal PropertyVal1 As Long)
'{... Code}
PropertysIntern.Prop1 = PropertyVal1 ' der Wert wird übernommen
End Property
'-- Variabeln-Property (Eigenschaftsprozeduren)
Public Property Get Prop2() As Class2
'{... Code}
Set Prop2 = PropertysIntern.Prop2 ' der Wert wird zurückgegeben
End Property
Public Property Set Prop2(ByVal PropertyVal1 As Class2)
'{... Code}
Set PropertysIntern.Prop2 = PropertyVal1 ' der Wert wird übernommen
End Property
'======== Externes Modul
Public Sub Main()
Dim ObjP As New Class1 ' Instanz erstellen zum Prüfen der Property in "Class1"
Dim Var1 As Long ' Temporäre Variablen
Dim Obj1 As New Class2
ObjP.Prop1 = Var1 ' Ausführung: "Property Let Prop1", "Var1" wird ins Objekt geschrieben
Var1 = ObjP.Prop1 ' Ausführung: "Property Get Prop1", der Wert wird zurückgegeben.
Set ObjP.Prop2 = Obj1 ' Ausführung: "Property Set Prop2", "Obj1" wird ins Objekt geschrieben
Set Obj1 = ObjP.Prop2 ' Ausführung: "Property Get Prop2", das Objekt wird zurückgegeben.
Debug.Print ObjP.Prop1 ' Ausführung: "Property Get Prop1", und nur während der Entwicklungszeit !
End Sub
Wird ein Variant verwendet kann es auch sein das alle drei Eigenschaften gleichzeitig verwendet werden müssen um alle Möglichkeiten zu behandeln.
'-------- Deklaration
Private Type PropertysInternType
Prop1 As Variant ' Variable Deklarieren
End Type
Private PropertysIntern As PropertysInternType
'-------- Code im Objekt
Public Property Get Prop1() As Variant
If IsObject(PropertysIntern.Prop1) Then
' Ist ein Objekt
Set Prop1 = PropertysIntern.Prop1
Else
' Ist kein Objekt
Prop1 = PropertysIntern.Prop1
End If
End Property
Public Property Set Prop1(ByVal Par1 As Variant)
' Ist ein Objekt
Set PropertysIntern.Prop1 = Par1
End Property
Public Property Let Prop1(ByVal Par1 As Variant)
' Ist kein Objekt
PropertysIntern.Prop1 = Par1
End Property
'-------- Code außerhalb vom Objekt
Set Obj2 = Obj1.Prop1 ' Objekt Aufruf Get
Var2 = Obj1.Prop1 ' Variable Aufruf Get
Set Obj1.Prop1 = Obj2 ' Objekt Aufruf Set
Obj1.Prop1 = Var2 ' Variable Aufruf Let
Die Lesende Eigenschaftsprozedur "Get" benötigt keinen Parameter, die Schreibenden "Let" "Set" mindestens einen welcher den Wert übernimmt der zugewiesen wurde.
Die Eigenschaftsprozeduren müssen deckungsgleich sein, das heißt die Namen müssen gleich lauten und die Parameterangaben ebenfalls.
Werden mehrere Parameter verwendet ist der letzte Parameter der Übergabewert, die vorangehenden die zusätzlichen Parameter.
Der Datentyp des letzten Arguments in einer "Property Set"-Deklaration muß entweder ein Objekt-Typ oder der Daten-Typ Variant sein.
'-- Pseudocode
' D ist die Übergabe Variable (Objekt-Typ oder Variant)
Prop1 = D ' Diese Anweisung löst...
Public Property Let Prop1(D) ' ... Diese Eigenschaftsprozedur aus
D = Prop1 ' Diese Anweisung löst...
Public Property Get Prop1() As {Daten-Typ von D} ' ... Diese Eigenschaftsprozedur aus
Set D = Prop1 ' Diese Anweisung löst...
Public Property Set Prop1() As {Daten-Typ von D} ' ... Diese Eigenschaftsprozedur aus
Prop1(A, B, C) = D ' Diese Anweisung löst...
Public Property Let Prop1(A, B, C, D) ' ... Diese Eigenschaftsprozedur aus
D = Prop1(A, B, C) ' Diese Anweisung löst...
Public Property Get Prop1(A, B, C) As {Daten-Typ von D} ' ... Diese Eigenschaftsprozedur aus
Für außerhalb des Projekts sichtbare Schnittstellen müssen diese über PropertyBag Organisiert werden, um einerseits die Namen sichtbar zu machen und anderseits die Daten zu initialisieren und zwischen zu speichern.
Ein gutes Beispiel dafür sind Benuzerdefinierte-Steuerelemente. Was man im Eigenschaftsfenster sehen und einstellen kann wird über das PropertyBag zur Verfügung gestellt.
Methoden sind Objekt-Prozeduren (Sub, Function) innerhalb einer Klasse, sie können genauso deklariert werden wie in einem Standard- Modul. (Siehe: Prozeduren)
Ein Beispiel für Ereignisse sind auch in den Formularen zu finden, die Ereignisse automatisch erzeugen wenn ein Formularelement erzeugt wird. Die "WithEvents" und "Set-New" Deklaration wird dabei automatisch im Hinderung erzeugt und die WithEvents-Objekte nach den Elemente-Namen benannt. Wird also ein Knopf erzeugt mit dem Namen "Command1" wird ein "Command1" WithEvents-Objekte aus der Klasse "CommandButton" erzeugt und instanziert. zB. "Command1_Click" ist dann ein Ereignis das beim klicken auf den Knopf ausgelöst wird, wobei "Click" eines der Ereignisse aus der CommandButton- Klasse ist.
Ein anderes Beispiel für ein Ereignis wäre eine Rückmeldung für eine Fortschrittsanzeige in einer Methode die viel Zeit in Anspruch nimmt bevor sie beendet ist. Das ist auch deshalb nützlich weil eben Objekte all ihre Prozeduren in sich enthalten sollten, also auch die Verwaltung einer Fortschritts-Berechnung. So kann das aufgerufene Objekt über ein Ereignis dem aufrufenden Objekt mitteilen, wo es sich in der Berechnung befindet und diese Information kann auswerten und zB. anzeigen wenn das aufrufende Objekt ein Formular ist.

Event Ist die interne Deklaration weil sie im Objekt die Ereignis-Namen deklariert welche das Objekt auslösen kann. Dieses Objekt ist dann eine Ereignisquelle.
'-------- Deklaration
Public Event Evt1() ' Ein Event wurde deklariert
Public Event Evt2(ByVal Par1 As Single, ByRef Cancel As Boolean) ' "Cancel" kann hier als Abbruchs-Variable verwendet werden.
Die über Event deklarierten Ereignisse können nun in der Klasse ausgelöst werden. Die funktioniert eigentlich wie bei einem Call nur diesmal über das Schlüsselwort RaiseEvent.
'-------- Code
RaiseEvent Evt1 ' das Deklarierte Ereignis wird ausgeführt
RaiseEvent Evt2(Par1, Cancel) ' hier werden Parameter übergeben, und über Cancel kann ein Rückgabewert verwendet werden um lange Prozesse abzubrechen.
Ist die externe Deklaration weil sie Ereignisse eines anderen Objekts im eigenen zugänglich macht und hier das Ereignis ausgeführt wird das von der Ereignisquelle ausgelöst wurde.
WithEvents deklariert Ereignisse aus einem Objekt um diese abfangen zu können. Bei der Deklaration ist folgendes zu beachten.
Kann in nicht in Standard-Modulen verwendet werden, nur in Klassen-Modulen (also auch in Formularen).
WithEvents muß explizit mit Klassenname deklariert werden, polymorph "As Object" "As Variant" geht nicht.
WithEvents-Variablen können keine Arrays sein.
Wird WithEvents für ein Objekt aus einer Klasse deklariert die keine Ereignisquelle ist, also keine Event Deklarationen enthält, tritt ein Fehler auf.
Die Ereignisse werden nur dann ausgelöst, wenn auch eine Instanz der WithEvents Objekt-Variable erzeugt wurde, wird diese Objektvariable auf Nothing gesetzt, werden auch de Ereignisse nicht mehr ausgelöst.
'-------- Deklaration
Private WithEvents EvtClass1 As Class1 ' Es wird deklariert das Ereignisse aus der Klasse "Class1" ausgelöst werden können. Dies ist aber noch kein instanziertes Objekt, sondern nur eine Deklaration, Ereignisse werden noch nicht ausgeführt
Ist eine WithEvents-Variable deklariert und Instanziert, werden ausgelöste Ereignisse an die Ereignisprozeduren geleitet.
Die Ereignisprozeduren werden wie folgt deklariert WithEventsVariabelName_EreignisName(DeklarierteParameter). Die DeklarierteParameter werden so angegeben wie in Events deklariert.
'-------- Code
Private Sub Form_Initialize() ' die Ereignis-Variable wird hier mein Initialisieren eines Formulars instanziert.
Set EvtClass1 = New Class1 ' hier wird aus dem deklarierten Ereignis-Objekt eine Instanz erzeugt, erst jetzt werden Ereignisse auch ausgeführt.
End Sub
Set EvtClass1 = Nothing ' Steht irgendwo im Code eine Löschung der Ereignis-Objekt Instanz, werden keine Ereignisse mehr ausgeführt.
Private Sub EvtClass1_Evt1()
'{...Code für das ausgelösten Ereignis}
End Sub
Private Sub EvtClass1_Evt2(ByVal Par1 As Single, ByRef Cancel As Boolean)
'{...Code für das ausgelösten Ereignis}
Cancel = True ' in diesem Beispiel ist es möglich zeitaufwendige Prozesse durch "Cancel" abzubrechen.
End Sub
Dieses Beispiel enthält 2 Klassen, eine als Auslöser und eine als Ausführer von Ereignissen.
'======== "Class1": Klasse der Ereignis-Quelle
'-------- Deklaration
'-- Ereignisse deklarieren
Public Event Evt1() ' Ein Event wurde deklariert
Public Event Evt2(ByVal Par1 As Single, ByRef Cancel As Boolean) ' Cancel kann hier als Abbruchs-Variable verwendet werden
'-------- Code
'-- Ist eine Test-Prozedur die Ereignisse auslöst
Public Sub TestEvt1(ByVal Par1 As Long)
Dim Cancel As Boolean
'{... Code mit Schleifen-Wiederholung und langer Laufzeit}
RaiseEvent Evt1 ' Ereignisse werden ausgelöst
RaiseEvent Evt2(Par1, Cancel)
If Cancel Then Exit Sub ' Bricht die Prozedur ab
'{... Code mit Schleifen-Wiederholung und langer Laufzeit}
End Sub
'======== "Class2": Klasse der Ereignis-Verarbeitung
'-------- Deklaration
Private WithEvents EvtClass1 As Class1 ' Es wird deklariert das in dieser Klasse Ereignisse aus einer anderen Klasse "Class1" ausgelöst werden können. Dies ist aber noch kein Instanziertes Objekt, sondern nur eine Deklaration, es werden noch keine Ereignisse ausgelöst.
'-------- Code
'-- Aktivieren der Ereignisausführung bei der Initialisierung
Private Sub Class2_Initialize()
'Dim EvtClass1 As New Class1 ' Diese Deklaration einer WithEvents-Variable ist nicht zugelassen.
Set EvtClass1 = New Class1 ' hier wird aus dem Deklarierten WithEvents-Objekt eine Instanz erzeugt. Erst jetzt werden Ereignisse ausgeführt.
End Sub
'-- Ereignisausführung
Private Sub EvtClass1_Evt1()
Debug.Print "EvtClass1_Evt1"
'{...Code }
End Sub
Private Sub EvtClass1_Evt2(ByVal Par1 As Single, ByRef Cancel As Boolean)
Debug.Print "EvtClass1_Evt2" ' Wert aus der Ereignisquelle können über die Parameter verwandet werden.
'{...Code }
Cancel = True ' in diesem Beispiel ist es möglich zeitaufwendige Prozesse über "Cancel" abzubrechen.
End Sub
Nun können von einer Klasse Objekte erzeugt werden.
Wichtig ist nun das unterscheiden werden muß wischen deklarierten und instanziert¦referenziert Objekt-Variabeln. Während ein Standard Daten-Typ bereitsteht in dem Moment wo durch die Dim Deklaration Speicher zugewiesen wurde, kann ein Objekt nach einer Dim Deklaration zwar den Speicher reservieren, dennoch aber noch auf Nichts -> Nothing verweisen.
Dabei werden 2 Arten der Deklaration unterschieden, die Instanz einer Klasse und die Referenz zu einem Objekt. Für die Benutzung spielt dies keine so große Rolle, aber für die Geschwindigkeit.
Die Instanz ist sie Verkörperung einer Klasse zu einem Objekt. Sie enthält die tatsächlichen Daten des Objekts.
Die Referenz hingegen ist ein Verweis auf ein bereits bestehendes Objekt, sie enthält selbst die Daten nicht, sondern verweist intern über ein Zeiger auf das Tatsächliche Instanzierte Objekt welches die Daten enthält. Deshalb sind Referenzen auch langsamer als Instanzen da die Daten auf die sie verweisen erst geholt werden müssen bevor sie verwendet werden können.
Dabei übernimmt VB6 vieles auch automatisch, was in der Praxis manchmal auch vermissend und sogar zu problematisch sein kann. VB6 erzeugt Instanzen auf die zugegriffen wird automatisch, und zerstört¦löscht diese auch automatisch wenn keine verweise mehr auf die Instanz existieren. Es ist also auch Aufgabe des Programmierers die Codes so zu schreiben das er den Überblick über die Existenz von Objekten behalten kann. Am Ende des Programms sollten alle Objekte auf Nothing gesetzt werden. Auch da beim beenden des Programms alle Objekte gelöscht sein sollten.
(Ein Beispiel ist hier das beenden eines Programms mit End. Da das Programm so abrupt unterbrochen wird, verbleiben Objekte also auch Formulare im Speicher).
| Code ......................... | Beschreibung |
| Dim ObjName As New ClassName | Deklariert die Objekt-Variabe und bereitet eine Instanz vor, erzeugt sie aber noch nicht und "Class_Initialize()" Ereignis wird noch nicht ausgelöst. Die Instanz wird erst dann erzeugt wenn das erste man auf da Objekt zugegriffen wird. |
| Dim ObjName As ClassName | Deklariert nur die Objekt-Variabe und bestimmt welcher Klasse sie angehört, Instanziert wird nichts. Die Deklaration sichert dabei am das Objekt-Variabe immer mit dem richtigen Klassen-Typ verwendet wird. |
| | |
| Set ObjName = New ClassName | Deklariert die Objekt-Variabe und bestimmt welcher Klasse sie angehört, und erzeugt eine Instanz, "Class_Initialize()" Ereignis wird ausgelöst. |
| Set ObjName = ObjName2 | Erzeugt ein Reverenz-Objekt und keine Instanz eines Objekts, also nur ein Verweis. Ändert sich Werte in der Instanz, ändern sich diese auch für alle Reverenz-Objekte die ja nur auf die Instanz verweisen. "Class_Initialize()" Ereignis in ObjName wird ausgelöst. |
| Set ObjName = Nothing | Das Objekt wird freigegeben. Gibt es keine weiteren Referenzen mehr wird die Instanz des Objekt gelöscht¦zerstört. "Class_Terminate()" Ereignis in ObjName wird ausgelöst. |
| | |
| ObjName1 = ObjName2 | Fehler: Das Kopieren des Inhalts eines Objekts auf ein anderes (ähnlich wie bei einem Type) ist so leider nicht möglich. |
'---- Varianten der Objekt-Erzeugung
'-- Dim-New Deklaration
Dim Obj1 As New Class1 ' hier wird die Variable "Obj1" von der Klasse "Class1" Deklariert, und eine Instanz vorbereiten aber nicht erzeugt
Obj1.var1 = 1 ' die Instanz wird jetzt beim ersten Zugriff auf das Objekt erzeugt, "Class_Initialize()" Ereignis wird ausgeführt
'-- Set-New Deklaration, (dies ist die bevorzugte Schreibweise, da mit "Dim" immer nur deklariert wird, und "Set" die Instanzierung vornimmt.)
Dim Obj1 As Class1 ' hier wird nur die Variable "Obj1" von der Klasse "Class1" deklariert, keine Instanz
Set Obj1 = New Class1 ' Objekt wird deklariert und die Instanz gleich erzeugt, "Class_Initialize()" Ereignis wird ausgeführt
Obj1.var1 = 1 ' alles steht bereit
'-- Set Deklaration (Objekt-Referenzen)
Dim Obj1 As Class1
Dim Obj2 As Class1
Set Obj1 = New Class1 ' Objekt wird deklariert und die Instanz gleich erzeugt, "Class_Initialize()" Ereignis wird ausgeführt
Set Obj2 = Obj1 ' Objekt-Referenz wird erzeugt, "Obj2" verweist auf "Obj1"
Obj1.var1 = 1 ' Änderungen sind für "Obj1" und "Obj2" sichtbar.
Debug.Print Obj2.var1
'-- Freigeben
Set Obj1 = Nothing
'-- Fehler
Dim Obj1 As Class1 ' hier wird nur die Variable "Obj1" von der Klasse "Class1" deklariert, keine Instanz
Obj1.var1 = 1 ' dies verursacht ein Fehler den es existiert noch keine Instanz
| Typ | Anwendung |
| Object | Universaltyp, Alle Objekte |
| Variant | Universaltyp, ist eigentlich kein Objekt aber kann auch Objekte aufnehmen |
| Form | Alle Formulare in Anwendungen (einschließlich untergeordneter MDI-Formulare und des MDI-Formulars) |
| Control | Alle Formular-Steuerelemente in Anwendungen |
| MDIForm | Ein MDI-Formular in der Anwendung (wenn eines enthalten ist) |
'-- Folgende Elemente können nicht mit New erstellen werden
Dim Obj1 As New Integer ' keine Standard Daten-Typen.
Dim Obj1 As New Control ' keine allgemeiner Objekttypen.
Dim Obj1 As New ListBox ' keine spezifische Steuerelementtypen.
Dim Obj1 As New lstNames ' keine spezifischer Steuerelemente.
Generische Objekt-Variablen (also mit As Object deklarierte Variablen) können Objekte unterschiedlichster Klassen enthalten. Ebenso können Variablen, die mit den integrierten Form- und Control-Typen von Visual-Basic deklariert wurden, Formulare und Steuerelemente unterschiedlicher Klassen enthalten.
Da ein Objekt unterschiedliche Klassen angehören können, enthalten sie auch unterschiedliche Daten und Funktionen. Um also korrekt auf ein spezielles Objekt reagieren zu können muß man dessen Klasse feststellen können.
' Prüf ob es such um das gleiche Objekt handelt
If Obj1 Is Obj2 Then
End If
' Prüft ob es sich um ein Objekt aus der Klasse Class1 handelt
If TypeOf Obj1 Is Class1 Then
End If
' Prüft über den String-Name ob es sich um ein Objekt aus der Klasse Class1 handelt
If TypeName(Obj1) = "Class1" Then
End If
|