王朝网络
分享
 
 
 

VCL中TStrings的重大BUG-不支持Unicode

王朝vc·作者佚名  2006-01-08
宽屏版  字体: |||超大  

好久没有来csdn了,最近主要忙着项目开发,这么旧没有来,想想不能空手而来,所以带来了一篇文章,也是我在项目开发中遇到的问题,希望大家会喜欢。

Unicode已经成为Windows字符的主要编码方式,我想这也是大势所趋,现在软件越来越倾向国际化,而国际化主要的编码方式就是Unicode,不管是单字节英文字符,还是双字节汉字,在Unicode编码格式下都能正常显示。在Windows2000中大到Word,小到Notepad,都能很好的显示Unicode格式的文本文件。可是在我最近的项目中却发现VCL中的TMemo类不支持它,例如如下16进制显示的Unicode文本文件

66 00 67 00 68 00 69 00

但是在C++ builder6中的TMemo控件中则显示为:

在WindowsXP自带的Notepad中显示为:

除了把第一个字符显示出来,其他的字符都被忽略了,这在设计应用中是绝对不允许的,究其原因,原来是TMemo类的Lines属性不支持Unicode,Lines属性是TStings类,TMemo是通过TStrings的LoadFormFile方法代开文件并显示的,在VCL源代码中,我们可以找到如下函数

procedure TStrings.LoadFromFile(const FileName: string);

var

Stream: TStream;

begin

Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);

try

LoadFromStream(Stream);

finally

Stream.Free;

end;

end;

procedure TStrings.LoadFromStream(Stream: TStream);

var

Size: Integer;

S: string;

begin

BeginUpdate;

try

Size := Stream.Size - Stream.Position;

SetString(S, nil, Size);

Stream.Read(Pointer(S)^, Size);

SetTextStr(S);

finally

EndUpdate;

end;

end;

最后来到SetTextStr函数,由于这个函数的处理,使得Unicode被忽略了

procedure TStrings.SetTextStr(const Value: string);

var

P, Start: PChar;

S: string;

begin

BeginUpdate;

try

Clear;

P := Pointer(Value);

if P <> nil then

while P^ <> #0 do

begin

Start := P;

while not (P^ in [#0, #10, #13]) do Inc(P);

SetString(S, Start, P - Start);

Add(S);

if P^ = #13 then Inc(P);

if P^ = #10 then Inc(P);

end;

finally

EndUpdate;

end;

end;

以上代码片断我们可以清楚的看出Unicode是如何被忽略了,对于Unicode,它的编码方式是不管单字节还是双字节都是都是以双字节编码,单字节的英文则以0来补高位,但是很可惜,在以上函数中只要遇到0就退出了,所以在上面的例子中我们看到了‘f’这唯一的幸存者。

原因找到了,解决起来就倒是很容易,在判断字符串结束时不要以0来定界,而是实际的字符长度,这样就可以解决了,如下代码:

Clear;

P := Pointer(S);

if P <> nil then

begin

iPos := 0;

while (iPos < Size) do // (P^ <> #0) do

begin

Start := P;

while not (P^ in [#0, #10, #13]) do

begin

Inc(P);

Inc(iPos);

end;

SetString(S1, Start, P - Start);

Add(S1);

if (P^ = #13) then

begin

Inc(P);

Inc(iPos);

end;

if (P^ = #10) then

begin

Inc(P);

Inc(iPos);

end;

if (P^ = #0) then

begin

Inc(P);

Inc(iPos);

end;

end;

end;

finally

EndUpdate;

end;

end;

这样TStrings就能很好的支持Unicode字符集了。

写在最后:

其实在C++ Builder中对Unicode支持的还是很好的,VCL提供了WideString类封装了w_char*,而且还提供很多有用的方法用于Ansi与Unicode的相互转换,可能是TMemo太老了,它还来不及改正,说道太老了,VCL里很多控件都应该升级了,比如TRichEdit还是用的Richedit1.0,VCL的界面外观还不能应用XP的外观。

Borland公司的产品推出速度却是“惊人”,很多都还没有用过Delphi6,Delphi7就快要出来了,Borland公司只是在技术上推出新产品,但在服务上却始终不见前进,在这点上Borland要多学习Microsoft,做一个产品要很踏实,升级太平凡会显得“落后的”,记得以前Borland C++ 就是因为过快的发布,而没有足够的测试,导致出现很多Bug,很多用户转向了Microsoft的Visual C++,要不是Delphi力挽狂澜,Borland早就Game Over了,希望Borland不要重蹈覆辙,相信很多和我一样的Borland忠实用户都不希望看到这样。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有