首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VB >

VB到底应该用Unicode版API还是ANSI版的

2012-01-10 
【高分】VB到底应该用Unicode版API还是ANSI版的?受一些文章的影响,我把所有的API调用都申明为Unicode版的,并

【高分】VB到底应该用Unicode版API还是ANSI版的?
受一些文章的影响,我把所有的API调用都申明为Unicode版的,并且使用了TLB

可最近接连遇到API的版本问题
首先是DrawTextW和DrawTextA,用DrawTextW怎么折腾都是乱码,用DrawTextA轻松搞定
接着就是叶帆的SubClass类,我用TLB里面定义的Unicode版API替换了他用Delcare声明的API
  导致没有任何提示崩溃~折腾一天后终于找到问题了。
  貌似跟GetModuleHandleA,GetWindowLongA,SetWindowLongA,CallWindowProcA这些不涉及字符串操作的API有关
  崩溃了~
接着又发现Shell_NotifyIcon设置托盘图标的Tip也会乱码!!!


这里有个图片


还有这么个图



想请教一下,到底是用Unicode好呢还是ANSI好 (也许这不应该是个问题)
用Unicode版API,到底该怎么处理编码?


[解决办法]
DrawTextW和DrawTextA

Public Declare Function DrawTextA Lib "user32" Alias "DrawTextA" (ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long

Public Declare Function DrawTextW Lib "user32" Alias "DrawTextW" (ByVal hdc As Long, ByVal lpStr As Long, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long

dim str as String
str = "测试"
call DrawTextA(.., str, ...)

call DrawTextW(.., VarPtr(str), ...)


[解决办法]
VB当中的String本身就是Unicode,如果参数定义为String,则在调用API的时候会经过转换成为ANSI,如果你不希望经过转换,则直接传String的变量地址。
[解决办法]
所有指针都一律定义为Long,但是自己要记得,或者做个标记,需要用到的时候,再通过VarPtr等传入指针(实体一定不能被释放掉)。
[解决办法]

探讨
引用:
VB当中的String本身就是Unicode,如果参数定义为String,则在调用API的时候会经过转换成为ANSI,如果你不希望经过转换,则直接传String的变量地址。


难道说,VB不管API是怎么定义的,是什么版本,都给转换成ANSI再传递过去?

[解决办法]
探讨
引用:
所有指针都一律定义为Long,但是自己要记得,或者做个标记,需要用到的时候,再通过VarPtr等传入指针(实体一定不能被释放掉)。


那对于结构里面,固定长度的字符串呢?

这个没办法用指针了吧?

[解决办法]
探讨
恩,我试试先

[解决办法]
如果是一个出参(被调用的过程需要回写)的String参数,使用StrPtr,而不是VarPtr.
[解决办法]
同意8楼。
用“Private/Public Declare ...”语法声明的函数,VB编译器认为就是API函数,那么只要是用“As String”声明的参数,VB编译器一概无条件地把字串由BSTR转换为ANSI传递。
对于VB的字符串,几个专门“武器”大概有:
StrConv()
VarPtr() '-- 获得字符串变量的地址
StrPtr() '-- 获得字符串首字符的地址
Len(),LenB()
Chr(),ChrB(),ChrW()
Asc(),AscB(),AscW()
vbNullString
vbNullChar
[解决办法]
探讨
谢谢僵哥的提示……大部分问题都解决了

再追加一个问题:

Soyokaze 说到 :

用“Private/Public Declare ...”语法声明的函数,VB编译器认为就是API函数,那么只要是用“As String”声明的参数,VB编译器一概无条件地把字串由BSTR转换为ANSI传递。

那有办法阻止VB的这种行为么?

[解决办法]
实验过,行不通。只要声明中用了“As String”
楼主可以用一个有代表性的函数来实验:
VB code
Private Declare Function CharUpperWide Lib "user32" Alias "CharUpperW" (ByVal lpsz As Long) As Long
[解决办法]
我现在也是搞不懂W和A的API在什么地方要用哪一种。。。
[解决办法]

图2 没有说调用过程

要么就是说错了

vb用 unicode 存储字符串,用 ansi 操作字符串,这些字符串的转换操作在vb中非常频繁

这样做也是为了兼容9x,9x并非unicode系统,而com又是bstr的标准操作,为了平衡和为coder减负


vb就做了这些自动转换,实际调用 w api 速度上来讲还要比 a api 要快一些
[解决办法]

探讨
我现在也是搞不懂W和A的API在什么地方要用哪一种。。。

[解决办法]
探讨
DrawTextW和DrawTextA

Public Declare Function DrawTextA Lib "user32" Alias "DrawTextA" (ByVal hdc As Long, ByVal lpStr As String, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long

Public Declare Function DrawTextW Lib "user32" Alias "DrawTextW" (ByVal hdc As Long, ByVal lpStr As Long, ByVal nCount As Long, lpRect As RECT, ByVal wFormat As Long) As Long

dim str as String
str = "测试"
call DrawTextA(.., str, ...)

call DrawTextW(.., VarPtr(str), ...)

[解决办法]
路过................

我比较喜欢声明为LONG再传指针进去的方式.....
[解决办法]
探讨
路过................

我比较喜欢声明为LONG再传指针进去的方式.....

[解决办法]
不懂,帮顶
[解决办法]
不懂,帮顶
[解决办法]
帮顶
[解决办法]
探讨
看来要修改TLB了…………楼上各位有好用的全一点的TLB么

[解决办法]
探讨
包含所有API定义的TLB……

IDL文件加上头文件48M…………一个个去修改累死了

[解决办法]
探讨
看来要修改TLB了…………楼上各位有好用的全一点的TLB么

[解决办法]
...
[解决办法]
UP
[解决办法]
我是菜鸟一个...
[解决办法]
ZxZxZxZx
[解决办法]
路过
[解决办法]
是不是也像C/C++ Windows编程里边有类似的宏定义TEXT() _T()之类的呢? 当然我是说VB里等价的东西用代替
[解决办法]
探讨
是不是也像C/C++ Windows编程里边有类似的宏定义TEXT() _T()之类的呢? 当然我是说VB里等价的东西用代替

[解决办法]
mark
[解决办法]
探讨
引用:
路过................

我比较喜欢声明为LONG再传指针进去的方式.....

如果对方COPY出来的是ANSI码,或者需要的是ANSI码,那就...

[解决办法]
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
[解决办法]
帮顶
[解决办法]
哈哈,接点分分分分分分......
------解决方案--------------------


.............
[解决办法]
圣诞节 _.|,_ 就要 
'|` 来临了哦 
/ \
/`,o\ 
送上 /_* ~_\ 
我 / o .'\ 
/_,~' *_\最真挚的 
/`. * *\ 祝福 
/ `~. o \ 
/_ * `祝所有朋友圣诞节 
/ o * ~'\ 快乐! 
/ * .~~' o\ 
/_,.~~'` * _\ 
/`~.. o \ 
/_ o `~~.,\ 
/* o _..~~`'* o\ 
`-._.~'`' * __.-' 
":-------:"
":-------:" 
☆圣诞快乐☆ 


圣诞快乐 
平平安安 


   /\~~~~~~~~~~~~~\   ▓  ^*^   ☆  $$  .☆ 
  ./ \~~~▓~  ~~~~\ ◆  圣诞 .快乐  *  $◢◣$  * 
  / ^^ \ ══════\.◆    * *  *  $◢★◣$  * 
 ..▎[] ▎田 田 ▎ |┃◆  .     *  $◢■■◣$  * 
 &&▎  ▎    ▎'|'▎ @       * $◢■■■◣$ * 
# ■■■■■■■■■■〓▄▃▂▁愿你圣诞快乐︸︸||︸︸ 

[解决办法]

[解决办法]
帮顶
[解决办法]
有深度!
[解决办法]
顶一下
[解决办法]
我觉得应该用ansi版的
[解决办法]
号号号发动洒 发达十分
[解决办法]

[解决办法]
严重关注!
[解决办法]
僵哥牛人,横跨VB C++ Delphi几大论坛。。。
重视未来趋势,我比较喜欢Unicode版本,
貌似Unicode程序无法在Win98以下运行?(虽然几乎没人用了)
[解决办法]
接分.


PS: 
我的目标是 ---->

^_^

[解决办法]
楼主伟大!支持!顺便接分!
[解决办法]
VB6/VBA/VBS 是同样的,都是 Unicode 内核,ANSI 界面!
不要奇怪,Unicode是大势所趋,VB6 采用 Unicode 内核是为了代表最先进的文化发展方向;
但 VB6 发行时主流的Win95操作系统是 ANSI 内核的,为了能在Win95/98中使用,VB6全面采用ANSI界面,只有这样才能代表最广大人民群众的利益。
所以 VB6 的 String 传给API时会自动被转化为 ANSI string,从API返回后又被自动转换为 unicode String。

所以用 VB6/VBA/VBS 必须用 ANSI 版的API。
如果有些API只有Unicode版本,你必须自己完成这样的工作才能使用:
 1 将 VB6 的字符串转化成 unicode 内码的字节数组
 2 把字节数组传给 unnicode 界面的API
 3 把API处理结果又自行转化为 String。


VB.NET 是和 VB6 完全不同的东东,是 Unicode 内核的,但是有 ANSI 和 Unicode 两种界面。
[解决办法]
路过学习...

热点排行
Bad Request.