|
使用API的过程中,会遇到一些需要返回字符串的API,比如GetClassName,GetWindowText,GetComputerName等.
这类API的共同特点是需要传入一个初始化为一定长度的字符串以及这个字符串的长度,并且在返回值(或某参数)里面返回复制到字符串内的字符的长度.
下面以GetComputerName为例,说明一下这类API使用这种方式的原理.
GetComputerName原型如下:
BOOL GetComputerName(
LPTSTR lpBuffer, // 缓冲区地址
LPDWORD nSize // 输入时,缓冲区长度;输出时,复制到缓冲区里的字符数
);
返回值为标志着是否成功复制的布尔变量.
那么在VB里面使用,就需要在lpBuffer参数处传入一个初始化为一定长度的字符串,并在nSize参数处以ByRef方式传入这个字符串的长度:
Option Explicit
Private Declare Function GetComputerName Lib "kernel32.dll" Alias "GetComputerNameA" ( _
ByVal lpBuffer As String, _
ByRef nSize As Long) As Long
Private Sub Form_Load()
Dim lpBuffer As String, nSize As Long, lRet As Long
nSize = 256
lpBuffer = Space(nSize) '分配256个长度
lRet = GetComputerName(lpBuffer, nSize)
'nSize参数的声明为ByRef,因为要用于返回"复制到缓冲区内字符的数量"
If lRet = 1 Then
'C里面True = 1,False = 0,而VB里True = -1,False = 0,所以API不能声明为Boolean返回值.
lpBuffer = Mid(lpBuffer, 1, nSize) '利用nSize的值来去掉多余的字符
Debug.Print """" & lpBuffer & """"
End If
End Sub
字符串缓冲区lpBuffer参数为什么要声明为ByVal,是因为BSTR的特殊性.实际传入到API里面的值,是一个指向lpBuffer字符串地址的指针.
因此把lpBuffer参数声明为ByVal lpBuffer As Long后再在调用时用StrPtr(lpBuffer)也是一样的效果,只是没必要......
由于这是一个缓冲区,所以事先需要初始化,就好象一张能写入XX个字的白纸一样,然后再拿给API,并告诉它,这张纸最多可以写XX个字.
当API得到所需要的字符串内容后,会检查这些内容的长度是否小于给出的缓冲区长度.如果缓冲区小了,那么就会在返回值(或某参数)里给出所需要的长度.
此时就需要再次分配足够的缓冲区并再次调用API来完成操作.
当然,这种情况很少碰到,因为我们完全可以一次性分配足够的缓冲区:)
对于如GetClassName,GetWindowText等API而言,复制到缓冲区内的字符数量是由API返回值来给出的.
具体一个API如何使用,请查看MSDN(本论坛总置顶帖"常用下载大全"里面有)
所以要记得使用这些值,不要再用判断NULL啊之类的非标准代码了~~~(话说,见到很多代码就是找NULL,晕倒.) |
|