Die Community zu .NET und Classic VB.
Menü

VB 5/6-Tipp 0719: Die Adresse einer Klassenmethode ermitteln und die dazugehörige Funktion/Prozedur aufrufen

 von 

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:

Schwierigkeitsgrad 2

Verwendete API-Aufrufe:

CallWindowProcA, RtlMoveMemory

Download:

Download des Beispielprojektes [3,46 KB]

'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-VersionWin32sWin95Win98WinMEWinNT4Win2000WinXP
VB4
VB5
VB6

Hat dieser Tipp auf Ihrem Betriebsystem und mit Ihrer VB-Version funktioniert?

Ja, funktioniert!

Nein, funktioniert nicht bei mir!

VB-Version:

Windows-Version:

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.