下面两个问题一直困扰着我这个处于第1层的菜鸟:1、为什么卡巴斯基KIS2009简体中文版安装在繁体XP下能正常显示简体中文,而瑞星、金山等则是乱码?2、为什么简体的MS Word或Firefox能显示繁体中文(特指Big5编码)的内容?处于1层以上的程序员(见《程序员》6月杂志周伟明的《程序员的十层楼》)肯定已经笑出来了,请略过剩下的内容。。。
这么说吧,如果想实现一个可以在简体中文系统中显示繁体中文的“记事本”,C++ Builder2009中如何实现?很多人(包括我)在没有了解各种字符编码以前,想当然地觉得既然支持Unicode了,那么直接使用TMemo的LoadFromFile方法直接load一个繁体中文的文档就能显示了。因为支持Unicode了嘛,Unicode就是在任何系统都能显示正常。好像很对,先试一下,初探嘛。
一、不变的“简体中文”版
既然支持Unicode,搞一个Form,放一个Button在上面,
Caption先不要去动,用程序去修改:
Form1->Caption = "简体中文";
Button1->Caption = "汉字";
简体XP下显示正常,可繁体XP下就显示乱码了。不是说支持Unicode了吗?跟踪调试一下:
简体XP下,“汉字”的“汉”编码是0x6C49,而繁体XP下,“汉”的编码变成了0x7296。我们知道“汉”在Uunicode编码中是0x6C49,说明简体XP下是正确的,而繁体XP下就不正确了。为什么会有这样的情况发生?把断点设置在“Button1->Caption = "汉字";”这一句,再用F7一直跟踪。原来是CB2009在把“汉字”赋值给Button1->Caption前,先进行了Ansi到Unicode的转换,恰恰问题就在CB2009使用的这个函数:InternalUStrFromPCharLen(Dest, Source, Length, DefaultSystemCodePage);函数在实现过程中获取了系统默认的CodePage(http://www.cppblog.com/shenhuafeng/archive/2007/04/05/21336.html),而简体XP和繁体XP的CodePage不一样(一个为936,一个为950)导致在转换到UNICODE的时候结果不一致,也就导致到繁体XP下显示为乱码。如何解决呢?在CB2009的帮助“Unicode in RAD Studio”一章中的“Issues(问题)”节中提到:运用“U”这个标量(一个宏,与VC++中的“L”类似)将ANSI字符常量强制识别为Unicode。这个过程是在编译时就已经完成,编译的时候是在简体XP下,所以程序运行时内存中存储的“汉字”Unicode是正确的。为了证实,将代码变为Button1->Caption = U"汉字";,再用F7跟踪。结果是程序一运行到这,就马上用UnicodeSetLength(var dst: UnicodeString; len: Integer);(注意dst的数据类型)来初始化一个UnicodeString类,等着给TButton赋值(TControl.SetText)了。
现在终于明白,不变的“简体中文”其实是不变的Unicode编码,已经不是我们的GB了。那么CB2009中的UnicodeString默认的CodePage是啥?调用UnicodeString.CodePage()就知道了——1200。
二、正确显示“繁体中文”
简体XP下显示繁体好像都很容易:用IE、Firefox浏览繁体网站,用MS Word打开繁体内容doc文档等。如何用CB2009也实现相应功能?先试试用Memo控件来Load一个繁体文本看看:
结果肯定是乱码,繁体XP下运行这个程序是能正常显示的。Memo控件中的每一行其实都是UnicodeString(属性Lines是TStrings类的对象),而繁体内容的TXT文本按ANSI保存,在Memo载入文件的时候做了一个ANSI到Unicode的转换。有了之前的跟踪结果,可以想象CB2009是获取了系统的默认CodePage(936)而导致繁体不能正确转换为UTF-16。那么我们让CB2009重新进行CodePage950的转换就应该可以正确显示了。
有个函数在前面跟踪源码的时候出现过——MultiByteToWideChar,看名字很容易理解它的作用是把多字节转为宽字符,CB2009应该是利用了这个函数将ANSI进行了转换,当然CB2009是用的简体系统默认的CodePage。转换应该可逆,那么应该有WideCharToMultiByte。实现它看看:
“载入文件”的Click事件实现如下:
运行一下看看:
好像自己的两个问题有了答案,但是总觉得第二个问题的方法效率低下,毕竟又转了一道。肯定还有更好的方法,当然,在没有找到好的办法前,我们这些菜鸟用用这种方法也是可以的。毕竟成长的过程是痛苦的。
此文章来自Tuuzed(土仔)作者