导读:VB可以用Declare声明来调用标准DLL的外部函数,但是其局限性也很明显:利用Declare我们只能载入在设计时通过Lib和Alias字句指定的函数指针!而不能在运行时指定由我们自己动态载入的函数指针),不能用Declare语句来调用任意的函数指针。当我们想动态调用外部函数的时候,就必须考虑采用其他的辅助方法,来完成这个任务了。 在文章《VB真是想不到系列之三:VB指针葵花宝典之函数指针 》、《Matthew Curland的VB函数指针调用》、《利用动态创建自动化接口实现VB的函数指针调用》等文献中对此问题都进行了一定程度上的讨论,但是头绪都很繁琐,对我这样的菜鸟还有点深奥,在资料搜索过程中,找到通过在VB中调入汇编程序,比较简便的实现了这个功能,下面就是实现原理:
/ ? I$ _7 X4 |( ^ 1)使用LoadLibrary加载DLL;7 S6 B, i4 j+ j7 O
2)GetProcAddress获得函数指针;( \( }: ~. C; D1 J% E! R" C
以上两步得到了预加载函数的指针,但是VB中没有提供使用这个指针的方法。我们可以通过一段汇编语言,来完成函数指针的调用!
) `$ ?) H: B0 o9 e+ L+ V+ C 3)通过汇编语言,把函数的所有参数压入堆栈,然后用Call待用函数指针就可以了。7 r$ ^( O6 i+ P/ K% C3 @6 _
实现以上功能的主要程序:
2 Q. G% B5 F3 r! b* v6 a ′加载Dll
$ K9 }1 e; o- Z! v8 j LibAddr = LoadLibrary(ByVal "user32")8 x3 j' _$ Y; n
′获得函数指针
4 r/ |7 q9 I5 |' } ProcAddr = GetProcAddress(LibAddr, ByVal "MessageBoxA")
9 G q0 [6 l& w4 v5 m ′原型为MessageBox(hWnd, lpText, lpCaption, uType)
3 q- m1 n8 Z4 H/ S6 E0 b ′---以下为Assembly部分---
, `$ `3 e! H# o( t+ P push uType8 O& t% c. U! N
push lpCaption
# I0 s! j9 F3 p) v- p, z push lpText# m, p) I9 h1 j5 I7 p. _5 w
push hWnd: [2 y+ \9 ?& f! P
call ProcAddr* f' B: @, L: W9 W2 `/ v% ]
′--------------------
# Z6 |8 k5 h) g# V) _' \% E FreeLibrary LibAddr′释放空间
2 S5 H4 g; H4 d- F3 g2 M 嘿,够简单吧!下面是动态调用MessageBoxA的源代码,上面的步骤被封装到RunDll32函数中,可放到模块(CallAPIbyName.bas)中:* s9 r1 ^7 G* z+ Q' C
Dim s1() As Byte, s2() As Byte1 ^: T- k; y' ~$ f" ~
Dim ret As Long, t1 D, s( H9 S: c5 \, f
s1 = StrConv("Hello~World", vbFromUnicode)
# @9 h |) a5 c! c" ]. } s2 = StrConv("VBNote", vbFromUnicode)
: o" {: y% \' g* R1 R3 {9 X; B) L2 j& s1 ~% Y5 q0 V' G* b
ret = RunDll32("user32", "MessageBoxA", hwnd, VarPtr(s1(0)), VarPtr(s2(0)), 0&) |