设为首页收藏本站Access中国

Office中国论坛/Access中国论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

剖析 Declare 语句

1970-1-1 08:00| 发布者: 共享| 查看: 1317| 评论: 0

下面的示例是 GetTempPath 函数的 Declare 语句,该函数返回 Microsoft® Windows® 临时文件夹的路径:

Private Declare Function GetTempPath Lib "kernel32" _
Alias "GetTempPathA" (ByVal nBufferLength As Long, _
ByVal lpBuffer As String) As Long
关键字 Declare 告诉 VBA 您想在自己的项目中加入一个 DLL 函数定义。标准模块中的 Declare 语句可以是公共或私有的,这取决于您是想只让某个模块使用该 API 函数还是整个项目均可用。在类模块中,Declare 语句必须是私有的。

关键字 Function 后面的函数名是用来在 VBA 中调用该函数时用的名称。这个名称可以与 API 函数本身的名称相同,或者在 Declare 语句中使用关键字 Alias,表示您打算在 VBA 中用另外的名称(别名)来调用该函数。

在前面的例子中,DLL 中 API 函数的名称是 GetTempPathA,而从 VBA 中调用它的名称是 GetTempPath。

注意 关键字 Alias 后面的是 DLL 函数的真实名称。
注意 GetTempPath 是 Win32API.txt 文件给该函数起的别名,您可把它更改为任何想要的名称。
在 Declare 语句中使用别名的原因有以下几点:

一些 API 函数的名称以下划线 (_) 开头,这在 VBA 中是非法的。在 VBA 中必须使用别名来调用某函数。
因为别名允许程序员随意给 DLL 函数命名,使函数名符合您在 VBA 中的命名标准。
因为 API 函数区分大小写而 VBA 函数不区分,所以可使用别名来更改函数名的大小写。
一些 DLL 函数带有能接受不同数据类型的参数。这些函数的 VBA Declare 语句把这些参数的类型定义为 Any。调用声明了 Any 类型参数的 DLL 函数有一定的风险,因为 VBA 不做任何数据类型检查。如果想避免这种传递 Any 类型参数带来的危险,可以声明同一个 DLL 函数的多个版本,每个都有不同的名称和数据类型。
在 Windows API 中,所有带有字符串参数的函数都有两个版本:一个 ANSI 版本和一个 Unicode 版本。ANSI 版的函数名带有后缀 "A"(见前面的例子),而 Unicode 版的后缀是 "W"。虽然 VBA 内部使用 Unicode 版本,但它在调用 DLL 函数前会把所有的字符串转为 ANSI 字符串,所以,在 VBA 中调用 Windows API 函数时一般都用 ANSI 版。API 查看器外接程序自动给所有带有字符串参数的函数取别名,所以在调用函数时不必包括后缀 "A"。
关键字 Lib 指明要调用的函数在哪个 DLL 中。请注意,在 Declare 语句里,DLL 的名称被包含在一个字符串中。如果用户的系统中找不到关键字 Lib 后面指定的 DLL,对函数的调用将失败,并产生一个代号为 48 的运行时错误,“调用 DLL错误”。由于这种错误可在 VBA 代码中处理,所以可以编写代码来体面地应付错误。

注意 如果调用的函数位于某一基本的 Windows DLL 中就不存在这种问题,因为要加载应用程序,这些 DLL 肯定存在。
下表给出了 Windows API 中最常用的的 DLL。

DLL 包括
Kernel32.dll 低层操作系统函数,例如管理内存和资源的函数。
User32.dll Windows 管理函数,例如负责消息处理、计时器、菜单和通讯的函数。
GDI32.dll 图形设备接口 (GDI) 库,包括负责设备输出的函数,例如负责绘图、显示上下文和字体管理的函数。

大部分 DLL 都是用 C 或 C++ 语言编写的,包括那些 Windows API 中的 DLL。因为 C 或 C++ 函数对参数和数据类型的要求在几个方面与 VBA 函数不同,所以,在给 DLL 函数传递参数时,需要对 C 或 C++ 函数要求的参数和数据类型有一定了解。

而且,DLL 函数的许多参数是以传值方式传递的。默认情况下,VBA 中的参数以传址方式传递,所以当 DLL 函数要求参数是以传值方式传递时,必须在函数定义里包含关键字 ByVal。如果函数定义中漏掉关键字 ByVal,可能会在应用程序中引起非法页面错误。或者可能会出现代号为 49 的 VBA 运行时错误,“错误的 DLL 调用约定”。

以传址方式传递参数就是把该参数在内存中的位置传递给被调用的过程。如果该过程修改了参数的值,实际上改变的是该参数唯一的副本,所以当执行返回到调用过程时,参数中包含的是已修改的值。

而以传值方式向 DLL 函数传递参数实际上是传递了该参数的一个副本,函数只对这一副本进行操作。这可以防止函数修改实际参数的内容。当执行返回到调用过程时,参数包含的值与调用其他过程前相同。

因为以传址方式传递允许在内存中修改参数,所以如果以传址方式传递了错误参数,DLL 函数可能会错误地改写内存,从而造成错误或其他意想不到的行为。Windows 有许多值不应该改写。例如 Windows 为每个窗口分配了一个唯一的 32 位标识符,称为句柄。句柄是以传值方式传递给 API 函数的,因为如果 Windows 修改了某窗口的句柄,就不能再跟踪该窗口了。

注意 虽然关键字 ByVal 出现在一些 String 类型的参数前,但字符串总是以传址的方式传递给 Windows API 函数。

最新评论

QQ|站长邮箱|小黑屋|手机版|Office中国/Access中国 ( 粤ICP备10043721号-1 )  

GMT+8, 2024-5-2 09:07 , Processed in 0.057206 second(s), 16 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

返回顶部