|
本帖最后由 liucqa 于 2012-2-24 01:20 编辑
看了一篇文章,理解有所加强
有关API字符串--API programmer必看.rar
(10.04 KB, 下载次数: 89)
这篇文章来自
Win32 API Programming with Visual Basic 的第六章。这本书我在网上只找到英文版。谁有全书的中文版,共享一下,谢谢!
本书中文译名《Visual Basic Win32 API编程》
贴出来一小段供大家学习
对Visual Basic来说,所有的字符是以2字节的Unicode形式表述的。(译者:在Visual Basic里处理字符是以Unicode格式的,不管所处的操作系统是可以以ANSI格式处理字符的Win98还是以Unicode格式的WinNT,但Visual Basic也支持ANSI格式的字符串传送,例如调用一个需要接收ANSI字符串的API函数时,Visual Basic会自动将其内部以Unicode格式表述的字符串转换为ANSI格式字符串传送。ANSI格式的字符是仅以一个字节来表述的字符。)从另一方面来说,Visual Basic使用Unicode格式在字符串中表述字符。例如,ASCII这样表述字符h:&H68,而Unicode是这样表述的:&H0068,同时在内存中则是这样保存:68 00。
本来,字符串“help”在内存中应该保存为这样:
00 68 00 65 00 6c 00 70
注意,由于字符串在内存中是颠倒保存的,所以,实际上“help“在内存是这样保存的:
68 00 65 00 6c 00 70 00
好了,我们现在知道在Visual Basic中字符串类string并非我们原先想象的那样。为了避免任何可能的误解,我们把string类型理解为Unicode格式的字符数组,而实际上它就是这样子的。这也有助于我们区别ANSI格式的字符数组。
请仔细阅读以下几句话,因为这是理解string类型的关键:
当我们写下这几句代码时:
Dim str as String
Str=”help”
本质上来说,我们其实并没有定义了一个Unicode格式的字符数组。我们其实定义了一个BSTR类型的变量。一个BSTR类型的变量就是一个指向以NULL结尾的,以四个字节为保留字开头的Unicode格式字符数组的指针。
从Visual Basic 4开始,string类型就不同了。新的数据类型叫做BSTR字符串。
BSTR字符串有以下几个要点要强调一下:
1.一个BSTR字符串变量实际上是一个指针变量。它占用32bit即4个字节,就像其它的指针一样。而且,它指向一个Unicode格式的字符数组。但是,我们不能把字符串与BSTR字符串等同起来。我们必须用它自己确切的名字DD“BSTR“。
2.一个BSTR字符串变量指向的字符串数组必须由4个字节的保留字开始(保存字符串数组的字节数而不是字符数),由2个空字符结束。
3.由于空字符在Unicode格式的字符串中的任何位置都有可能出现,所以,以空字符声明一个Unicode格式的字符串的结束并不合适。因此,在4个保留字中保存字符串的长度是至关重要的。
4.我们再强调一下,BSTR字符串指针实际指向的是Unicode格式的字符数组的首地址,而不是开头的4个字节。接下来我们就会看到,在这儿这样不厌其烦地强调BSTR字符串变量的特征是为了与马上就要解释的VC++中的string类型作个比较。
5.图示中的4个字节的length记录的是字符数组的字节数(注意,不是字符数),包括结尾的空字节。因为数组是Unicode格式的,所以实际字符是length的一半。
在这儿强调一下,一个Unicode格式的空字符其实是占用2个字节的空间,而不是1个字节。在Unicode格式的数组中测试空字符时要当心这一点。
我们一般在惯例上说BSTR字符串“help”是“一个BSTR类型的字符串”。一般公认为,一个BSTR字符串变量指向的一个字符数组中包括至少两个空字符。
就Visual Basic来说,BSTR字符串未尾的两个空字节可能没什么用处,但是对Win32来说,它们却是至关重要的。原因在于,Win32版本的Unicode String(它称为LPWSTR)定义为指向一个空字符结尾的Unicode格式的字符串的指针。
从这个原因上解释BSTR字符串为什么要以空字符结尾就合情合理了。
有关String这个术语
为了避免任何可能的误解,以下我们仅使用术语BSTR、Unicode字符数组和ANSI字符数组,我们会尽量避开使用string这个术语。如果必须使用String,我们会把它改为Vusual Basic String(就是BSTR)或Visual C++ String(就是以上说过的LPSTR)。
然而,在Vusual Basic文档里,你会经常看到String这个字,至于它是以上所说的三种字符串中的哪一种,就要靠你自己的去判断了。
研究String的工具
如果我们想继续研究String,那么我们还需要一些工具。让我们来看看以下几个工具。
Visual Basic的StrConv函数:
StrConv函数是用来转变字符数组的格式的函数。它的语法为:
StrConv(string,conversion,LCID)
其中的String指的是一个BSTR类型的字符串,Conversion是一个常量(接下来马上就要介绍),而LCID是一个可选的标识符(在此我们忽略它)。
我们感兴趣的Conversion参数是以下两个:
VbUnicode(其实叫VbToUnicode更合适)
VbFromUnicode
这两个参数将BSTR字符数组转换为Unicode格式或ANSI格式。
但是现在我们有个麻烦。我们没有一个ANSI BSTR类型的字符串。定义中已经说过,BSTR字符数组指向的是Unicode格式的字符数组。
但我们还是可以想象一下,一个ANSI BSTR的字符串应该是怎样的。如同在图6-2中描述的一样,只须将Unicode格式的字符数组用ANSI格式的字符数组代替就是了。
现在我们说StrConv至少有两种合法的形式:
StrConv(an_ANSI_BSTR,vbFromUnicode)
StrConv(an_BSTR,vbUnicode)具有讽刺意思的是,在第一种情况的时候,Visual Basic居然不认识自己的函数的返回值!请看下面的代码:
s = "help"
Debug.Print s
Debug.Print StrConv(s, vbFromUnicode)
其输出居然是:
help
敨灬
原因是Visual Basic试图把ANSI BSTR字符串解释为BSTR字符串。请再看下面的代码:
s = "h" & vbNullChar & "e" & vbNullChar & "l" & vbNullChar & "p" & vbNullChar
Debug.Print s
Debug.Print StrConv(s, vbFromUnicode)
输出结果是:
h e l p
help
在这儿我们为了让StrConv正常工作,而仿照Unicode格式填充一个字符串数组并传递给Visual Basic让它处理。而这种结果是:一个ANSI BSTR字符串于是有了一个合法的BSTR的解释。
这表明,StrConv函数并不真正理解或关心传过来的字符串究竟是BSTR还是ANSI BSTR。它只是设想无论如何你只要传递给它一个字符串指针就成了,它的任务只是盲目地去转换这个字符数组而已。我们以后会发现,很多其它的字符串函数都是这样。这就是说,它们可以接收一个BSTR或是一个ANSI BSTR字符指针,只要这个指针指向的是空字节结尾的字符数组就行了。
Len和LenB函数
Visual Basic有两个返回字符串长度的函数:Len和LenB。它们都可以接收一个BSTR或是一个ANSI BSTR,并且返回一个长整型数值。以下的代码说明了一切:
s = "help"
Debug.Print Len(s), LenB(s)
Debug.Print Len(StrConv(s, vbFromUnicode)), LenB(StrConv(s, vbFromUnicode))
输出结果是:
4 8
2 4
这表明,Len返回的是字符数,而LenB返回的是在BSTR中的字节数。
Chr,ChrB和ChrW函数
这几个函数的输入参数和输出结果都不相同。刚接触它们时,你可能会感到无所适从。对此,我的建议是:把它们的定义多读几遍。
Chr函数接收一个在0到255之间的长整型的整数,返回一个长度为1的BSTR类型字符串。此处,BSTR指向的字符是Unicode格式的。所以,虽然长度为1,但实际占用2字节。从最新的Visual Basic的文档来看,Chr和Chr$没有区别。
ChrB函数接收一个在0到255之间的长整型的整数,但它的返回值是一个长度为1字节的ANSI BSTR类型的字符串。该字符串是ANSI格式,所以占用1个字节。
ChrW函数接收一个在0到255之间的长整型的整数,返回值是一个长度为1的BSTR的字符串。该字符串是Unicode格式,所以占用2个字节。
Asc,AscB和AscW函数
这些函数就是Chr的反函数。其中,AscB接收一个ANSI BSTR类型的字符串,并返回一个Byte型的该字符串第一个字符的ASCII代码。为了证明返回值确是Byte类型的数据,请看下面的代码:
Debug.Print VarType(AscB("h")) = vbByte
输出结果是True。从字面上来看,可能你会认为AscB会接收一个BSTR类型的字符,但是,实际上它只认这个BSTR字符的第一个字节,其它的字节就被忽略掉了。
Asc函数接收一个BSTR类型的字符串(不是ANSI BSTR),并返回一个该字符串第一个字符的Unicode代码。
Null字符串和Null字符
Visual Basic允许Null值的BSTR类型字符串。请看下面代码:
Dim s As String
s = vbNullString
Debug.Print VarPtr(s) ‘有关这两个函数,接下来马上介绍。
Debug.Print StrPtr(s)
输出结果是:
1243948
0
这说明,一个Null值的BSTR字符串仅仅是一个指向内容为0的字符指针。在Win32和Visual C++中,这种字符串叫做空指针。让我们再来看看vbNullString和vbNullChar的区别。vbNullChar并不是指针,它是一个值为0的Unicode字符。
请大家不要把一个值为Null的BSTR和一个空BSTR搞混了。请看下面代码:
Dim s As String
Dim t As String
s = vbNullString
t = ""
空BSTR字符串t是一个指向非空内存地址的指针。在那个地址保存的是空BSTR字符串的终止符。而且,它前面的那4个保留字节中保存的该字符串的长度信息为0。
VarPtr和StrPtr函数
在微软的文档里并没有VarPtr和StrPtr函数的描述,但它们是非常有用的。特别是VarPtr函数。
请看,如果参数var为有效变量的话,那么,
VarPtr(var)
返回的是变量的长整型地址。
如果str是一个BSTR字符串变量,那么:
StrPtr(str)
返回的是BSTR字符串指针指向的Unicode字符串的首地址。
|
|