升级到 DELPHI 6 !
当你载入一个 Delphi5 或早先的工程到 Delphi 6 中时,它被自动更新。下面的主题描述可能会潜在影响现存 Delphi 工程的变化。
IDE 问题
自动包名更新
兼容性问题
关于你需要集成到你的应用程序中的额外特性的信息,也请参考 Delphi 新特性 。
IDE问题
当你第一次在 Delphi 6 中打开你的工程时,它看起来和在以前版本的 Delphi 中的不一样。IDE 有了很多变化,包括窗口布局和组件面板的改变。关于这些变化的更完整的综述,参见 DELPHI 新特性 中的 新的IDE 特性 部分。
自动包名更新
如同在以前的 Delphi 升级里一样, 许多包的名称已经改变了。比如, "vclide50" 现在是 "vclide60"。过去版本的 Delphi 执行自动的包名更新,这一版也不例外。然而更新机制已经改变了,它现在依赖于一个已改变文件的列表(可以在 Bin 目录里的 Delphi.upg 文件中发现),而不是简单地改变后缀。过去,当 Delphi 检测到可能和包名变化相关的错误时,它为过时的后缀搜索包名并自动以正确的后缀替换它们。比如, Delphi 5 会自动更新对 "package40" 的引用(如果存在这样一个包在话),因此它替代性地去读 "package50"。Delphi 6 通过搜索一个过时包名的列表,并如列表指示的那样替换它们,来执行这个任务。列表包含在文件 Delphi.upg 中,你可在 Bin 目录中发现它。
用户也可以使用一个文本编辑器(包括 Delphi IDE 的编辑器)检查和改变文件的内容。这对于组件设计者来说会是有用的特性,他们可能需要为 Delphi 6 修改他们的组件并将组件放在和以前用过的不一样的包中。
兼容性问题
下面是会影响你的 Delphi 应用程序的一般兼容性问题:
受 VCL 层次结构改变影响的数据提供者及客户数据集事件
实现默认数据库登录对话框需要改变代码
潜在的二进制表单文件不兼容性
可写常量的变化
有序类型的一元负化
被重命名的 DsgnIntf 及其相关变化
组件编辑器的变化
TDesignWindow 的变化
VCL 包的变化
OpenGL 接口单元移到 rtl.dcp 中
某些类型从 HTTPApp.pas 移动到 HTTPProd.pas 中
Search 单元被删除,SearchBuf 例程被移动和改变
升级到 DELPHI 6 !
受VCL层次结构改变影响的数据提供者及客户数据集事件
TCustomClientDataSet 的引入需要改变 Delphi 5 和更早的代码中的事件处理器。
下列五个类型中的六个事件被DBCLIENT.PAS的变化影响。它们是:
类型
事件/变化
TResolverErrorEvent
影响数据提供者的OnUpDateError事件
TBeforeUpdateRecordEvent
影响数据提供者的BeforeUpdateRecord事件
TAfterUpdateRecordEvent
影响数据提供者的AfterUpdateRecord事件
TProviderDataEvent
影响数据提供者的OnGetData和 OnUpdateData事件
TReconcileErrorEvent
影响客户数据集的OnReconcileError事件
在使用上述事件的事件处理器内,你必须用 TCustomClientDataSet 替代 TClientDataSet。
实现默认数据库登录对话框需要改变代码
以前,设定一个连接组件(诸如 TDatabase,TADOConnection 或 TDCOMConnection)的 LoginPrompt 属性导致一个默认登陆对话框出现。现在情况这不再是这样,除非你添加 DBLogDlg 到你的 uses 子句中。依赖于默认登陆对话框的应用程序必须被编辑以添加 DBLogDlg 到 uses 子句,否则它们将不会提示输入用户名和密码。
潜在的二进制表单文件不兼容性
过去,较新版本的 Delphi 二进制表单文件(或 DFM 文件)可以被较老版本读出。在 Delphi 6 中不再是这样;Delphi 6 执行内部字符串流的方式使得某些二进制表单文件会被不正确地读出。过去,流采用本地特定字符集执行。现在流采用的字符集为 UTF-8 。因此,如果在二进制表单文件中有 ASCII 码大于 127 的字符(诸如Delphi 6 中的版权符号),那么该文件将不能被较老版本的 Delphi 读出。
如果你想要在旧版本 Delphi 里使用一个 Delphi 6 表单文件(包括导入到 Delphi 6 中的和用 Delphi 6 修改过的旧的表单文件),该文件应该被保存为文本格式而不是二进制格式。
可写常量的变化
$WRITEABLECONST 编译器开关(也就是 $J )现在有一个默认的状态为 OFF ,这将阻止 Delphi 工程具有可写常量。可写常量指的是将类型常量作为运行时可修改的变量来使用。这里是一个例子:
const
foo: Integer = 12;
begin
foo := 14;
end.
在以前版本的 Delphi 里,这是一个可接受的思维产物;常量实际不是常量。现在,当 $WRITEABLECONST 关闭时,这个代码将产生一个编译错误:就在 begin..end 块里对 foo 变量赋值时。为了修正它,只要把常量声明改为变量声明即可。
你可能有这种代码:使用类型常量作为初始化的局部变量,而它又有着全局存续期。
就象这样:
procedure MyProc;
const
somedata: Integer = 12;
begin
Inc(somedata, 3);
end;
你将需要将局部常量移动到过程外面,并以本来面目(一个全局变量)声明它。在做出这个改变后,上面的代码段变为:
var
somedata: Integer = 12;
procedure MyProc;
begin
Inc(somedata, 3);
end;
很大程度上依赖于类型常量这种怪异用法的代码(诸如 ActiveX 控件封装生成器)可以在源文件插入一个{$WRITEABLECONST ON} 指令里来快速修正。这种习惯在 RTL,VCL,CLX和 DB 源代码里被禁止,并且在 IDE 源代码里不鼓励这种习惯。但是对于处在边缘地带的单元,诸如 ActiveX 控件封装器,这却是可接受的。
总的来说,你应该注意词组“可写常量”是一种“矛盾修饰法”。 以前版本的 Delphi 默认地允许它们,以保持和较老 16 位编译器的兼容性。然而对于大多数 Delphi 开发者这已经不重要了。因此请使用良好的编程习惯,避免使用“可写常量”。
1 2 3
升级到 DELPHI 6 !
有序类型的一元负化
过去,Delphi 使用 32 位操作处理有序类型数字的一元负化,这可能会导致某些奇怪的结果。这里是使用一元负化的一个代码例子:
var
c: Cardinal;
i: Int64;
begin
c := 4294967294;
i := -c;
WriteLn(i);
end;
在以前版本的 Delphi 中,被显示的 i 的值会是 2 。对于这个情况显然这是错误的行为。在 Delphi 6 中,一元负化在提升有序类型为一个 64 位有符号类型后再处理,这样最终显示的 i 值为 -4294967294 。
很可能现存的代码会依赖于不正确的一元负化行为。Delphi 用户应该意识到这个新的行为。你花时间去为有序变量的一元负化检查你的代码实例并确保你的应用程序适当地响应新行为是值得的。
被重命名的 DsgnIntf 及其相关变化
在你的工程中对 DsgnIntf 的引用应该被改变为新的 Delphi 6 名称,DesignIntf。你也许也会需要添加DesignEditors,VCLEditors 和 RTLConsts 到你的 uses 子句。你也将需要添加 designide 到你的包的requires 列表。对 dsnide50 的引用可能也应该变为 designide,如果那没有被 Delphi 自动改变的话。
任何使用 IDesigner 的运行时包需要使用 IDesignerHook 来避免运行时需要 designide。在运行时代码里,IDesignerHook 应该足够。设计时代码可以使用 IDesigner,但是应该使用类似下面的代码来从 IDesignerHook 的一个实例获得实际 IDesigner 接口。
var
RealDesigner: IDesigner;
...
SomeDesignerHook.QueryInterface(IDesigner,RealDesigner);
...
IDesignerHook 仅要求 Classes 和 Forms 单元可用。IDesigner 需要 DesignIntf,后者包含了许多其它包,而其中一些可能不是可重新分发的。
组件编辑器的变化
类 TComponentEditor 在 Delphi 6 里有不同的祖先系。在 Delphi 5 里,它从 TInterfacedObject 继承;现在它从一个新的类 TBaseComponentEditor 继承。类 TComponentEditorClass 现在也是 TBaseComponentEditor 而不是 TComponentEditor 的一个类。这些层次体系上的变化会要求你修改你的旧的 Delphi 工程。
TDesignWindow 的变化
关于类 TDesignWindow,存在大量变化。它已经被移动到 DesignWindows 单元,并且它的 FormClosed 方法已经被 DesignerClosed 替代。过去,你可以通过使用 AForm 参数在 FormClosed 里获得对表单的访问。现在,在 DesignerClosed 里,你必须使用 Designer 的 Root 属性来访问表单。
在 FormClosed 里,你可以通过调用 TDesignerSelectionList.Create 或 TComponentList.Create 创建选择列表。为在 DesignerClosed 里创建选择列表,你必须使用一个 IDesignerSelections 接口。你可以使用CreateSelectionList 函数创建一个。
SelectionClosed 方法的参数也和 Delphi 5 里不一样。
VCL 包的变化
某些 VCL 相关的包的内容已经被重新分发到其它包。如果你在你的工程里引用 vcl50.dcp,你将需要将那些引用改变为指向其它单元,诸如 vcl.dcp 和 rtl.dcp。
OpenGL 接口单元移到 rtl.dcp 中
Borland OpenGL 接口单元(opengl.dcu)是 Delphi 5 Lib 文件夹里的独立单元。在 Delphi 6 中,它已经被集成到 rtl.dcp 里。对于移植到 Delphi 6 中的 Delphi 5 工程,这会导致某些问题。
这里有个例子。在一个 Delphi 5 工程里,通过放置同名的单元在你的工程路径的某个地方,你有可能做出一个工程特定的对 OpenGL 单元的覆盖。Delphi 6 中使用的同一方法也导致在使用 rtl.dcp 组件中出现许多名称冲突。现在需要名称上的改变。
某些类型从 HTTPApp.pas 移动到 HTTPProd.pas 中
HTTPApp 单元里的数个类型已经被移动到 HTTPProd 单元里。它们是 THTMLBgColor,THTMLAlign和THTMLVAlign。如果你的工程使用这些单元中的任何一个,你应当改变你的 uses 语句来指向 HTTPProd 而不是HTTPApp。
Search 单元被删除,SearchBuf 例程被移动和改变
单元 Search 不再存在于 Delphi 6 中。SearchBuf,这个在一个本文缓冲区内定位一个子字符串的例程,已经被移动到 StrUtils 单元;且它的参数已经变化了。最后的参数是一个 TStringSearchOptions 对象。如果你的工程因为编译器不能找到 Search 单元而不能编译,那么改变你的 uses 语句来包含 StrUtils 而不是Search。你也将需要检查你的 SearchBuf 调用以确保你的参数匹配新的语法。