在学生里看到这样一个声明:
Private Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal _ lpbuffer As String, nSize As Long) As Long
声明API函数:
在VB中声明API函数有两种方法:如果只在某个窗体中使用API函数,可以在窗体代码的General部分声明它,这里必须采用Private声明,因为这个API函数只能被一个窗体内的程序所调用。
声明的语法是:
Private Declare Function ... '有返回值时表示是个函数,用Function' Private Declare Sub..... '无返回值时,用sub'
想要在多个窗体中使用同一个API函数,就需要在模块中声明了。先添加一个模块, 然后采用如下语法声明:
Public Declare Function.... Public Declare Sub....
另外可采用以下几种方式使用API函数,以SetWindowPos函数(设置和获取窗口位置)为例:
Set忽略函数返回值的调用:
Set WindowPos Form1.hWnd, -2 ,0 ,0 ,0, 0, 3
注意此时函数的参数是不加括号的。
Call方法调用:
Call SetWindowPos(Form1.hWnd, -2, 0, 0, 0, 3)
注意这里需要加上括号,但我们不取回函数的返回值。
MyLng 取得函数返回值的调用:
MyLng = SetWindowPos(Form1.hWnd, -2, 0, 0, 0, 3)
此时需要加上括号,而且必须事先定义一个变量(变量的类型与函数返回值类型相同)来存储API函数的返回值。
advapi32.dll:
GetUserName Lib "advapi32.dll" Alias "GetUserNameA" '通过Alias标识了一个别名GetUserName给GetUserNameA,尾部的"A" 表明它是一个ANSI函数' 'GetUserName是VB中使用的过程名称。而GetUserNameA则是动态连接库中可以识别的名称'
advapi32.dll:是一个高级API应用程序接口服务库的一部分,用于支持非常多的API应用程序接口,包括安全和注册的调用。
GetUserName:是advapi32.dll中的一个函数,作用是获取当前线程的用户名
GetUserName函数:
随着系统安全性的加强,不同的用户有不同的上网权限,就需要识别当前的用户是什么帐号登录了,然后再作出权限分配。有出错时也需要对当前帐号进行记录下来,因为不同的帐号有不同的权限,有些磁盘是不允许操作的。面对这些需求,就需要使用GetUserName函数。
语法是:GetUserName(字符串, 整型数值)
Dim s$, cnt&, dl& cnt& = 199 s$ = String$(200,0) '返回200个AscII码值为0的字符' dl& = GetUserName(s$, cnt) Debug.Print Left$(s$, cnt); cnt
Private Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal - lpbuffer As String, nSize As Long) As Long
参数 类型及说明:
lpBuffer String,一个字串缓冲区,预先初始化成由nSize指定的长度。它将用于容纳用户名,是获取名称缓冲区。
nSize Long,初始化成lpBuffer的长度。返回以后,它会包含载入lpBuffer的字符数量 ,是缓冲区的大小和返回帐号的大小。
注解:
lpBuffer和nSize需要赋初值。
库名:advapi32.dll
分类:硬件与系统函数
Long,TRUE(非零)表示成功,否则返回零。会设GetLastErrorlpBuffer获取最后一个Errorlp缓冲区(String),一个字串缓冲区,预先初始化成由nSize指定的长度。它将用于容纳用户名nSize Long,初始化成lpBuffer的长度。返回以后,它会包含载入lpBuffer的字符数量
声明中的Lib 和 Alias 是怎么回事:
Lib:系统会使用到的函数库。
Alias:用于指定API函数的别名,如果我们调用的API函数要使用字符串(参数中包含String型)的话,Alias关键字是必须的。这是因为在ANSI和Unicode字符集中同一API函数的名称可能是不一样的,为了保证不出现声明错误,我们使用Alias关键字指出API函数的别名,一般来说在WIN9X平台下我们把API函数名后加一个大写A作为别名即可。
常见的API参数类型的说明
API函数的参数中最常见的是长整Long型数据类型,例如API中的句柄、一些特定的常量、函数的返回值都是此类型 的值;另外几种常见的参数类型有:整型Integer、Byte型、String型等。
声明中的ByVal是作什么用的
这跟VB的参数传递方式有关,在默认情况下VB是通过地址传递方式传递函数的参数、而有些API函数要求必须采用传值方式来传递函数参数(这两种参数传递方式是不同的,前者传递的是一个指针,而后者要求是参数真实的值)。这样就会发生错误,解决的办法是在API函数参数声明的前面加上ByVal关键字,这样VB就采用传值方式传递参数了。
怎样得到完整的API函数声明
VB自带了API文本查看器API TEXT VIEWER,我们可以在其中找到API函数的完整声明,然后把它粘贴到程序中即可。
使用Alias子句的几种情况:
Alias子句中的函数名是大小写敏感的,也就是说,必须与函数在生成时的声明(如在C源文件中的声明)一致。这是因为32位动态库与16位动态库不同,其中的函数名是区分大小写的。同样道理,如果没有使用Alias子句,那么在Function(或Sub)后的函数名也是区分大小写的。
通常在以下几种情况时需要使用Alias子句:
A. 处理使用字符串的系统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
应当注意,对于VB中使用的系统WindowsAPI函数,应该指定函数的ANSI版本,因为只 有WindowsNT才支持Unicode版本,而Windows95不支持这个版本。仅当应用程序只运行 在WindowsNT平台上的时候才可以使用Unicode版本。
B. 函数名是不标准的名称
有时,个别的DLL过程的名称不是有效的标识符。例如,它可能包含了非法的字符(如连字符),或者名称是VB的关键字(如GetObject)。在这种情况下,可以使用Alias关键字。
例如,操作环境DLLs中的某些过程名以下划线开始。尽管在VB标识符中允许使用标识符,但是下划线不能作为标识符的第一个字符。为了使用这种过程,必须先声明一个名称合法的过程, 然后用Alias子句引用过程的真实名称:
'lopen是VB中使用的过程名称。而_lopen则是动态连接库中可以识别的名称' Declare Function lopen Lib "kernel32" Alias "_lopen" _ (ByVal lpPathName As String, ByVal iReadWrite _ As Long) As Long
C. 使用序号标识DLL过程
除了使用名称之外,还可以使用序号来标识DLL过程。某些动态连接库中不包含过程的名称,在声明它们包含的过程时必须使用序号。同使用名称标识的DLL过程相比,如果使用序号,在最终的应用程序中消耗的内存将比较少,而且速度会快些。但是,一个具体的API的序号 在不同的操作系统中可能是不同的。
例如GetWindowsDirectory在Win95下的序号为432,而在WindowsNT4.0下为338。总而言之,如果希望应用程序能够在不同的操作系统下运行,那么最好不要使用序号来标识API过程。如果过程不属于API,或者应用程序使用的范围很有限,那么使用序号还是有好处的。
要使用序号来声明DLL过程,Alias子句中的字符串需要包含过程的序号,并在序号的前面加一个数字标记字符(#)。例如,Windowskernel中的GetWindowsDirectory函数的序号为432;可以用下面的语句来声明该DLL过程:
Declare Function GetWindowsDirectory Lib "kernel32" _ Alias "#432" (ByVal lpBuffer As String, _ ByVal nSize As Long) As Long
在这里,可以使用任意的合法名称作为过程的名称,VB将用序号在DLL中寻找过程。