VB 5/6-Tipp 0719: Die Adresse einer Klassenmethode ermitteln und die dazugehörige Funktion/Prozedur aufrufen
von Philipp Stephani
Beschreibung
Mit dem AddressOf-Operator von Visual Basic lässt sich zwar die Adresse einer Prozedur in einem Standardmodul auslesen, nicht jedoch die einer Klassenmethode. Mit Hilfe der Bibliothek "TlbInf32.dll", die mit VB mitgeliefert wird, ist auch dies möglich. Dazu wird die entsprechende Adresse einfach aus der VTable des Objektes gelesen. Mit Hilfe der Adresse kann die Methode dann aufgerufen werden (mit CallWindowProc oder Assembler-Befehlen). Allerdings muss beachtet werden, dass VB Prozeduren und Funktionen in Klassen völlig anders handhabt als solche in Modulen. Als erstes, verborgenes Argument muss immer der Objektzeiger der gewünschten Objektinstanz übergeben werden. Funktionen platzieren ihren Rückgabewert in einem ebenfalls verborgenden ByRef-Argument, das als letztes erscheinen muss.
Schwierigkeitsgrad: | Verwendete API-Aufrufe: | 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 prjProzedurAdresse.vbp -------- ' Es muss ein Verweis auf 'TypeLib Information' gesetzt werden. '--- Anfang Formular "frmProzedurAdresse" alias frmProzedurAdresse.frm --- ' Steuerelement: Rahmensteuerelement "fraFormularObjekt" ' Steuerelement: Beschriftungsfeld "lblFormularAdresse" (Index von 0 bis 3) auf fraFormularObjekt ' Steuerelement: Rahmensteuerelement "fraFunktion" ' Steuerelement: Schaltfläche "cmdFunktionAufrufen" auf fraFunktion ' Steuerelement: Beschriftungsfeld "lblFunktionAdresse" (Index von 0 bis 3) auf fraFunktion ' Steuerelement: Rahmensteuerelement "fraProzedur" ' Steuerelement: Schaltfläche "cmdProzedurAufrufen" auf fraProzedur ' Steuerelement: Beschriftungsfeld "lblProzedurAdresse" (Index von 0 bis 3) auf fraProzedur ' Steuerelement: Schaltfläche "cmdAdressenErmitteln" Option Explicit Private Declare Sub RtlMoveMemory Lib "kernel32.dll" ( _ ByRef Destination As Long, _ ByVal Source As Long, _ ByVal Length As Long) Private Declare Function CallWindowProcA Lib "user32.dll" ( _ ByVal lpPrevWndFunc As Long, _ ByVal hWnd As Long, _ ByVal Msg As Long, _ ByVal wParam As Long, _ ByRef lParam As Long) As Long Private mObjektAdresse As Long Private mProzedurAdresse As Long Private mFunktionAdresse As Long Public Sub Beispiel1(ByVal Eins As Long, ByVal Zwei As Long, ByRef Drei As Long) ' Eine Beispielprozedur, die öffentlich sein muss, da sonst kein ' VTable-Eintrag ' dafür erstellt wird. MsgBox "Beispiel1 wurde aufgerufen.", vbInformation Drei = Eins + Zwei End Sub Public Function Beispiel2(ByVal Eins As Long, ByVal Zwei As Long) As Long ' Eine Beispielfunktion, die öffentlich sein muss, da sonst kein ' VTable-Eintrag ' dafür erstellt wird. MsgBox "Beispiel2 wurde aufgerufen.", vbInformation Beispiel2 = Eins + Zwei End Function Private Sub cmdAdressenErmitteln_Click() Dim Schnittstelle As InterfaceInfo Dim Mitglied As MemberInfo Dim VTableAdresse As Long With Me.lblFormularAdresse mObjektAdresse = ObjPtr(Me) ' mObjektAdresse zeigt jetzt auf die Stelle im Arbeitsspeicher, an ' der die Instanzdaten gespeichert sind .Item(1).Caption = CStr(mObjektAdresse) RtlMoveMemory VTableAdresse, mObjektAdresse, 4 ' die ersten 4 Bytes der Instanzdaten beinhalten die Adresse der ' VTable .Item(3).Caption = CStr(VTableAdresse) End With Set Schnittstelle = InterfaceInfoFromObject(Me).VTableInterface For Each Mitglied In Schnittstelle.Members Select Case Mitglied.Name Case "Beispiel1" With Me.lblProzedurAdresse .Item(1).Caption = CStr(Mitglied.VTableOffset) RtlMoveMemory mProzedurAdresse, VTableAdresse + _ Mitglied.VTableOffset, 4 ' An dem Mitgliederoffset innherhabl der VTable befindet ' sich die Adresse der Prozedur .Item(3).Caption = CStr(mProzedurAdresse) End With Case "Beispiel2" With Me.lblFunktionAdresse .Item(1).Caption = CStr(Mitglied.VTableOffset) RtlMoveMemory mFunktionAdresse, VTableAdresse + _ Mitglied.VTableOffset, 4 ' An dem Mitgliederoffset innherhabl der VTable befindet ' sich die Adresse der Funktion .Item(3).Caption = CStr(mFunktionAdresse) End With End Select Next Mitglied Me.cmdProzedurAufrufen.Enabled = True Me.cmdFunktionAufrufen.Enabled = True End Sub Private Sub cmdFunktionAufrufen_Click() Dim Eins As Long Dim Zwei As Long Dim Drei As Long Eins = 5 Zwei = 10 CallWindowProcA mFunktionAdresse, mObjektAdresse, Eins, Zwei, Drei ' CallWindowProc ruft die Funktion auf und übergibt ihr vier Argumente. ' Das erste Argument muss die Adresse der aktuellen Instanz beinhalten. ' Das letzte Argument ist ein Zeiger (bzw. Referenz) auf den Rückgabewert ' der Funktion. Diese beiden Argument wird von VB verborgen; deswegen ' wird die Beispielprozedur auch nur mit zwei Parametern deklariert. MsgBox "Ergebnis: " & CStr(Drei), vbInformation End Sub Private Sub cmdProzedurAufrufen_Click() Dim Eins As Long Dim Zwei As Long Dim Drei As Long Eins = 5 Zwei = 10 CallWindowProcA mProzedurAdresse, mObjektAdresse, Eins, Zwei, Drei ' CallWindowProc ruft die Prozedur auf und übergibt ihr vier Argumente. ' Das erste Argument muss die Adresse der aktuellen Instanz beinhalten. ' Dieses Argument wird von VB verborgen; deswegen wird die ' Beispielprozedur ' auch nur mit drei Parametern deklariert. MsgBox "Ergebnis: " & CStr(Drei), vbInformation End Sub '--- Ende Formular "frmProzedurAdresse" alias frmProzedurAdresse.frm --- '--------- Ende Projektdatei prjProzedurAdresse.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.