|
楼主 |
发表于 2016-6-11 20:43
|
显示全部楼层
本帖最后由 hyefeifei 于 2016-6-12 09:20 编辑
这个贴子开的真是有些悔啊,没多少人看不说,制做这些图着实辛苦,不过即然开了,尽量坚持到底吧。
当vba发现你要传递一个字符串参数给一个外部函数(copymemory)时,它会叫暂停,然后:
a. 首先它把字符串由Unicode码转为ansi码
b. 其次,它把转成ansi码的字符串变量传给函数
c. 函数执行完后,它把得到的结果再由ansi码转回Unicode
具体见下图:
关于unicode与ansi,你须知道下面一条就可以了:
在unicode中,中文和英文字符都占2个字节,在ansi中,中文占2个字节,英文占1个字节。
我们再看下面的例子:
- Sub testn1()
- Dim s1 As String
- Dim s2 As String
- s1 = "abcde混沌"
- s2 = String$(7, 0)
- CopyMemory ByVal s2, ByVal s1,7
- Debug.Print s2
- End Sub
复制代码 |
虽然"abcde混沌"的长度为7,但得到的结果s2是:“abcde混”,刚才说了,转成ansi码时,英文字符占一个字节,中文字符占2个字节,这里一共有5个英文字符,2个中文字符,所以ansi的长度应该是9,把程序改为:
- Sub testn1()
- Dim s1 As String
- Dim s2 As String
- s1 = "abcde混沌"
- s2 = String$(9, 0)
- CopyMemory ByVal s2, ByVal s1,9
- Debug.Print s2
- End Sub
复制代码 |
你会发现结果正确了。
那么,难道字符串的长度每回我都要数一下吗?我们如何取得这个长度呢?你可以用:
LenB(VBA.StrConv(s1, vbFromUnicode))
来取字符串长度,程序修改如下:
- Sub testn2()
- Dim s1 As String
- Dim s2 As String
- Dim p As Long
- s1 = "abcde混沌"
- p = LenB(VBA.StrConv(s1, vbFromUnicode))
- s2 = String$(p, 0)
- CopyMemory ByVal s2, ByVal s1, p
- Debug.Print s2
- End Sub
复制代码 |
看了以上的讲解,你也许觉得有些繁琐了,又要转换,又要计算长度,有没有绕过UA转换的方法呢?当然是有,我们看下图
Copymemory byval s2,byval s1,9 这种方式,是通过线路1,线路2,分别到郑家和王家的,我们也可以通过线路3到郑家,通过线路4到王家,代码为:
Copymemory byval strptr(s2),byval strptr(s1),14
当s1,s2在括号中时,vba就不会发现我们是在传字符串给函数,也就不会做转换了,此时,我们直接到郑家取14个长度的内容,放到王家,所以第三个参数为14,程序如下:
- Sub testb1()
- Dim s1 As String
- Dim s2 As String
- s1 = "abcde混沌"
- s2 = String$(Len(s1), 0) ‘这句要用len,实际会在内存分配14个字节空间
- CopyMemory ByVal StrPtr(s2), ByVal StrPtr(s1), LenB(s1) ‘这句要用lenb,要复制14个字节
- Debug.Print s2
- End Sub
复制代码 |
我们看示意图,既然线路1,3可以到郑家,线路2,4可以到王家,那么我们可不可以这样组合:
CopyMemory ByVal StrPtr(s2), ByVal s1,a
不要这样做,因为这里参数2没转码,参数1转码,所以会得出错误的结果。
待续……
|
|
评分
-
4
查看全部评分
-
|