如何使用 TInterfacedObject 扩展现有接口 IMessageFilter?
How to extend existing interface IMessageFilter with TInterfacedObject?
我想按照此处所述实施 IOleMessageFilter
:
How to: Fix 'Application is Busy' and 'Call was Rejected By Callee' Errors
我找到了一个运行良好的 Delphi 实现:
(请参阅答案中的更新 #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 代码可以在网络上的许多其他站点上找到。到目前为止,一切都很好。我只将 class 名称更改为 TOleMessageFilter
而不是 IOleMessageFilter
.
但是使用起来有点烦人。
var
Filter: TOleMessageFilter;
Filter := TOleMessageFilter.Create;
Filter.RegisterFilter;
...
Filter.RevokeFilter;
Filter.Free;
我想要的是,Filter
被声明为接口,例如IOleMessageFilter
。
var
Filter: IOleMessageFilter;
Filter := TOleMessageFilter.Create as IOleMessageFilter;
Filter.RegisterFilter;
...
Filter.RevokeFilter;
Filter := nil;
并且可以自动释放 TInterfacedObject
。
如何创建新的 IOleMessageFilter
,其中 "derives" 来自 IMessageFilter
,但仍有新方法 RegisterFilter()
和 RevokeFilter()
,实现为 TOleMessageFilter = class(TInterfacedObject, IOleMessageFilter)
,并且仍然可以将它与需要 IMessageFilter
的 CoRegisterMessageFilter()
一起使用(在 RegisterFilter()
方法中使用)?
我已尝试申报:
IOleMessageFilter = interface(IMessageFilter)
procedure RegisterFilter;
procedure RevokeFilter;
end;
TOleMessageFilter = class(TInterfacedObject, IOleMessageFilter)
...
end;
但是调用 CoRegisterMessageFilter
会抛出一个错误:
Interface not supported.
编辑:
我也曾尝试将 TOleMessageFilter
声明为:
TOleMessageFilter = class(TInterfacedObject, IMessageFilter, IOleMessageFilter)
哪种 "seems" 有效,但我不确定这是正确的方法。
拆分两个接口并让 TOleMessageFilter 保留对实际消息过滤器的引用,作为奖励,您不必再调用 RegisterFilter 和 RevokeFilter,因为这将从 constructor/destructor:
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.
我想按照此处所述实施 IOleMessageFilter
:
How to: Fix 'Application is Busy' and 'Call was Rejected By Callee' Errors
我找到了一个运行良好的 Delphi 实现:
(请参阅答案中的更新 #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 代码可以在网络上的许多其他站点上找到。到目前为止,一切都很好。我只将 class 名称更改为 TOleMessageFilter
而不是 IOleMessageFilter
.
但是使用起来有点烦人。
var
Filter: TOleMessageFilter;
Filter := TOleMessageFilter.Create;
Filter.RegisterFilter;
...
Filter.RevokeFilter;
Filter.Free;
我想要的是,Filter
被声明为接口,例如IOleMessageFilter
。
var
Filter: IOleMessageFilter;
Filter := TOleMessageFilter.Create as IOleMessageFilter;
Filter.RegisterFilter;
...
Filter.RevokeFilter;
Filter := nil;
并且可以自动释放 TInterfacedObject
。
如何创建新的 IOleMessageFilter
,其中 "derives" 来自 IMessageFilter
,但仍有新方法 RegisterFilter()
和 RevokeFilter()
,实现为 TOleMessageFilter = class(TInterfacedObject, IOleMessageFilter)
,并且仍然可以将它与需要 IMessageFilter
的 CoRegisterMessageFilter()
一起使用(在 RegisterFilter()
方法中使用)?
我已尝试申报:
IOleMessageFilter = interface(IMessageFilter)
procedure RegisterFilter;
procedure RevokeFilter;
end;
TOleMessageFilter = class(TInterfacedObject, IOleMessageFilter)
...
end;
但是调用 CoRegisterMessageFilter
会抛出一个错误:
Interface not supported.
编辑:
我也曾尝试将 TOleMessageFilter
声明为:
TOleMessageFilter = class(TInterfacedObject, IMessageFilter, IOleMessageFilter)
哪种 "seems" 有效,但我不确定这是正确的方法。
拆分两个接口并让 TOleMessageFilter 保留对实际消息过滤器的引用,作为奖励,您不必再调用 RegisterFilter 和 RevokeFilter,因为这将从 constructor/destructor:
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.