With some ASM we can call functions by their pointers or
even call them in new threads so our app keeps responding.
It's actually the first time I've written the ASM code myself,
so please don't bash me for any crashes.
I used an upload at pscode for orientation, but I can't find it atm.

First we need a module. Let's name it modFncPtr.
Its functions are:
* GetFncAddress - like GetProcAddress, just more comfortable
* WaitForThread - wait for the end of a thread in a DoEvents loop
* CallPointerAsync - run a function in a new thread
* CallPointer - just run a function

VB Code:
  1. Option Explicit
  2.  
  3. Private Declare Function GetExitCodeThread Lib "kernel32" ( _
  4.             ByVal hThread As Long, _
  5.             lpExitCode As Long) As Long
  6.  
  7. Private Declare Function CreateThread Lib "kernel32" ( _
  8.             lpThreadAttributes As Long, _
  9.             ByVal dwStackSize As Long, _
  10.             ByVal lpStartAddress As Long, _
  11.             lpParameter As Any, _
  12.             ByVal dwCreationFlags As Long, _
  13.             lpThreadId As Long) As Long
  14.  
  15. Private Declare Function CallWindowProcA Lib "user32" ( _
  16.             ByVal adr As Long, _
  17.             ByVal p1 As Long, _
  18.             ByVal p2 As Long, _
  19.             ByVal p3 As Long, _
  20.             ByVal p4 As Long) As Long
  21.  
  22. Private Declare Function LoadLibraryA Lib "kernel32" ( _
  23.             ByVal szLib As String) As Long
  24.  
  25. Private Declare Function GetProcAddress Lib "kernel32" ( _
  26.             ByVal hModule As Long, _
  27.             ByVal szFnc As String) As Long
  28.  
  29. Private Declare Function GetModuleHandleA Lib "kernel32" ( _
  30.             ByVal szModule As String) As Long
  31.  
  32. Private Declare Sub RtlFillMemory Lib "kernel32" ( _
  33.             pDst As Any, _
  34.             ByVal dlen As Long, _
  35.             ByVal Fill As Byte)
  36.  
  37. Private Declare Sub RtlMoveMemory Lib "kernel32" ( _
  38.             pDst As Any, _
  39.             pSrc As Any, _
  40.             ByVal dlen As Long)
  41.  
  42. Private Const STILL_ACTIVE  As Long = 259&
  43. Private Const MAXCODE       As Long = &HEC00&
  44.  
  45. Public Type ASYNCCALL
  46.     hThread                 As Long
  47.     ret                     As Long
  48.     asm(MAXCODE - 1)        As Byte
  49. End Type
  50.  
  51. Private lngAsyncRet         As Long
  52.  
  53. ' like GetProcAddress, but with a more comfortable first parameter
  54. Public Function GetFncAddress(ByVal library As String, ByVal sFunction As String) As Long
  55.     Dim hModule As Long
  56.     Dim pFunc   As Long
  57.  
  58.     ' check if module already loaded
  59.     hModule = GetModuleHandleA(library)
  60.     If hModule = 0 Then
  61.         ' module not loaded, try to load it
  62.         hModule = LoadLibraryA(library)
  63.         If hModule = 0 Then
  64.             Err.Raise 999, , "library missing!"
  65.             Exit Function
  66.         End If
  67.     End If
  68.  
  69.     ' get entry point of function
  70.     pFunc = GetProcAddress(hModule, sFunction)
  71.     If pFunc = 0 Then
  72.         Err.Raise 998, , "not a exported function!"
  73.         Exit Function
  74.     End If
  75.  
  76.     GetFncAddress = pFunc
  77. End Function
  78.  
  79. ' wait for end of thread
  80. Public Sub WaitForThread(hThread As Long)
  81.     Dim dwExitCode  As Long
  82.  
  83.     Do
  84.         GetExitCodeThread hThread, dwExitCode
  85.         If dwExitCode <> STILL_ACTIVE Then Exit Do
  86.         DoEvents
  87.     Loop
  88. End Sub
  89.  
  90. ' run a function in a new thread
  91. Public Sub CallPointerAsync(ByVal fnc As Long, udtAsync As ASYNCCALL, ParamArray params())
  92.     Dim pASM            As Long
  93.     Dim TID             As Long
  94.     Dim hThread         As Long
  95.     Dim i               As Integer
  96.  
  97.     pASM = VarPtr(udtAsync.asm(0))
  98.  
  99.     ' fill code array with INT 3s (Debugger)
  100.     RtlFillMemory ByVal pASM, MAXCODE, &HCC
  101.  
  102.     AddByte pASM, &H58                  ' POP EAX
  103.     AddByte pASM, &H59                  ' POP ECX
  104.     AddByte pASM, &H50                  ' PUSH EAX
  105.  
  106.     For i = UBound(params) To 0 Step -1
  107.         AddPush pASM, CLng(params(i))   ' PUSH dword
  108.     Next
  109.  
  110.     AddCall pASM, fnc                   ' CALL rel. addr
  111.  
  112.     AddByte pASM, &HBA                  ' MOV EDX, |||||
  113.     AddLong pASM, VarPtr(udtAsync.ret)  '          dword
  114.  
  115.     AddByte pASM, &H89                  ' MOV ||||| ||| |||||, EAX
  116.     AddByte pASM, &H2                   '     dword ptr [EDX]
  117.  
  118.     AddByte pASM, &HC3                  ' RET
  119.  
  120.     hThread = CreateThread(ByVal 0&, 0, VarPtr(udtAsync.asm(0)), _
  121.                            ByVal 0&, 0, TID)
  122.  
  123.     udtAsync.hThread = hThread
  124. End Sub
  125.  
  126. ' run function by its pointer
  127. Public Function CallPointer(ByVal fnc As Long, ParamArray params()) As Long
  128.     Dim btASM(MAXCODE - 1)  As Byte
  129.     Dim pASM                As Long
  130.     Dim i                   As Integer
  131.  
  132.     pASM = VarPtr(btASM(0))
  133.  
  134.     ' fill code array with INT 3s (Debugger)
  135.     RtlFillMemory ByVal pASM, MAXCODE, &HCC
  136.  
  137.     ' remove CallWindowProc parameters from stack
  138.     AddByte pASM, &H58                  ' POP EAX
  139.     AddByte pASM, &H59                  ' POP ECX
  140.     AddByte pASM, &H59                  ' POP ECX
  141.     AddByte pASM, &H59                  ' POP ECX
  142.     AddByte pASM, &H59                  ' POP ECX
  143.     AddByte pASM, &H50                  ' PUSH EAX
  144.  
  145.     For i = UBound(params) To 0 Step -1
  146.         AddPush pASM, CLng(params(i))   ' PUSH dword
  147.     Next
  148.  
  149.     AddCall pASM, fnc                   ' CALL rel addr
  150.     AddByte pASM, &HC3                  ' RET
  151.  
  152.     CallPointer = CallWindowProcA(VarPtr(btASM(0)), _
  153.                                   0, 0, 0, 0)
  154. End Function
  155.  
  156. Private Sub AddPush(pASM As Long, lng As Long)
  157.     AddByte pASM, &H68
  158.     AddLong pASM, lng
  159. End Sub
  160.  
  161. Private Sub AddCall(pASM As Long, addr As Long)
  162.     AddByte pASM, &HE8
  163.     AddLong pASM, addr - pASM - 4
  164. End Sub
  165.  
  166. Private Sub AddLong(pASM As Long, lng As Long)
  167.     RtlMoveMemory ByVal pASM, lng, 4
  168.     pASM = pASM + 4
  169. End Sub
  170.  
  171. Private Sub AddByte(pASM As Long, bt As Byte)
  172.     RtlMoveMemory ByVal pASM, bt, 1
  173.     pASM = pASM + 1
  174. End Sub

