在动态链接技术中,模块和程序是分离的,模块独立于程序而存在于另一个分离的dll 文件中,这个dll 文件是动态链接到程序中的。文件是动态链接到程序中的。
那如何在vb 中编写一个DLL 程序呢?程序呢?
首先,新建一个工程,然后先中“Ac veX Dll ”工程。”工程。  然后开始编辑,往程序中添加你需要的部件和控件。然后开始编辑,往程序中添加你需要的部件和控件。
编辑完成后,保存工程,工程一般是以“.vbp ”文件保存,定义的类以“.cls ”和“.vbw ”文件保存,窗体以“.frm ”文件保存,添加的模块一“.bas ”文件保存……。
接着选择“文件”菜单,弹出下拉框,选中“生成.dll ”选项,它就会在上面弹出一个进度条“正在生成.dll 文件”。生成以后是一个有好象齿轮状的图标。。生成以后是一个有好象齿轮状的图标。
当你需要在其他的程序中调用这个dll 的时候,需要在系统中注册一下,具体的过程是
开始->运行->打开”C:”C:\WINDOWS\system32\
\WINDOWS\system32\\WINDOWS\””,然后到你要注册的控件的路径,添加在 的后面。的后面。
如果你要引用,就开一个“标准EXE ”工程,然后在“工程”选项中,单击“引用”,到你刚才的“.dll ”的文件名,在前面的复选框中打勾,就可以引用你刚才在那里面写的方法等。方法等。
Public Func on DllMain(
hinstDLL As Long,        // long 类型包含dll 的instance handle 句柄. 也是dll 的模块句柄的模块句柄  fdwReason As Long,      // 常数标识,入口点为何被调用常数标识,入口点为何被调用
lpwReserved As Long    //long 类型提供关于类型提供关于  DLL_PROCESS_ATTACH(DETACH)的信息的信息  ) As Boolean
fdwReason 通常的取值通常的取值
DLL_PROCESS_ATTACH (1)
进程装载了dll ,每进程初始化要执行。A process is loading the DLL. Any per-process
ini aliza on should be performed.
DLL_THREAD_ATTACH (2)
进程交换(注入)一个新的线程,每线程初始化要执行。The process is spawning a new
thread. Any per-thread ini aliza on should be performed.
DLL_THREAD_DETACH (3)
一个线程结束。每线程清除要执行。A thread is exi ng. Any per-thread cleanup should be
performed.
DLL_PROCESS_DETACH (0)
一个进程断开dll 链接,或者进程结束,每进程清除要执行。A process is detaching the DLL,
or the process is exi ng. Any per-process cleanup should be performed.
lpvReserved
一个long 类型提供更多关于类型提供更多关于
DLL_PROCESS_ATTACH 和 DLL_PROCESS_DETACH 的信 息. (如果fdwReason 是
DLL_THREAD_ATTACH or DLL_THREAD_DETACH ,则该参数无用)
如果fdwReason 是 DLL_PROCESS_ATTACH, lpvReserved 值无意义对于用函数
LoadLibrary and GetProcAddress 装载dll, 如果如果  fdwReason 是 DLL_PROCESS_DETACH,
lpvReserved 值无意义,如果返回值是从值无意义,如果返回值是从  Win32 FreeLibrary func on, lpvReserved 值也无
意义,如果进程结束调用入口点.
函数的返回值只有在fdwReason 是 DLL_PROCESS_ATTACH 才有意义,如果初始化成
功,函数返回true,否则返回false.因为这个函数是window 调用的入口点.传入这个函数的
参数值是由windows 决定.当一个线程被用win32 TerminateThread 函数和函数和  Win32  TerminateProcess 函数结束,没有调用入口点.
要开发一个windows dll ,我们创建一个简单的数学函数库,下面代码存在一个.bas 模块中名字:MathLib.bas
Op on Explicit
Public Const DLL_PROCESS_DETACH = 0
Public Const DLL_PROCESS_ATTACH = 1
Public Const DLL_THREAD_ATTACH = 2
Public Const DLL_THREAD_DETACH = 3
Public Func on DllMain(hInst As Long, fdwReason As Long,
lpvReserved As Long) As Boolean
Select Case fdwReason
Case DLL_PROCESS_DETACH
' No per-process cleanup needed
Case DLL_PROCESS_ATTACH
DllMain = True
Case DLL_THREAD_ATTACH
' No per-thread ini aliza on needed
Case DLL_THREAD_DETACH
' No per-thread cleanup needed
End Select
End Func on
开头包含一个DllMain过程,没有每进程或者每线程初始化需要执行。如果fdwReason 参数是DLL_PROCESS_ATTACH被调用,DllMain简单的返回True。另外,注意dll的函数中的输入参数和返回值用win32 api类型,不要用variant。
我们同样需要一个测试程序(test)验证我们的windows dll是否运行正常,所以创建个标准exe工程,由一个窗口和一个模块组成,模块代码就是declare声明。
声明。
Public Declare Func on Incement Lib "MathLib.dll" (var As Integer) As Integer
Public Declare Func on Square Lib "MathLib.dll" (var As Long) As Long
如果不在系统路径,最好加上dll全路径。
全路径。
那么dll文件时怎么生成的呢?当我们选择文件->编译XXX.dll菜单选项来编译Ac veX dll,vb把我们的代码无缝结合成Ac veX dll,但是当我们检查vb的安装目录,其实这个过程并不是无缝的。在vb安装目录除,还有C2.exe和,一个是编译器,一个是链接
器,这里就说明本身不能生成dll文件,而dll是由这2个程序一起运行生成的。
个程序一起运行生成的。  VB编译文件实际上采取了两次编译的方法,首先是调用C2.exe产生*.OBJ文件,然后调用Link.EXE连接。如果在LINK的时候添加EXPORT选项,实际上是可以输出函数的。但是,在VB的工程选项中将这些屏蔽了。我们可以通过改名C2.exe和来中断编译器和链
是如何编译的。
接器的执行过程来发现vb是如何编译的。
编译器,其代码如下:
下面的代码是个新版本的C2.exe调用真正的C2.exe编译器,其代码如下:
Public Sub Main()
On Error Resume Next
Dim strCmd As String, strPath As String
Dim oFS As New Scrip ng.FileSystemObject
Dim ts As TextStream
strCmd = Command
strPath = App.Path
Set ts = oFS.CreateTextFile(strPath & "\")
ts.WriteLine "Beginning execu on at " & Date & " " & Time()
ts.WriteBlankLines 1
ts.WriteLine "Command line parameters to c2 call:"
ts.WriteLine " " & strCmd
ts.WriteBlankLines 1
ts.WriteLine "Calling C2 compiler"
Shell " " & strCmd
If Err.Number <> 0 Then
ts.WriteLine "Error in calling "
End If
ts.WriteBlankLines 1
ts.WriteLine "Returned from c2 compiler call"
ts.Close
End Sub
从命令行中我们可以看出生成给链接器执行的object文件,就是说怎么创建windows dll,
传递了什么参数。看下面代码:
我们必须中断调用链接器,这样我们可以看到vb传递了什么参数。看下面代码:
Public Sub Main()
On Error Resume Next
Dim strCmd As String, strPath As String
Dim oFS As New Scrip ng.FileSystemObject
Dim ts As TextStream
strCmd = Command
asp 源代码strPath = App.Path
Set ts = oFS.CreateTextFile(strPath & "\")
ts.WriteLine "Beginning execu on at " & Date & " " & Time()
ts.WriteBlankLines 1
ts.WriteLine "Command line parameters to LINK call:"
ts.WriteLine " " & strCmd
ts.WriteBlankLines 1
ts.WriteLine "Calling LINK linker"
Shell " " & strCmd
If Err.Number <> 0 Then
ts.WriteLine "Error in " Err .Clear
End If
ts.WriteBlankLines 1
ts.WriteLine "Returned from linker call"
ts.Close
End Sub
执行前,把原始 改成 ,上面代码编译为
如果我们同c 或者c++链接器比较命令行参数,不同之处一目了然。这里/DLL 开关指定创建标准的windows dll ,而且这里没有/DEF 开关来指定模块定义(module defini on .def)文件,用于列出dll 的输出函数。(在c 或者c++中,我们用语句来定义输出函数),vb 不支持它,然而,生成.def 文件就是定义一个库的输出。文件就是定义一个库的输出。接着,接着,如果我们检查vb 环境中Ac veX dll 工程生成的文件,vb 并没有生成.def 文件。文件。
检查了Ac veX dll 的输出表后,截获vb 的编译,截获vb 的链接,并同C 和C ++比较了传递给链接器的参数,我们可以识别出为什么在vb 中创建真正的windows dll 。不过用下面的办法,我们还是可以做到创建windows dll 的。的。
Vb 可以调用自己的定义的Ac veX DLL
pclass.dll (Ac veX DLL ,类名称:class1)
Public Func on myFunc on(ByVal i As Integer) As Integer
myFunc on= i End Func on
主程序调用:主程序调用:
Private Sub Command1_Click()
On Error GoTo errorHandle:
Dim obj As Object
Set obj = CreateObject("pclass.class1")    @#pclass 是DLL 名称,class1是pclass.dll 中的类名称中的
类名称
@#注意:不是模块名称注意:不是模块名称
Func on(20)
Set obj = Nothing
Exit Sub errorHandle:
MsgBox Err.Descrip on & " -- 清检查DLL 文件名称、类名称、是否注册等!"
Err .Clear End Sub

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。