CnPack Forum


 
Subject: 浅谈Delphi2009控件移植
rarnu (橙子)
灌水部部长
Rank: 8Rank: 8


UID 2689
Digest Posts 11
Credits 648
Posts 209
点点分 648
Reading Access 10
Registered 2006-10-2
Status Offline
Post at 2008-9-9 10:26  Profile | Site | Blog | P.M. 
浅谈Delphi2009控件移植

原文在我blog上,点击进入

QUOTE:
当Delphi支持了Unicode,它将会变成什么样子呢?
我的看法如下:
1. 开发变得复杂了,因为要更多的考虑编码问题
2. 绝大多数控件都需要修改,以使其能适应Delphi2009
3. 多国语言的软件得到了较好的支持

第一点和第二点,相信很多人都有体会了,原本在Delphi2007上通顺利编译通过的项目,放到Delphi2009上就要进行很大的改动。特别是API的调用,MessageBoxA改成MessageBoxW之类,会让原本简单的程序变得很复杂。
我在论坛上承接移植控件的项目时,已经有很深的体会。比如说 str: array[0..15] of Char,原本这个 str 是可以直接拿来用作PChar,但是现在就必须 PChar(string(str)),或许这有一点不方便,但是这对于Delphi2009来说,完全没有办法。因为它不可能放弃Ansi。

如果想不修改编码就在Delphi2009上编译Delphi2007的项目,可以使用 {$H+} 编译预处理,这将把字符串编码设为Ansi,而不是使用默认的Unicode。
当然了,这仅仅是针对一些简单的项目可以如此处理。对于复杂的控件,如DevExpress,RemObjects等等,用这一招完全无效,还是得老老实实的修改代码。由于编译器改动太大,使得一些原本能顺利使用的语法也需要重新考虑。类似于 Boolean(ArrStr[1]) := True; 这样的代码已经不被支持。

下面来说说修改控件的问题,主要是编码问题,已有一些总结如下:

