VB 5/6-Tipp 0582: Callbacks in Klassenmodule und Formulare
von Stefan Maag
Beschreibung
Einige kennen das Problem bereits: Man möchte Controls subclassen und muß deshalb Windows als Callback eine Procedur in einem Modul angeben, da nur dort der AddressOf-Operator funktioniert. Wie bringt man nun aber den Aufruf weiter an eine Form/ein Klassenmodul, ohne daß man dessen Instanz und Namen kennt? Das geht z.B. über eine Interfaceklasse!
Schwierigkeitsgrad: | Verwendete API-Aufrufe: keine | Download: |
'Dieser Quellcode stammt von http://www.activevb.de 'und kann frei verwendet werden. Für eventuelle Schäden 'wird nicht gehaftet. 'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. 'Ansonsten viel Spaß und Erfolg mit diesem Source! '------------- Anfang Projektdatei Projekt1.vbp ------------- '--------- Anfang Formular "Form1" alias Form1.frm --------- ' Steuerelement: Schaltfläche "Command4" ' Steuerelement: Schaltfläche "Command3" ' Steuerelement: Schaltfläche "Command2" ' Steuerelement: Schaltfläche "Command1" Option Explicit ' Hier werden die Funktionen der Interfaceklasse implementiert Implements cifInterface Private Sub Form_Load() ' um den Aufruf aus dem Modul wieder zu bekommen, ' muß unser Globales Objekt mit dem Verweis auf ' das Interface unserer Form gefüttert werden Set MyInterface = Me End Sub ' hier die 4 Buttons, um unsere Funktionen zu testen Private Sub Command1_Click() Test_IFC_Function1 End Sub Private Sub Command2_Click() Test_IFC_Function2 End Sub Private Sub Command3_Click() Test_IFC_Sub1 End Sub Private Sub Command4_Click() Test_IFC_Sub2 End Sub ' Hier folgen nun die Implementierungen unserer ' Schnittstellen-Funktionen aus cifInterface ' diese müssen unbedingt private sein! Private Sub cifInterface_IFCSub1() MsgBox "Callback über Interface Sub 1" End Sub Private Sub cifInterface_IFCSub2() MsgBox "Callback über Interface Sub 2" End Sub Private Function cifInterface_IFCFunction1() As Long MsgBox "Callback über Interface Funktion 1" End Function Private Function cifInterface_IFCFunction2() As Long MsgBox "Callback über Interface Funktion 2" End Function '---------- Ende Formular "Form1" alias Form1.frm ---------- '--------- Anfang Modul "Module1" alias Module1.bas --------- Option Explicit ' DEMO zu "Callback" in Klassenmodule mittels Interface-Klassen ' so lassen sich z.B. auch gut Aufrufe bei PlugIns Standardisieren ' ' Autor: Stefan Maag ' für activevb.de ' Datum: 03.02.2003 ' Hier wird ein Objekt als Globales Interface definiert ' Diese Routinen werden dann aus der Form aufgerufen ' und der Aufruf wird über die InterfaceKlasse ' cifInterface wieder an die Form zurückgeleitet Public MyInterface As CifInterface Public Sub Test_IFC_Function1() Dim ret As Long ret = MyInterface.IFCFunction1 End Sub Public Sub Test_IFC_Function2() Dim ret As Long ret = MyInterface.IFCFunction2 End Sub Public Sub Test_IFC_Sub1() MyInterface.IFCSub1 End Sub Public Sub Test_IFC_Sub2() MyInterface.IFCSub2 End Sub '---------- Ende Modul "Module1" alias Module1.bas ---------- '------ Anfang Klasse "CifInterface" alias Class1.cls ------ Option Explicit ' Diese Klasse stellt nur Schnittstellenfunktionen zur ' Verfügung (Interface) ' Jede Klasse oder Formular, das diese Funktionen nutzen ' will, muß diese Interface-Klasse implemtieren ' Implements cifInterface ' ACHTUNG: Diese Funktionen dürfen keinen Code enthalten, ' nur die Definition der Functionsköpfe ' in ActiveX-DLL's muss die Eigenschaft einer ' Interface-Klasse auf "Public, nicht instanzierbar" ' eingestellt gestellt werden ' zum Test Inteface Funkiton 1 Public Function IFCFunction1() As Long End Function ' zum Test Inteface Funkiton 2 Public Function IFCFunction2() As Long End Function ' zum Test Inteface Sub 1 Public Sub IFCSub1() End Sub ' zum Test Inteface Sub 1 Public Sub IFCSub2() End Sub '------- Ende Klasse "CifInterface" alias Class1.cls ------- '-------------- Ende Projektdatei Projekt1.vbp --------------
Tipp-Kompatibilität:
Windows/VB-Version | Win32s | Win95 | Win98 | WinME | WinNT4 | Win2000 | WinXP |
VB4 | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
VB5 | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
VB6 | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
Ihre Meinung
Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.
Archivierte Nutzerkommentare
Klicken Sie diesen Text an, wenn Sie die 2 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.
Kommentar von Götz Reinecke am 20.12.2004 um 12:02
> ... Zwar ist RaiseEvent nicht ganz so flexibel,
> aber es reicht meistens aus und ist einfacher
> zu benutzen.
Es geht hier aber um den Unmstand, daß die Instanz des Empfängers zur Laufzeit unbekannt ist. So etwas läßt sich über RaiseEvent nicht umsetzen.
Beispiel:
Es liegen unterschiedliche Child-Klassen vor deren Objekte zur Laufzeit wiederum unterschiedliche Parents zugewiesen werden können/sollen.
RaiseEvent/WithEvent versagt hier, dies geht nur über ein Interface, daß beiden (Child und Parent) bekannt ist und über die das Child im Parent Ereignisse auslösen kann:
'Interface [INotify]:
Public Sub OnChanged(ByRef SenderID As Long)
End Sub
'Child1 [clsChild1]:
Private m_Parent As INotify
Public Property Set Parent(ByRef NewValue As INotify)
Set m_Parent = NewValue
End Property
Private Sub DoSomething()
'...
m_Parent.OnChanged(MyID)
End Property
'Child2 [clsChild2]:
Private m_Parent As INotify
Public Property Set Parent(ByRef NewValue As INotify)
Set m_Parent = NewValue
End Property
Private Sub DoSomething()
'...
m_Parent.OnChanged(MyID)
End Property
'Parent1 [clsParent1]:
Implements INotify
Private Sub INotify_OnChanged(SenderID As Long)
Call MsgBox("Nachricht von: " & SenderID)
End Sub
'Parent2 [clsParent2]:
Implements INotify
Private Sub INotify_OnChanged(SenderID As Long)
Call MsgBox("Nachricht von: " & SenderID)
End Sub
Childs & Parents sind jeweils andere Typen, können aber über INotify willkürlich getauscht werden. (Polymorphie)
schöne Grüße
Götz
Kommentar von Konrad Rudolph am 15.03.2003 um 11:19
Hmmm.... bliebe nur noch zu erwähnen, daß ähnliches auch sehr viel einfacher über RaiseEvent zu erreichen ist.
Zwar ist RaiseEvent nicht ganz so flexibel, aber es reicht meistens aus und ist einfacher zu benutzen.