我最初怀疑问题在于该函数期望Single
和 Delphi 将您的浮点数转换为其他内容。当我在调试器中对其进行跟踪时,我发现传递给的变体Invoke
具有VType
ofvarCurrency
且货币值为2
. 我不确定这是怎么发生的!
正如我在回答这个问题时发现的那样,将单精度浮点数转换为变体非常棘手。我最初怀疑您可以使用我在那里提出的解决方案来解决您的问题。
function VarFromSingle(const Value: Single): Variant;
begin
VarClear(Result);
TVarData(Result).VSingle := Value;
TVarData(Result).VType := varSingle;
end;
....
w := CreateOleObject('Word.Application');
w.Visible := true;
Writeln(w.CentimetersToPoints(VarFromSingle(2.0)));
但这也以同样的方式失败了,原因我还不明白。
像你一样,我尝试使用IDispatch.Invoke
. 这就是我想出的:
program SO16279098;
{$APPTYPE CONSOLE}
uses
SysUtils, Variants, Windows, ComObj, ActiveX;
function VarFromSingle(const Value: Single): Variant;
begin
VarClear(Result);
TVarData(Result).VSingle := Value;
TVarData(Result).VType := varSingle;
end;
var
WordApp: Variant;
param: Variant;
retval: HRESULT;
disp: IDispatch;
Params: TDispParams;
result: Variant;
begin
try
CoInitialize(nil);
WordApp := CreateOleObject('Word.Application');
disp := IDispatch(WordApp);
param := VarFromSingle(2.0);
Params := Default(TDispParams);
Params.cArgs := 1;
Params.rgvarg := @param;
retval := disp.Invoke(
371,//CentimetersToPoints
GUID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
Params,
@Result,
nil,
nil
);
// retval = E_FAIL
Params := Default(TDispParams);
retval := disp.Invoke(
404,//ProductCode
GUID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
Params,
@Result,
nil,
nil
);
// retval = S_OK
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
我不能这样调用CentimetersToPoints
,但可以调用ProductCode
函数。
要添加到您的成功/失败指标集合中,当我CentimetersToPoints
使用我调用函数时,PowerShell
我取得了成功。当我使用 Python 调用时win32com.client
,我得到E_FAIL
.
显然我们缺少一些特殊的魔法成分。似乎所有的 MS 工具都知道这个魔法。
我得出结论,不可能CentimetersToPoints
使用 Delphi 中实现的变体调度来调用。它不知道魔法,不管魔法是什么。
显然可以呼吁Invoke
并IDispatch
取得成功。我们可以看出这一点,因为其他环境可以做到这一点。所以,我还不知道缺失的魔法是什么。
如果您可以使用早期绑定的 COM,那么您可以回避这个问题:
Writeln((IDispatch(w) as WordApplication).CentimetersToPoints(2.0));
好的,在Hans Passant的帮助下,我有一些 Delphi 代码可以调用这个函数:
program SO16279098;
{$APPTYPE CONSOLE}
uses
SysUtils, Variants, Windows, ComObj, ActiveX;
function VarFromSingle(const Value: Single): Variant;
begin
VarClear(Result);
TVarData(Result).VSingle := Value;
TVarData(Result).VType := varSingle;
end;
var
WordApp: Variant;
param: Variant;
retval: HRESULT;
disp: IDispatch;
Params: TDispParams;
result: Variant;
begin
try
CoInitialize(nil);
WordApp := CreateOleObject('Word.Application');
disp := IDispatch(WordApp);
param := VarFromSingle(2.0);
Params := Default(TDispParams);
Params.cArgs := 1;
Params.rgvarg := @param;
retval := disp.Invoke(
371,//CentimetersToPoints
GUID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD or DISPATCH_PROPERTYGET,
Params,
@Result,
nil,
nil
);
Writeln(Result);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
由于未知原因,您需要包括DISPATCH_PROPERTYGET
以及DISPATCH_METHOD
.
我问的问题可能使这个问题重复了。所以,我投票结束。