gpt4 book ai didi

delphi - 如何使用 TInterfacedObject 扩展现有接口(interface) IMessageFilter?

转载 作者:行者123 更新时间:2023-12-03 15:55:49 33 4
gpt4 key购买 nike

我想实现IOleMessageFilter,如下所述:

How to: Fix 'Application is Busy' and 'Call was Rejected By Callee' Errors

我找到了一个运行良好的 Delphi 实现:

`EOleException: Call was rejected by callee` while iterating through `Office.Interop.Word.Documents`

(请参阅答案中的更新#1)

实现如下所示:

type
TOleMessageFilter = class(TInterfacedObject, IMessageFilter)
public
// IMessageFilter
function HandleInComingCall(dwCallType: Longint; htaskCaller: HTask;
dwTickCount: Longint; lpInterfaceInfo: PInterfaceInfo): Longint;stdcall;
function RetryRejectedCall(htaskCallee: HTask; dwTickCount: Longint;
dwRejectType: Longint): Longint;stdcall;
function MessagePending(htaskCallee: HTask; dwTickCount: Longint;
dwPendingType: Longint): Longint;stdcall;

// TOleMessageFilter
procedure RegisterFilter;
procedure RevokeFilter;
end;

implementation

function TOleMessageFilter.HandleInComingCall(dwCallType: Integer; htaskCaller: HTask; dwTickCount: Integer; lpInterfaceInfo: PInterfaceInfo): Longint;
begin
Result := 0;
end;

function TOleMessageFilter.MessagePending(htaskCallee: HTask; dwTickCount, dwPendingType: Integer): Longint;
begin
Result := 2 //PENDINGMSG_WAITDEFPROCESS
end;

function TOleMessageFilter.RetryRejectedCall(htaskCallee: HTask; dwTickCount, dwRejectType: Integer): Longint;
begin
Result := -1;
if dwRejectType = 2 then
Result := 99;
end;

procedure TOleMessageFilter.RegisterFilter;
var
OldFilter: IMessageFilter;
NewFilter: IMessageFilter;
begin
OldFilter := nil;
NewFilter := TOleMessageFilter.Create as IMessageFilter;
CoRegisterMessageFilter(NewFilter,OldFilter);
end;

procedure TOleMessageFilter.RevokeFilter;
var
OldFilter: IMessageFilter;
NewFilter: IMessageFilter;
begin
OldFilter := nil;
NewFilter := nil;
CoRegisterMessageFilter(NewFilter,OldFilter);
end;

这个确切的 Delphi 代码可以在网络上的许多其他网站上找到。到目前为止,一切都很好。我只是将类名更改为 TOleMessageFilter 而不是 IOleMessageFilter

但是使用有点烦人。

var
Filter: TOleMessageFilter;

Filter := TOleMessageFilter.Create;
Filter.RegisterFilter;
...
Filter.RevokeFilter;
Filter.Free;

我想要的是,Filter 被声明为接口(interface),例如IOleMessageFilter

var
Filter: IOleMessageFilter;

Filter := TOleMessageFilter.Create as IOleMessageFilter;
Filter.RegisterFilter;
...
Filter.RevokeFilter;
Filter := nil;

并具有自动释放TInterfacedObject的优点。

如何创建一个新的 IOleMessageFilter,它“派生”自 IMessageFilter,但仍然具有新方法 RegisterFilter()RevokeFilter (),实现为 TOleMessageFilter = class(TInterfacedObject, IOleMessageFilter),并且仍然能够与需要 CoRegisterMessageFilter() 一起使用IMessageFilter(在 RegisterFilter() 方法中使用)?

我试图声明:

IOleMessageFilter = interface(IMessageFilter)
procedure RegisterFilter;
procedure RevokeFilter;
end;

TOleMessageFilter = class(TInterfacedObject, IOleMessageFilter)
...
end;

但是调用CoRegisterMessageFilter会抛出错误:

Interface not supported.

编辑:

我还尝试将 TOleMessageFilter 声明为:

TOleMessageFilter = class(TInterfacedObject, IMessageFilter, IOleMessageFilter)

这“似乎”有效,但我不确定这是正确的方法。

最佳答案

拆分两个接口(interface)并让 TOleMessageFilter 保留对实际消息过滤器的引用,作为奖励,您不必再调用 RegisterFilter 和 RevokeFilter,因为这将在构造函数/析构函数中完成:

program SO46913922;

{$APPTYPE CONSOLE}

{$R *.res}

uses
ActiveX,
Windows,
SysUtils;


type
IOleMessageFilter = interface
['{0ECA5DA7-F6C7-4D21-8FD3-872558F88CBE}']
procedure RegisterFilter;
procedure RevokeFilter;
end;

TMessageFilter = class(TInterfacedObject, IMessageFilter)
public
// IMessageFilter
function HandleInComingCall(dwCallType: Longint; htaskCaller: HTask;
dwTickCount: Longint; lpInterfaceInfo: PInterfaceInfo): Longint;stdcall;
function RetryRejectedCall(htaskCallee: HTask; dwTickCount: Longint;
dwRejectType: Longint): Longint;stdcall;
function MessagePending(htaskCallee: HTask; dwTickCount: Longint;
dwPendingType: Longint): Longint;stdcall;
end;

TOleMessageFilter = class(TInterfacedObject, IOleMessageFilter)
private
Filter : IMessageFilter;
procedure RegisterFilter;
procedure RevokeFilter;
public
constructor Create;
destructor Destroy; override;
end;


function TMessageFilter.HandleInComingCall(dwCallType: Integer; htaskCaller: HTask; dwTickCount: Integer; lpInterfaceInfo: PInterfaceInfo): Longint;
begin
Result := 0;
end;

function TMessageFilter.MessagePending(htaskCallee: HTask; dwTickCount, dwPendingType: Integer): Longint;
begin
Result := 2 //PENDINGMSG_WAITDEFPROCESS
end;

function TMessageFilter.RetryRejectedCall(htaskCallee: HTask; dwTickCount, dwRejectType: Integer): Longint;
begin
Result := -1;
if dwRejectType = 2 then
Result := 99;
end;

procedure TOleMessageFilter.RegisterFilter;
var
OldFilter: IMessageFilter;

begin
OldFilter := nil;
Filter := TMessageFilter.Create;
CoRegisterMessageFilter(Filter,OldFilter);
end;

procedure TOleMessageFilter.RevokeFilter;
var
OldFilter: IMessageFilter;
NewFilter: IMessageFilter;
begin
OldFilter := nil;
NewFilter := nil;
CoRegisterMessageFilter(NewFilter,OldFilter);
Filter := nil;
end;

constructor TOleMessageFilter.Create;
begin
RegisterFilter;
end;

destructor TOleMessageFilter.Destroy;
begin
RevokeFilter;
inherited;
end;

var
Filter : IOleMessageFilter;

begin
try
CoInitialize(nil);
Filter := TOleMessageFilter.Create;
Readln; // do something
Filter := nil;
finally
CoUninitialize();
end;
Readln;
end.

关于delphi - 如何使用 TInterfacedObject 扩展现有接口(interface) IMessageFilter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46913922/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com