Example on how to call user32.MessageBoxA in the same thread:
VB Code:
  1. Dim fnc         As Long
  2.     Dim ret         As Long
  3.  
  4.     Dim strTitle    As String
  5.     Dim strMsg      As String
  6.  
  7.     ' Get the entry point of user32.MessageBoxA
  8.     fnc = GetFncAddress("user32", "MessageBoxA")
  9.  
  10.     ' convert message to Ansi
  11.     strTitle = StrConv("Title", vbFromUnicode)
  12.     strMsg = StrConv("Messages", vbFromUnicode)
  13.  
  14.     ' call function pointer
  15.     ret = CallPointer(fnc, hWnd, StrPtr(strMsg), StrPtr(strTitle), vbInformation)
  16.  
  17.     MsgBox "Return: " & ret
That was easy, wasn't it?

One more for an asynchronous call:
VB Code:
  1. Dim MsgBoxThread As ASYNCCALL
  2.     Dim fnc         As Long
  3.  
  4.     Dim strTitle    As String
  5.     Dim strMsg      As String
  6.  
  7.     ' get entry point of user32.MessageBoxA
  8.     fnc = GetFncAddress("user32", "MessageBoxA")
  9.  
  10.     'convert message to Ansi
  11.     strTitle = StrConv("Title", vbFromUnicode)
  12.     strMsg = StrConv("Message", vbFromUnicode)
  13.  
  14.     ' call function in a new thread
  15.     ' the udt MsgBoxThread will contain the thread handle, the return value
  16.     ' and the asm code(!)
  17.     ' make sure MsgBoxThread doesn't run out of scope before
  18.     ' the thread is finished! Else your app will crash!
  19.     CallPointerAsync fnc, MsgBoxThread, hWnd, StrPtr(strMsg), StrPtr(strTitle), vbInformation
  20.  
  21.     With MsgBoxThread
  22.         ' wait for the thread to finish
  23.         WaitForThread .hThread
  24.         ' when the thread is finished .ret contains the return value
  25.         MsgBox "Return: " & .ret
  26.     End With