我只是将Delphi 6中编写的一些旧代码升级到Delphi XE2。不幸的是,代码引用了Word97 COM对象来生成一些.doc文档。代码中有Word97的直接使用条款。
我必须保持生成的文档采用与旧版Crystal Report和另一个第三方应用程序使用相同的Word格式,该应用程序需要该文档的格式。
所以,问题。因为我在uses子句中使用Word97,所以编译器抱怨每当使用EmptyParam变量时,实际和正式var参数的类型必须相同。这直接来自Word97.pas源文件。这是因为现在将EmptyParam声明为函数而不是变量。
处理这个问题的最佳方法是什么?我应该将Delphi 6源文件(Word97.pas等)复制到我的本地目录中,直接将它们与System.Variants.pas一起添加到我的项目中,并将我的应用程序的编译器指令更改为包含EMPTYPARAM_VAR吗?我没有尝试过,但希望它会将EmptyParam声明为变量。或者也许有一个更简单的解决方案。
由于
修改
这里有更多的背景信息,即使我已经接受了答案,以备将来参考。这是代码示例(AddClaimsLetter是“应用程序”COM对象 - 即TWordApplication):
AddClaimsLetter.Documents.Open(Wordfile, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam);
在不改变任何内容的情况下,此处的EmptyParam参数在编译时失败,说明“E2033实际和正式var参数的类型必须相同”。
但是,因为我想保留Word97(在Delphi 6 Ent。安装文件夹中的OCX / Server中),我确实需要将.pas文件复制到我的本地项目文件中并声明一个已使用的变量EmptyParam(因为这些文件也试图编译,我得到了与上面相同的编译错误)。
所有现在都在工作,但我可能会与管理层讨论升级到此应用程序的Office的更高版本!
由于
答案 0 :(得分:15)
我快速解决问题的方法可能是声明OleVariant类型的局部变量,并为其分配函数EmptyParam的结果。
答案 1 :(得分:7)
对于每个var
参数,您应该添加一个用EmptyParam
调用填充的局部变量。
原因是所有var
参数都通过引用传递。如果在多个引用处传递相同的变量,则可能会遇到以下问题(使用整数简化)。
Before: VarParameter=-1
Before: A=-1
Before: B=-1
After: A=2
After: B=2
After: VarParameter=2
EAssertionFailed: Assertion failure
这是显示风险的代码:
program TheVarParameterRisk;
procedure AssignParameters(var A: Integer; var B: Integer);
begin
Writeln('Before: A=', A);
Writeln('Before: B=', B);
A := 1;
B := 2;
Writeln('After: A=', A);
Writeln('After: B=', B);
Assert(A = 1);
end;
var
VarParameter: Integer;
begin
try
VarParameter := -1;
try
Writeln('Before: VarParameter=', VarParameter);
AssignParameters(VarParameter, VarParameter);
finally
Writeln('After: VarParameter=', VarParameter);
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
您在AssignParameters
中看到Assert
失败,因为调用者将相同的引用传递给两个var
参数。
这正是EmptyParam
成为函数的原因:它永远不应该作为var
参数传递。
人们抱怨Delphi中的错误(例如here)导致覆盖EmptyParam
值。
现在EmptyParam
是一个函数,问题就解决了。当您需要将其作为var
参数传递时,请使用本地中间件。
注意:
EmptyParam
传递给var
参数,那么基本上你本身就有问题:var
参数意味着什么是将被更改,这意味着传递EmptyParam
(或具有相同内容的本地变量)阻止了更改。var
参数而不是const
参数),则导入的类型库具有错误的参数标志,或者(如果参数标记是好的)它是错误的(您应该在https://quality.embarcadero.com提交错误报告(这曾经是索引http://qc.embarcadero.com的搜索引擎,但已关闭; https://quality.embarcadero.com需要免费帐户搜索)。修改强>
你必须将EmptyParam
传递给var
参数的事实是一个非常强烈的提示,我认为被调用的函数可能会真正使用这些参数并且会失败。就像我的示例函数失败一样。 (是的,函数文档可能会引诱您使用多个EmptyParam
参数,实际上这些参数实际上并不是空的;我经常看到文档说A和实际函数执行B)。
答案 2 :(得分:1)
我是否应该将Delphi 6源文件(Word97.pas等)复制到我的本地目录中,直接将它们与System.Variants.pas一起添加到我的项目中,并将我的应用程序的编译器指令更改为包含EMPTYPARAM_VAR?我没有尝试过,但希望它会将EmptyParam声明为变量。
您可能在法律上允许将Word97.pas从较旧的Delphi复制到新版本,但是您需要“升级”它以使用新的编译器。您可能会面临更多问题,主要是因为Delphi XE2启用了Unicode而Delphi 6不支持。如果那个单位是我认为的那样(如上所述我在Delphi的3个版本中没有它我已经得到了方便和检查)那么它是OLE自动化Word的包装 - 也就是说,它充满了难以理解的系统没有实现的代码和许多方法声明。最后一点,没有实现的方法声明,使得非常难以改变:如果你改变某些东西并且它编译它并不意味着它是正确的 - 你只会在运行时找到它是否有效或者不
你应该做什么: