rt,请指点

解决方案 »

  1.   

    输出函数的标准DLL不需要先注册,只需要拷贝到系统目录然后再VB中定义DLL的输出函数就可以调用函数的功能了。
      

  2.   

    system32或者你的应用程序所在地目录都可以
      

  3.   

    在应用程序中使用 DLL 过程
    由于 DLL 过程存在于 Visual Basic 应用程序之外的文件中,在使用时必须指定过程的位置和调用参数。可以用 Declare 语句提供这类信息。在声明了 DLL 过程之后,可以把它当做 Visual Basic 自己的过程使用。重点   如果在 Visual Basic 中直接调用 DLL,那么 Visual Basic 环境下固有的安全机制将受到不利影响。这意味着在测试和调试程序时可能会遇到更多的系统故障。为了减少这种危险,在声明 DLL 过程、传递参数和指定类型的时候务必要小心。无论在什么情况下,一定要经常保存已经完成的工作。DLL 可以提供不同凡响的功能,但是要用好它也不容易。下例将演示如何调用 Windows API 中的过程。调用函数 SetWindowText 来改变一个窗体的标题栏。当然,在实际应用中,通常总是利用 Visual Basic 的 Caption 属性来改变标题栏。该示例的目的在于说明如何声明并调用过程。声明 DLL 过程
    首先,在模块的声明部分对过程进行声明:Private Declare Function SetWindowText Lib "user32" _
    Alias "SetWindowTextA" (ByVal hwnd As Long, _
    ByVal lpString As String) As Long过程的精确语法定义可以用 API Viewer 应用程序找到,在 Win32api.txt 文件中也可以找到它。如果将 Declare 放在 Form 或者 Class 模块内,那么必须在它的前面加上 Private 关键字。同一个 DLL 过程在一个工程中只需声明一次;然后可以任意调用。详细信息 关于如何声明语句,请参阅本章后面的“声明 DLL 过程”主题。调用 DLL 过程
    在声明了函数之后,调用它的方式与标准的 Visual Basic 函数相同。在下例中,Form Load 事件调用了上面声明的过程。Private Sub Form_Load()
       SetWindowText Form1.hWnd, "Welcome to VB"
    End Sub在运行这段代码时,函数首先使用 hWnd 属性确定要修改标题栏的窗口(Form1.hWnd),然后将标题栏修改为“Welcome to VB”。需要牢记的是:Visual Basic 不能验证传递到 DLL 过程的值是否正确。如果传递了错误的值,那么过程将出错,并可能因此导致 Visual Basic 应用程序停止运行。这样就不得不重新加载和启动应用程序。在测试 DLL 过程时千万要小心,一定要经常地保存自己的工作。注意   极少数 API 调用能够识别缺省的 Variant 数据类型。最好声明具体的变量类型并使用 Option Explicit,这样,API 的可靠性要高得多。
      

  4.   

    声明 DLL 过程
    尽管 Visual Basic 在 Win32api.txt 中提供了大量的预定义声明,但还是需要知道如何亲自编写声明。例如,有时希望访问用其它语言编写的 DLL 中的过程,或者改写 Visual Basic 的预定义声明,以满足特殊需要。要声明一个 DLL 过程,需要在代码窗口的“声明”部分增加一个 Declare 语句。如果该过程返回一个值,应将其声明为 Function:Declare Function publicname Lib "libname" [Alias "alias"] [([[ByVal] variable [As type] [,[ByVal] variable [As type]]...])] As Type如果过程没有返回值,可将其声明为 Sub:Declare Sub publicname Lib "libname" [Alias "alias"] [([[ByVal] variable [As type] [,[ByVal] variable [As type]]...])]缺省情况下,在标准模块中声明的 DLL 过程是公有的,可以在应用程序的任何地方调用它。在其它类型的模块中定义的 DLL 过程是模块私有的,必须在它们前面声明 Private 关键字,以示区分。在 32 位的 Visual Basic 中过程名是区分大小写的。在以前的 16 位版本中,过程名是不区分大小写的。详细信息   请参阅《联机手册》中《语言参考》中的“声明语句”。指定库
    Declare 语句中的 Lib 子句用来告诉 Visual Basic 如何找到包含过程的 .dll 文件。如果引用的过程属于 Windows 核心库(User32、Kernel32 或 GDI32),则可以不包含文件扩展名:Declare Function GetTickCount Lib "kernel32" Alias _
    "GetTickCount" () As Long对于其它 DLL,Lib 子句指定文件的路径:Declare Function lzCopy Lib "c:\windows\lzexpand.dll" _
    (ByVal S As Integer,    ByVal D As Integer) As Long如果未指定 libname 的路径,Visual Basic 将按照下列顺序查找该文件: .exe 文件所在的目录
    当前目录
    Windows 位系统目录(通常为 \Windows\System)
    Windows 目录(不一定是 \Windows)
    Path 环境变量中的目录 
    下表中列出了通常的操作系统环境库文件。动态链接库 描述 
    Advapi32.dll 高级 API 服务,支持大量的 API(其中包括许多安全与注册方面的调用) 
    Comdlg32.dll 通用对话框 API 库 
    Gdi32.dll 图形设备接口 API 库 
    Kernel32.dll Windows 32 位核心的 API 支持 
    Lz32.dll 32 位压缩例程 
    Mpr.dll 多接口路由器库 
    Netapi32.dll 32 位网络 API 库 
    Shell32.dll 32 位 Shell API 库 
    User32.dll 用户接口例程库 
    Version.dll 版本库 
    Winmm.dll Windows 多媒体库 
    Winspool.drv 后台打印接口,包含后台打印 API 调用。 
    处理使用字符串的 Windows API 过程
    如果调用的 Windows API 过程要使用字符串,那么声明语句中必须增加一个 Alias 子句,以指定正确的字符集。包含字符串的 Windows API 函数实际有两种格式:ANSI 和 Unicode。因此,在 Windows 头文件中,每个包含字符串的函数都同时有 ANSI 版本和 Unicode 版本。例如,下面是 SetWindowText 函数的两种 C 语言描述。可以看到,第一个描述将函数定义为 SetWindowTextA,尾部的“A”表明它是一个 ANSI 函数:WINUSERAPI
    BOOL
    WINAPI
    SetWindowTextA(
       HWND hWnd,
       LPCSTR lpString);第二个描述将它定义为 SetWindowTextW,尾部的“W”表明它是一个 Unicode 函数:WINUSERAPI
    BOOL
    WINAPI
    SetWindowTextW(
       HWND hWnd,
       LPCWSTR lpString);因为两个函数实际的名称都不是“SetWindowText”,要引用正确的函数就必须增加一个 Alias 子句:Private Declare Function SetWindowText Lib "user32" _
    Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal _
    lpString As String) As Long请注意,Alias 子句后面的字符串必须是过程的真正名称,而且必须是区分大小写的。重点   对于 Visual Basic 中使用的 API 函数,应该指定函数的 ANSI 版本,因为只有 Windows NT 才支持 Unicode 版本,而 Windows 95 不支持这个版本。仅当应用程序只运行在 Windows NT 平台上的时候才可以使用 Unicode 版本。使用值或引用传递
    在缺省的情况下,Visual Basic 以引用方式传递所有参数。这意味着并没有传递实际的参数值,Visual Basic 只传递了数据的 32 位地址。在 Declare 语句中不要求包含 ByRef 关键字,但是如果包含该关键字,就能够清楚地看出数据是以何种方式传递的。许多 DLL 过程要求参数以值方式传递。这意味着它们需要实际的数据,而不是数据的内存地址。如果过程需要一个传值参数,而传递给它的参数是一个指针,那么由于得到了错误的数据,该过程将不能正确地工作。要使参数以使用值方式传递,在 Declare 语句中需要在参数声明的前面加上 ByVal 关键字。例如,InvertRect 过程要求第一个参数使用值,而第二个使用引用:Declare Function InvertRect Lib "user32" Alias _
    "InvertRectA" (ByVal hdc As Long, _
    lpRect As RECT) As Long也可以在调用过程时使用 ByVal 关键字。注意   在查看使用 C 语言语法的 DLL 过程文档时,请记住 C 以传值方式传递数组以外的参数。字符串参数是一个特例。如果以使用值方式传递字符串,那么传递的将是该字符串中第一个数据字节的地址;如果以使用引用方式传递字符串,那么实际传递的将是用来保存另一个地址的内存单元的地址;后面的“地址”实际是字符串的第一个数据字节的内存地址。本章后面的帮助主题“将字符串传递到 DLL 过程”将解释如何确定字符串参数传递的正确方式。不标准的名称
    有时,个别的 DLL 过程的名称不是有效的标识符。例如,它可能包含了非法的字符(如连字符),或者名称是 Visual Basic 的关键字(如 GetObject)。在这种情况下,可以使用 Alias 关键字。例如,操作环境 DLL 中的某些过程名以下划线开始。尽管在 Visual Basic 标识符中允许使用下划线,但是下划线不能作为标识符的第一个字符。为了使用这种过程,必须先声明一个名称合法的过程,然后用 Alias 子句引用过程的真实名称:Declare Function lopen Lib "kernel32" Alias "_lopen" _
    (ByVal lpPathName As String, ByVal iReadWrite _
    As Long) As Long在上例中,lopen 是 Visual Basic 中使用的过程名称。而 _lopen 则是 DLL 中可以识别的名称。为了使用方便,也可以使用 Alias 子句改变过程的名字。如果使用自己的名称替代了过程原来的名称(例如使用 WinDir 代替 GetWindowsDirectoryA),那么必须在文档中清楚地说明这种修改,从而便于将来对文档进行维护。使用序号标识 DLL 过程
    除了使用名称之外,还可以使用序号来标识所有 DLL 过程。某些 DLL 中不包含过程的名称,在声明它们包含的过程时必须使用序号。同使用名称标识 DLL 过程相比,如果使用序号,在最终的应用程序中消耗的内存将比较少,而且速度会快些。重点   一个具体的 API 的序号在不同的操作系统中可能是不同的。例如 GetWindowsDirectory 在 Win95 下的序号为 432,而在 Windows NT 4.0 下为 338。总而言之,如果希望应用程序能够在不同的操作系统下运行,那么请不要使用序号来标识 API 过程。如果过程不属于 API,或者应用程序使用的范围很有限,那么使用序号还是有好处的。要使用序号来声明 DLL 过程,Alias 子句中的字符串需要包含过程的序号,并在序号的前面加一个数字标记字符 (#)。例如,Windows kernel 中的 GetWindowsDirectory 函数的序号为 432;可以用下面的语句来声明该 DLL 过程:Declare Function GetWindowsDirectory Lib "kernel32" _
    Alias "#432" (ByVal lpBuffer As String, _
    ByVal nSize As Long) As Long注意,这里可以使用任意的合法名称作为过程的名称,Visual Basic 将用序号在 DLL 中寻找过程。为了得到要声明的过程的序号,可以使用 Dumpbin.exe 等实用工具。(Dumpbin.exe 是 Microsoft Visual C++ 提供的一个实用工具。)利用 Dumpbin,可以提取出 .dll 文件中的各种信息,例如 DLL 中的函数列表,它们的序号以及与代码有关的其它信息。详细信息   关于运行 Dumpbin 实用程序的有关说明,请参阅 Microsoft Visual C++ 文档。灵活的参数类型
    某些 DLL 过程的同一个参数能够接受多种数据类型。如果需要传递多种类型的数据,可以将参数声明为 As Any,从而取消类型限制。例如,根据需要,下面的声明中的第三个参数 (lppt As Any) 既可以传递一个 POINT 结构的数组,也可以传递一个 RECT 结构:Declare Function MapWindowPoints Lib "user32" Alias _
    "MapWindowPoints" (ByVal hwndFrom As Long, _
    ByVal hwndTo As Long, lppt As Any, _
    ByVal cPoints As Long) As LongAs Any 子句提供了一定的灵活性,但是,由于它不进行任何的类型检查,风险也随之增加。如果不进行类型检查,那么在调用过程时用错类型的可能性增加,这可能导致各种问题,包括应用程序的失败。在使用 As Any 子句时,必须仔细检查所有参数的类型。在消除了类型限制以后,Visual Basic 假定参数以传引用方式传递。在实际调用过程时,如果要使用传值方式,可以加入 ByVal。字符串将以传值方式传递,因此传递的是指向字符串的指针,而不是指向指针的指针。更深入的讨论请参阅“将字符串传递到 DLL 过程”。
      

  5.   

    将 C 语言声明转换为 Visual Basic 声明
    在文档中,通常使用 C 语言的语法描述 DLL 中的过程。要在 Visual Basic 中调用这些过程,需要将它们转换成合法的 Declare 语句,并使用正确的参数调用它们。在进行这种转换时,必须将 C 数据类型转换为 Visual Basic 的数据类型,并且说明每个参数是以使用值的 (ByVal) 方式,还是使用引用的 (ByRef)(缺省)方式。下表针对常用的 C 语言数据类型列出了与之等价的 Visual Basic 类型(用于 32 位版本的 Windows)。C 语言数据类型 在 Visual Basic 中声明为 调用时使用的表达式 
    ATOM ByVal variable As Integer 结果为 Integer 类型的表达式 
    BOOL ByVal variable As Long 结果为 Long 类型的表达式 
    BYTE ByVal variable As Byte 结果为 Byte 类型的表达式 
    CHAR ByVal variable As Byte 结果为 Byte 类型的表达式 
    COLORREF ByVal variable As Long 结果为 Long 类型的表达式 
    DWORD ByVal variable As Long 结果为 Long 类型的表达式 
    HWND, HDC, HMENU 等。(Windows 句柄) ByVal variable As Long 结果为 Long 类型的表达式 
    INT, UINT ByVal variable As Long 结果为 Long 类型的表达式 
    LONG ByVal variable As Long 结果为 Long 类型的表达式 
    LPARAM ByVal variable As Long 结果为 Long 类型的表达式 
    LPDWORD variable As Long 结果为 Long 类型的表达式 
    LPINT, LPUINT variable As Long 结果为 Long 类型的表达式 
    LPRECT variable As type 自定义类型的任意变量 
    LPSTR, LPCSTR ByVal variable As String 结果为 String 类型的表达式 
    LPVOID variable As Any 任何变量(在传递字符串的时候使用 ByVal) 
    LPWORD variable As Integer 结果为 Integer 类型的表达式 
    LRESULT ByVal variable As Long 结果为 Long 类型的表达式 
    NULL As Any 或
    ByVal variable As Long ByVal Nothing 或 ByVal 0& 或 vbNullString 
    SHORT ByVal variable As Integer 结果为 Integer 类型的表达式 
    VOID Sub procedure 不可用 
    WORD ByVal variable As Integer 结果为 Integer 类型的表达式 
    WPARAM ByVal variable As Long 结果为 Long 类型的表达式