Results 1 to 40 of 63

Thread: [VB6] Call Functions By Pointer (Universall DLL Calls)

Threaded View

  1. #11

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] Call Functions By Pointer (Universall DLL Calls)

    Bonnie, if this is a Sub from a VB class you want to call, and you know the method's name, far easier:
    :: Copy pointer to uninitialized object and call the Object.SubName, remove pointer from that object, done

    Now, for a bit of fun, let's do a simple example of calling the object's IDispatch.Invoke method instead
    1) Create new class, leave default name & add these 2 methods
    Code:
    Public Sub TestMe()
        MsgBox "Test"
    End Sub
    Public Function TestMe2() As Long
        MsgBox "Test2" & vbNewLine & "vRtn should equal " & ObjPtr(Me)
        TestMe2 = ObjPtr(Me)
    End Function
    2) Within the form add a command button & this sample code. Ensure project also includes the attached cUniversalDLLCalls class
    Code:
    Private Type DISPPARAMS
        rgVarg As Long      ' pointer to array of variant agruments
        rgDispID As Long    ' pointer to array of DISPIDs of named argument
        cArgs As Long       ' number of arguments
        cNamedArgs As Long  ' number of named arguments
    End Type
    
    ' sample of getting the IDataObject GUID
    Private Sub Command1_Click()
        Const IUnknownRelease As Long = 8&
        Const IDispatchIDsOfNames As Long = 20&
        Const IDispatchInvoke As Long = 24&
        
        Dim IID_Dispatch As Long, lDispID As Long
        Dim aGUID(0 To 3) As Long, sName As String
        Dim DP As DISPPARAMS, vRtn As Variant
        Dim c As New cUniversalDLLCalls, tc As Class1
        
        Set tc = New Class1
        
        sName = "{00020400-0000-0000-C000-000000000046}" ' GUID for IDispatch
        c.CallFunction_DLL "ole32.dll", "IIDFromString", STR_NONE, CR_LONG, CC_STDCALL, StrPtr(sName), VarPtr(aGUID(0))
        ' ensure object implements IDispatch...
        c.CallFunction_COM ObjPtr(tc), 0&, CR_LONG, CC_STDCALL, VarPtr(aGUID(0)), VarPtr(IID_Dispatch)
        If IID_Dispatch <> 0& Then
            Erase aGUID()
            sName = "TestMe2" ' << change to another known method in the class
            Call c.CallFunction_COM(IID_Dispatch, IDispatchIDsOfNames, CR_LONG, CC_STDCALL, VarPtr(aGUID(0)), VarPtr(sName), 1&, 0&, VarPtr(lDispID))
            If lDispID <> 0 Then
                Call c.CallFunction_COM(IID_Dispatch, IDispatchInvoke, CR_LONG, CC_STDCALL, lDispID, VarPtr(aGUID(0)), 0&, 1&, VarPtr(DP), VarPtr(vRtn), 0&, 0&)
                Debug.Print "return value if any: "; vRtn
            Else
                Debug.Print "method ["; sName; "] not found"
            End If
            ' Release the interface at some point. QueryInterface calls AddRef internally
            c.CallFunction_COM IID_Dispatch, IUnknownRelease, CR_LONG, CC_STDCALL
        End If
    End Sub
    change sName = "TestMe2" to sName = "TestMe" to test the other sub. Note: that if parameters exist, then this gets more difficult and the DISPPARAMS structure needs to be filled out completely

    Edited: If wanting to pursue this further, here's a bit of help with the DISPPARAMS structure

    1) declare a variable vArgs() As Variant, size it to the number of parameters the method expects
    2) populate it in reverse order and ensure the correct vartype of each param, example:
    method's params: (Index As Integer, NewValue As Long)
    NewValue would be: vArgs(0) = 15&, CLng(15), just ensure Long vartype
    Index would be: vArgs(1) = 1%, CInt(1), just ensure Integer vartype
    3) the structure members: DP.cArgs = nrArgs: DP.rgVarg = VarPtr(vArgs(0))
    4) The 3rd from last parameter in that IDispatchInvoke sample call above is 1&. That is the constant for DISPATCH_METHOD, aka, vbMethod

    So how do we NOT pass an optional parameter to a VB class? Per docs, we must pass Variant of type Error with a specific error code in place of the optional parameter. How that parameter is coded determines whether VB sees it as passed or not passed. The following shows how to NOT provide the final Optional parameter of a method. Remember last parameter is 1st in the array:
    Code:
    Const DISP_E_PARAMNOTFOUND As Long = &H80020004
    
    vArgs(0) = DISP_E_PARAMNOTFOUND
    ' tweak to force variant type of Error. Can use CopyMemory API if desired, but...
    c.CallFunction_DLL "kernel32.dll", "RtlMoveMemory", STR_NONE, CR_None, CC_STDCALL, _
                                VarPtr(vArgs(0)), VarPtr(vbError), 2&
    
    ' Note: Proper way would be to have VB give us a Variant of Error vartype, i.e., 
    ' vArgs(0)= CVErr(DISP_E_PARAMNOTFOUND) but that errors
    Ok, that was fun. If anyone is asking what's difference between a parameter and a named parameter? See this MSDN link. If you wish to use named parameters/arguments with IDispatch, you have to get the DISPID of each named argument when you made the call to DispatchIDsOfNames, passing a array of names & a return array for the DISPIDs. These are then populated separately in the DISPPARAMS members. Here is a bit more info. Bottom line, more work but doable.

    Last but not least, haven't tried messing with methods that take ParamArrays, I'll let someone else play with that if they wish
    Last edited by LaVolpe; Dec 1st, 2014 at 06:43 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width