这是一篇旧文档
动态载入类,可设置为任何委托原型
Imports System.Runtime.InteropServices
Public Class ClsoAPI
' 载入动态链接库
Private Declare Function LoadLibrary Lib "kernel32.dll" Alias "LoadLibraryA" (ByVal path As String) As IntPtr
' 获取函数指针地址
Private Declare Function GetProcAddress Lib "kernel32.dll" (ByVal libPtr As IntPtr, ByVal funcName As String) As IntPtr
' 释放动态链接库
Private Declare Function FreeLibrary Lib "kernel32.dll" (ByVal libPtr As IntPtr) As Boolean
Dim hLib As IntPtr '存储链接库指针
Sub New(ByVal dllpath As String)
hLib = LoadLibrary(dllpath)
If hLib = 0 Then Throw New Exception("载入库错误!")
End Sub
Protected Overrides Sub Finalize()
FreeLibrary(hLib)
MyBase.Finalize()
End Sub
Function GetProc(ByVal ApiName As String, ByVal DelegateT As Type) As [Delegate]
Dim api = GetProcAddress(hLib, ApiName)
If api = 0 Then Throw New Exception("载入函数错误!")
Return Marshal.GetDelegateForFunctionPointer(api, DelegateT) '将非托管函数指针转换为委托
End Function
End Class
上面的类型封装了动态载入API的过程,在构建这个类型时,我们需要先传递动态链接库的路径,然后调用GetProc来获取API的委托包装。
GetProc的两个参数分别为API函数在库中的名称和委托函数原型的类型信息,类型信息可以用Vb.NET的GetType关键字获得,具体的示例代码如下。
建立一个窗体,拖放两个按钮,添加下面的代码:
Public Class frmMain
' 弹出对话框的委托原型
Delegate Function MessageBox(ByVal hwnd As Int32, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Int32) As Int32
' 关于对话框的委托原型
Delegate Function ShellAbout(ByVal hwnd As Int32, ByVal szApp As String, ByVal szOtherStuff As String, ByVal hIcon As Int32) As Int32
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim c As New ClsoAPI("user32.dll")
Dim m As MessageBox = c.GetProc("MessageBoxA", GetType(MessageBox))
Dim i = m.Invoke(Me.Handle, "文本", "标题", 1)
MsgBox(i)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim c As New ClsoAPI("shell32")
Dim sa As ShellAbout = c.GetProc("ShellAboutA", GetType(ShellAbout))
sa.Invoke(Me.Handle, "CLSO API", "版权所有,翻版不究,盗版可耻!", Me.Icon.Handle)
End Sub
End Class
可以看出来,在动态调用API时,首先我们必须要知道我们调用的API的原型,然后在代码中声明这个原型的委托,才能动态调用这个API。
上面的示例我们分别调用了一个弹出对话框和微软的关于对话框,其他的API也是相似的调用方法。