明辉站/网站教程/内容

如何手工声明API

网站教程2024-02-18 阅读
[摘要]尽管 Visual Basic 在 Win32api.txt 中提供了大量的预定义声明,但还是需要知道如何亲自编写声明。例如,有时希望访问用其它语言编写的 DLL 中的过程,或者改写 Visual Basic 的预定义声明,以满足特殊需要。  要声明一个 API 过程,需要在代码窗口的“声明”部分...
尽管 Visual Basic 在 Win32api.txt 中提供了大量的预定义声明,但还是需要知道如何亲自编写声明。例如,有时希望访问用其它语言编写的 DLL 中的过程,或者改写 Visual Basic 的预定义声明,以满足特殊需要。
  要声明一个 API 过程,需要在代码窗口的“声明”部分增加一个 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]]...])]

  缺省情况下,在标准模块中声明的 API 过程是公有的,可以在应用程序的任何地方调用它。在其它类型的模块中定义的 API 过程是模块私有的,必须在它们前面声明 Private 关键字,以示区分。

 

  一.指定库

  Declare 语句中的 Lib 子句用来告诉 Visual Basic 如何找到包含过程的 .API 文件。如果引用的过程属于 Windows 核心库(User32、Kernel32 或 GDI32),则可以不包含文件扩展名:

Declare Function GetTickCount Lib "kernel32" Alias _
"GetTickCount" () As Long
  对于其它 DLL,Lib 子句指定文件的路径:

Declare Function lzCopy Lib "c:\windows\lzexpand.API" _
(ByVal S As Integer, ByVal D As Integer) As Long
  如果未指定 libname 的路径,Visual Basic 将按照下列顺序查找该文件:

.exe 文件所在的目录


当前目录


Windows 位系统目录(通常为 \Windows\System)


Windows 目录(不一定是 \Windows)


Path 环境变量中的目录


下表中列出了通常的操作系统环境库文件。
动态链接库 描述
Advapi32.API 高级 API 服务,支持大量的 API(其中包括许多安全与注册方面的调用)
Comdlg32.API 通用对话框 API 库
Gdi32.API 图形设备接口 API 库
Kernel32.API Windows 32 位核心的 API 支持
Lz32.API 32 位压缩例程
Mpr.API 多接口路由器库
Netapi32.API 32 位网络 API 库
Shell32.API 32 位 Shell API 库
User32.API 用户接口例程库
Version.API 版本库
Winmm.API 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 关键字,但是如果包含该关键字,就能够清楚地看出数据是以何种方式传递的。
  许多 API 过程要求参数以值方式传递。这意味着它们需要实际的数据,而不是数据的内存地址。如果过程需要一个传值参数,而传递给它的参数是一个指针,那么由于得到了错误的数据,该过程将不能正确地工作。
  要使参数以使用值方式传递,在 Declare 语句中需要在参数声明的前面加上 ByVal 关键字。例如,InvertRect 过程要求第一个参数使用值,而第二个使用引用:

Declare Function InvertRect Lib "user32" Alias _
"InvertRectA" (ByVal hdc As Long, _
lpRect As RECT) As Long

  也可以在调用过程时使用 ByVal 关键字。
  字符串参数是一个特例。如果以使用值方式传递字符串,那么传递的将是该字符串中第一个数据字节的地址;如果以使用引用方式传递字符串,那么实际传递的将是用来保存另一个地址的内存单元的地址;后面的“地址”实际是字符串的第一个数据字节的内存地址。

……

相关阅读