1. 使用{$H+}来避免字符串解析为Unicode
2. 使用StrPCopy函数,来对Char数组赋值,ArrStr := str; 已经不再支持了
3. 使用PChar/PWideChar来生成字符串指针。
4. 对于Length(str)要特别小心,在Unicode的情况下,一个汉字的长度和一个英文字母的长度都是1,而Ansi情况下,一个汉字长度是2。
5. 数据相关的控件最麻烦,TDataSet被大幅修改,因此从TDataSet继承来的控件,大多数override的方法也需要同步修改
6. StrPas(@ArrStr[0])这种写法不被支持,应用Str: string; StrPas(PChar(Str)); 来代替
7. 转义在先不被支持,如上面说的Boolean(ArrStr[1]) := True; 这样的代码可修改为 ArrStr[1] := IfThen(True, #1, #0);
8. PropertyEditor中的字符串必须是Ansi的,不然会导致内存泄漏(不知正式版还有没有这个问题。。)
9. ISAPI 及一些特定的API没有W的形式,它们只允许使用Ansi,因此传入参数时,必须用PAnsiChar(AnsiString(Str))进行转换

一些新语法的问题,比如说HashMap,可以按Java的写法,修改成IMap<T,T>和THashMap<T,T>
诸如此类的不再多说,泛型的使用是必然的,也是必须的,当然这对于控件的相关修改会比较大,但是能使控件更完善。
另外,由于Delphi2009支持反射,以往用RTTI获取类成员的代码,如果为了精简,可以使用反射单元的相关成员来代替。不知有没有人测试过反射和 RTTI的率,个人感觉,反射比RTTI慢一些,但是反射的功能远远强于RTTI。因此,开发时要用哪个,还是按照实际情况来决定比较好。

再来谈谈第三点,它对多国语言的支持强化了,我们可以在一个软件里,用上我们能够想像到的任何一种语言,而且都可以正确的显示(虽然对于我来说,完全用不到英文以外的语言,但是还是要说一下的)。但是这种多语支持却做得并不尽人意。本地化向导可以帮助完成一部分事情,但是自己要做的事还是很多。而 TSiLang是第三方,并且收费的,虽然实现多语很方便,但是我相信会去购买的人也不多吧。
Delphi完全可以在多语方面再做得更好一些,还有个小小的bug,以色列文会乱码,不过中国的用户应该永远碰不到这问题了吧。





Rarnu
CnPack Interfacer
rarnu@cnpack.org
Top
Passion (LiuXiao)
管理员
Rank: 9Rank: 9Rank: 9


UID 359
Digest Posts 19
Credits 6756
Posts 3554
点点分 6756
Reading Access 102
Registered 2004-3-28
Status Offline
Post at 2008-9-9 10:50  Profile | Blog | P.M. 
{$H+}效果不大,并且对Char没影响,不太推荐使用。
Top
ilue
新警察
Rank: 1



UID 9539
Digest Posts 0
Credits 5
Posts 3
点点分 5
Reading Access 10
Registered 2007-4-5
Status Offline
Post at 2008-9-9 14:26  Profile | Blog | P.M. 


QUOTE:
……str: array[0..15] of Char,原本这个 str 是可以直接拿来用作PChar,但是现在就必须 PChar(string(str)),……

不知道指的是不是下面这个用法,例如:

QUOTE:
var
  str: array[0..15] of Char;
begin
  MessageBox(Handle, str, nil, MB_OK);
……

这个在12.0.3170.16989下试了一下,可以编译通过。
Top
rarnu (橙子)
灌水部部长
Rank: 8Rank: 8


UID 2689
Digest Posts 11
Credits 648
Posts 209
点点分 648
Reading Access 10
Registered 2006-10-2
Status Offline
Post at 2008-9-9 23:19  Profile | Site | Blog | P.M. 
版本真高。。我都还在3163.16897上打滚呢。。。




Rarnu
CnPack Interfacer
rarnu@cnpack.org
Top
gaoyanan (高亚男)
普通灌水员
Rank: 2



UID 39457
Digest Posts 0
Credits 62
Posts 22
点点分 62
Reading Access 10
Registered 2008-4-1
Status Offline
Post at 2008-9-25 16:11  Profile | Blog | P.M.  | QQ
1.
var
  wsTitle, wsInfo: WideString;

  wsTitle := Application.Title;
  wsInfo := 'WideString 字符串测试';
  MessageBoxW(self.Handle, @wsInfo[1], @wsTitle[1], MB_OK or MB_ICONINFORMATION);
==============================================================
2.
var
  wsTitle, wsInfo: string;
  wsTitle := Application.Title;
  wsInfo := 'string 字符串测试';
  MessageBoxW(self.Handle, @wsInfo[1], @wsTitle[1], MB_OK or MB_ICONINFORMATION);
==============================================================
3.
不使用sizeOf做善后的程序员,不是一个扎实的程序员,就像依赖.net去维护资源的程序员一样。
var
  str, str1: array[0..100] of Char;
  wsTitle, wsInfo: string;
begin
  wsTitle := Application.Title;
  str := 'array Char 常量字符串测试';
  MessageBoxW(self.Handle, @str[0], @wsTitle[1], MB_OK or MB_ICONINFORMATION);

  wsTitle := 'array Char 字符串测试';
  wsInfo := Format('字符串长度%d,字符串空间长度%d。', [Length(wsTitle), Length(wsTitle) * SizeOf(wsTitle[1])]);
  StrPCopy(str1, wsInfo);
  MessageBoxW(self.Handle, @str1[0], @wsTitle[1], MB_OK or MB_ICONINFORMATION);
==============================================================
4.
function StrPas(const Str: PAnsiChar): AnsiString;
begin
  Result := Str;
end;

function StrPas(const Str: PWideChar): UnicodeString;
begin
  Result := Str;
end;

实在没有想到StrPas有什么用,完全可以
var
  str, str1: array[0..100] of Char;
  wsTitle, wsInfo: string;

  wsInfo := str1;
  wsInfo := str1 + '===';

6.不支持左转译,可以依赖右转译。我想这是考虑系统安全吧。
var
  ArrStr: array[0..100] of Char;
  tmp: Integer;
begin
  ArrStr[0] := Char($35);
  ArrStr[1] := Char(False);
  TButton(Sender).Caption := ArrStr;
Top
 




All times are GMT++8, the time now is 2024-4-24 21:10

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.021861 second(s), 7 queries , Gzip enabled

Clear Cookies - Contact Us - CnPack Website - Archiver - WAP