之前,我负责一个VB6编写的办公自动化系统,要求能在运行时,支持在不同语言间切换(英文,中文,日文,德文,法文和西班牙文);实质就是实现一个VB6的MUI程序.
这个需要的困难在于VB6显示文本的标准控件(Label,Textbox等)不支持Unicode;但字符串在其内部是按Unicode保存的,也就是说VB6本身是支持Unicode的.
VB6中,标准控件显示字符串的过程如下:
1) 标准控件先将Unicode字符串转换成ANSI字符串;
2) 标准控件尝试将ANSI字符串转换成其Font.Charset属性中指定的字符集格式的字符串;如果转换失败,则显示为问号(?).
具体可参照:Display Unicode Strings in Visual Basic 6.0.
因此,实现MUI程序的思路有两种:
1) 将标准控件替换为能支持Unicode的控件;
2) 将资源文件中不同字符集的文本,转换为ANSI格式,提供给标准控件使用;
第1)种方式可用 Forms 2.0 (fm20.dll);
第2)种方式,我在网上找到两篇文章,但各有不足:
a) Auto-Detect Language and Display Unicode in VB6 TextBox and Label Controls;
ChilkatCharset2控件需购买,具对日文的一些标点符号(如全角句号)不支持.
b) How To Convert from ANSI to Unicode & Unicode to ANSI for OLE
没有测试成功.
下面,着重介绍我自己认为比较成功的实现,它使用了ADODB.Stream(msado25.tlb);其实现思路如下:
1) 将程序中用到的文本保存为Unicode格式的资源文件中;
之所以将资源文本保存为双字节的Unicode格式,而非Utf8或Utf7格式,可省去从其它格式向VB6支持的Unicode格式转换过程.
2) 将显示文本的标准控件的Font.Charset,设置为程序要显示语言所对应的字符集,并设置一种支持这种字符集的字体到Font.Name属性;
代码
1
If
g_Str.NumJapanese
>
0
Then
2
charset
=
"
Shift_JIS
"
3
Text1.Font.Name
=
"
MS UI Gothic
"
4
Text1.Font.charset
=
128
5
6
ElseIf
g_Str.NumKorean
>
0
Then
7
charset
=
"
ks_c_5601-1987
"
8
Text1.Font.Name
=
"
GulimChe
"
9
Text1.Font.charset
=
129
10
11
ElseIf
g_Str.NumCentralEuro
>
0
Then
12
charset
=
"
windows-1250
"
13
Text1.Font.Name
=
"
Arial
"
14
Text1.Font.charset
=
238
15
16
ElseIf
g_Str.NumArabic
>
0
Then
17
charset
=
"
windows-1256
"
18
Text1.Font.Name
=
"
Traditional Arabic
"
19
Text1.Font.charset
=
178
20
21
ElseIf
g_Str.NumHebrew
>
0
Then
22
charset
=
"
windows-1255
"
23
Text1.Font.Name
=
"
David
"
24
Text1.Font.charset
=
177
25
26
ElseIf
g_Str.NumCyrillic
>
0
Then
27
charset
=
"
windows-1251
"
28
Text1.Font.Name
=
"
Arial
"
29
Text1.Font.charset
=
204
30
31
ElseIf
g_Str.NumGreek
>
0
Then
32
charset
=
"
windows-1253
"
33
Text1.Font.Name
=
"
Arial
"
34
Text1.Font.charset
=
161
35
36
ElseIf
g_Str.NumThai
>
0
Then
37
charset
=
"
windows-874
"
38
Text1.Font.Name
=
"
Angsana New
"
39
Text1.Font.charset
=
222
40
41
ElseIf
g_Str.NumChinese
>
0
Then
42
charset
=
"
gb2312
"
43
Text1.Font.Name
=
"
SimSun
"
44
Text1.Font.charset
=
134
45
'
An alternative is to use Big5:
46
'
Text1.Font.Name = "MingLiu"
47
'
charset = "big5"
48
'
fontCh = 136
49
50
Else
51
charset
=
"
windows-1252
"
52
Text1.Font.charset
=
0
53
Text1.Font.Name
=
"
Arial
"
54
End
If
3) 根据要显示的语言,利用ADODB.Stream将资源文件中Unicode格式保存的字符串转换成操作系统的区域语言(Locale)支持字符集的字符串;
代码
1
'
调用API来获取操作系统默认的区域语言设置(LocaleID)
2
Private
Declare
Function
GetSystemDefaultLCID
Lib
"
kernel32
"
()
As
Long
3
4
'
将Unicode字符串,转换为指定字符集的字节数组;
5
'
用于转换用资源文件中读取的文本;
6
Public
Function
ConvertStringToBytes(
ByRef
strText
As
String
, charset
As
String
)
As
Byte
()
7
8
Dim
objStream
As
ADODB.Stream
9
Dim
data()
As
Byte
10
11
'
init stream
12
Set
objStream
=
New
ADODB.Stream
13
objStream.charset
=
charset
14
objStream.Mode
=
adModeReadWrite
15
objStream.Type
=
adTypeText
16
objStream.Open
17
18
'
write bytes into stream
19
objStream.WriteText strText
20
objStream.Flush
21
22
'
rewind stream and read text
23
objStream.Position
=
0
24
objStream.Type
=
adTypeBinary
25
'
objStream.Read 3 ' skip first 3 bytes as this is the utf-8 marker
26
data
=
objStream.Read()
27
28
'
close up and return
29
objStream.Close
30
ConvertStringToUtf8Bytes
=
data
31
32
End Function
33
'
转换为指定字符集的字节数组,转换为ANSI(即LocaleID)对应的字符集的字符串;
34
'
用于将ConvertStringToBytes()返回的字节数组转换为GetCharset()字符集的字符串.
35
Public
Function
ConvertBytesToString(
ByRef
data()
As
Byte
, charset
As
String
)
As
String
36
37
Dim
objStream
As
ADODB.Stream
38
Dim
strTmp
As
String
39
40
41
'
init stream
42
Set
objStream
=
New
ADODB.Stream
43
objStream.charset
=
charset
44
objStream.Mode
=
adModeReadWrite
45
objStream.Type
=
adTypeBinary
46
objStream.Open
47
48
'
write bytes into stream
49
objStream.Write data
50
objStream.Flush
51
52
'
rewind stream and read text
53
objStream.Position
=
0
54
objStream.Type
=
adTypeText
55
strTmp
=
objStream.ReadText
56
57
'
close up and return
58
objStream.Close
59
ConvertUtf8BytesToString
=
strTmp
60
61
End Function
62
63
'
获取操作系统默认区域语言对应的字符集
64
Public
Function
GetCharset()
As
String
65
Dim
localeId
As
Long
66
Dim
charset
As
String
67
68
'
获取操作系统的LocaleId
69
localeId
=
GetSystemDefaultLCID()
70
71
Select
Case
localeId
72
73
Case
1033
74
charset
=
"
windows-1252
"
75
Case
2052
76
charset
=
"
gb2312
"
77
Case
1041
78
charset
=
"
Shift_JIS
"
79
Case
Else
80
charset
=
"
windows-1252
"
81
End
Select
82
83
GetCharset
=
charset
84
End Function
85
86
'
显示资源文本中的文本
87
Private
Sub
DisplayText(filename
As
String
)
88
89
'
保存资源文本中的文本的变量
90
Dim
textBytes
As
Variant
91
Dim
f
As
New
FileSystemObject
92
Dim
fs
As
TextStream
93
'
将Unicode文本读取到变量中
94
Set
fs
=
f.OpenTextFile(filename, ForReading,
False
, TristateTrue)
95
96
Do
While
Not
fs.AtEndOfStream
97
textBytes
=
fs.ReadAll
98
Loop
99
100
fs.Close
101
102
'
Convert to a Unicode string:
103
Dim
s
As
String
104
s
=
textBytes
105
Dim
t
As
Long
106
'
CkString是免费的第三方组件,可自动判定一个字符串所对应的字符集
107
'
下载地址:http://www.chilkatsoft.com/download/CkString.zip
108
Dim
g_Str
As
New
CkString
109
g_Str.Str
=
s
110
111
'
获取资源文本所代表的字符集名称,设置对应的字体和字符集到textbox上
112
Dim
charset
As
String
113
If
g_Str.NumJapanese
>
0
Then
'
日文
114
charset
=
"
Shift_JIS
"
115
Text1.Font.Name
=
"
MS UI Gothic
"
116
Text1.Font.charset
=
128
117
118
ElseIf
g_Str.NumKorean
>
0
Then
'
韩语
119
charset
=
"
ks_c_5601-1987
"
120
Text1.Font.Name
=
"
GulimChe
"
121
Text1.Font.charset
=
129
122
123
ElseIf
g_Str.NumCentralEuro
>
0
Then
'
中欧语言
124
charset
=
"
windows-1250
"
125
Text1.Font.Name
=
"
Arial
"
126
Text1.Font.charset
=
238
127
128
ElseIf
g_Str.NumArabic
>
0
Then
'
阿拉伯语
129
charset
=
"
windows-1256
"
130
Text1.Font.Name
=
"
Traditional Arabic
"
131
Text1.Font.charset
=
178
132
ElseIf
g_Str.NumGreek
>
0
Then
'
希腊语
133
charset
=
"
windows-1253
"
134
Text1.Font.Name
=
"
Arial
"
135
Text1.Font.charset
=
161
136
ElseIf
g_Str.NumThai
>
0
Then
'
泰语
137
charset
=
"
windows-874
"
138
Text1.Font.Name
=
"
Angsana New
"
139
Text1.Font.charset
=
222
140
ElseIf
g_Str.NumChinese
>
0
Then
'
中文
141
charset
=
"
gb2312
"
142
Text1.Font.Name
=
"
SimSun
"
143
Text1.Font.charset
=
134
144
'
繁体则使用Big5:
145
'
Text1.Font.Name = "MingLiu"
146
'
charset = "big5"
147
'
Text1.Font.charset = 136
148
Else
'
默认值
149
charset
=
"
windows-1252
"
150
Text1.Font.charset
=
0
151
Text1.Font.Name
=
"
Arial
"
152
End
If
153
154
Dim
bytes()
As
Byte
155
Dim
g_OSCharset
As
String
156
'
获取操作系统默认语言对应的字符集
157
g_OSCharset
=
GetCharset()
158
'
先将Unicode资源文本转换成对应的字节数组;
159
bytes
=
ConvertStringToBytes(s, charset)
160
'
将字节数组转换成ANSI(即默认字符集)对应的字符串
161
vbstr2
=
ConvertBytesToString(bytes, g_OSCharset)
162
'
设置字符串到VB6的标准控件中
163
Me
.Text1.Text
=
vbstr2
164
End Sub
参考:
1) 字符集列表及LocaleId列表(http://www.livio.net/main/charset.asp)