好了在简单地介绍了 Unicode 之后,现在来介绍 Unicode API(什么?不知道什么是 API ?(汗)如果是那样的话这篇文章可能不太适合你)。
Windows NT 从一开始就在其内部使用 Unicode ,以至于其后续产品(Windows 2000、XP)都一直沿用它。而 Windows 95、98和 ME 就没有那么幸运,它们都一直使用单(双)字节的字符集。这样就使得同一个有关字符串的 API 有两个不同字符集的版本:Unicode 版和非 Unicode 版。在函数名上,Unicode 版的 API 具有一个 ''''W'''' 后缀代表 wide ,如:MessageBoxW;而非 Unicode 版的 API 具有一个 ''''A'''' 后缀代表 ANSI ,如:MessageBoxA。 在 Windows NT/2000/XP 上这两种版本的 API 都有,也就是说 Windows NT 支持 Unicode 和非 Unicode 字符集。而在 Windows 95/98/ME 上几乎所有 API 都只有其非 Unicode 版本,意味着它们之支持单(双)字节字符集。
VB 和 Unicode API
现在言归正传。VB 在使用了 Unicode 之后,可以享受到 Unicode 所带来的各种好处。不过,麻烦也随之而来了…… 因为 Windows 95/98/ME 不支持 Unicode ,而 VB 只支持 Unicode ,所以当从 VB 里调用一个非 Unicode API 时,VB 先要把所有字符串都转换成非 Unicode 字符串,然后调用 API,最后把所有字符串再转换回 Unicode(见图1)。这样使得 API 的调用速度变得十分缓慢,而且效率很低。
看到这里,也许有的人会问了“那为什么不用 Unicode API 呢?”在 API 查看器中的 API 都是非 Unicode 的(Alias 以 ''''A'''' 结尾),是因为兼容性问题。要让程序在 Windows 9x 和 NT 里都能执行,就必须要调用非 Unicode 的 API ,要不然的话会很麻烦;不过这是以性能为代价的。 如果程序需要高性能,经常使用需要传递字符串为参数的 API,而且只运行在 Windows NT/2000/XP 环境下的话(如服务器程序),完全可以用 Unicode API 来替换效率超低的非 Unicode API (见图2)。
对于刚接触 API 的程序员来说,知道怎样把现有的非 Unicode API 声明转化为 Unicode API 声明就已经足够了:
以下是一个简单的 API 声明:(作用是获得一个窗体的标题)
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long ''''GetWindowTextA'''' 指明这是一个非 Unicode API
以下是修改后的 API 声明:
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextW" (ByVal hwnd As Long, ByVal lpString As Long, ByVal cch As Long) As Long ''''GetWindowTextW'''' 指明这是一个 Unicode API
由此可见,修改一个非 Unicode API 成为一个 Unicode API 的要点是: * 把 Alias 里函数名的结尾 ''''A'''' 换成 ''''W''''。 * 把所有 ByVal *** As String ,改为 ByVal *** As Long 。
'''' 在 VB 中使用 Unicode API '''' 选择 lstrcpy 这个函数完全是因为所有除了 Windows 95 的 Windows 系统都支持它的 Unicode 版本,包括 WIndows 98 和 ME。 '''' 使得大家可以在任何 WIndows 95 以上的系统中都可以调试此例子。(事实上, Windows 95/98/ME 只支持大约 16 个 API 的 Unicode 版本。)
'''' 此程序只是简单地用 API 来复制一个字符串到另一个字符串。该程序只需要一个 Module 就足够了。请务必把工程的启动窗口设为 Sub Main() 。
Option Explicit
'''' lstrcpy API 的作用是复制一个字符串到另一个字符串。Unicode 和非 Unicode 版本分别为 lstrcpyW 和 lstrcpyA 。 Private Declare Function lstrcpyA Lib "kernel32" (ByVal lpString1 As String, ByVal lpString2 As String) As Long Private Declare Function lstrcpyW Lib "kernel32" (ByVal lpString1 As Long, ByVal lpString2 As Long) As Long '''' 用 timeGetTime API 来计算时间。 Private Declare Function timeGetTime Lib "winmm.dll" () As Long Private Const COPY_TIMES = 10000& '''' 要复制的次数。
Sub Main() Dim stra As String, strw As String, strx As String, i As Long Dim tm As Long, t1 As Long, t2 As Long
'''' 以上程序在 Windows 98 Second Edition + Visual Basic 6 Professional Service Pack 5 下调试通过。 '''' 结果:非 Unicode API 的运行时间大概是 Unicode API 的 15 倍左右。
结束语
在 VB 中使用 Unicode API 能够显著提高应用程序用 API 处理字符串的效率。 用此方法唯一不足的是兼容性问题。不过,微软已经停止了继续开发 Windows 95 系列操作系统,意味着其以后推出的操作系统都将基于 Windows NT 技术,也意味着它们都将支持 Unicode 。 换句话说,使用 Unicode API 将成为一项大家都要掌握的技术(其实不应该叫“技术”,因为这很简单)。