我想像Delphi那样“响应ConnectionEventsVt事件”,我想做到“实现了ConnectionEventsVt接口”就能实现事件,因为“响应DispInterface类型的接口,要求接受者实现IDispath接口,在Invoke方法中根据Dispid判别是哪个事件”我觉得那样的办法真是很笨的。。。
现在的问题是,我要怎么样做组件才能实行第一种啊?
Delphi里面有个想到,可以产生事件的接口,但是那样好像就是第二种的。
我曾经增加一个接口定义。然后组件:
unit uEventCOMImpl;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
ComObj, ActiveX, AxCtrls, Classes, COMEvent_TLB, StdVcl, Dialogs, Windows, SysUtils;
type
TEventCOM = class(TAutoObject, IConnectionPointContainer, IEventCOM)
private
{ Private declarations }
FConnectionPoints: TConnectionPoints;
FConnectionPoint: TConnectionPoint;
FEvents: IEventCOMEvents;
FEvent: IEventCOMEvent;
{ note: FEvents maintains a *single* event sink. For access to more
than one event sink, use FConnectionPoint.SinkList, and iterate
through the list of sinks. }
public
procedure Initialize; override;
protected
function Get_Event: IUnknown; safecall;
procedure Set_Event(const Value: IUnknown); safecall;
procedure BeginEvent; safecall;
procedure EndEvent; safecall;
{ Protected declarations }
property ConnectionPoints: TConnectionPoints read FConnectionPoints
implements IConnectionPointContainer;
procedure EventSinkChanged(const EventSink: IUnknown); override;
end;
implementation
uses ComServ;
procedure TEventCOM.EventSinkChanged(const EventSink: IUnknown);
begin
inherited EventSinkChanged(EventSink);
Windows.OutputDebugString('EventSinkChanged1');
//FEvents := EventSink as IEventCOMEvents;
FEvent := EventSink as IEventCOMEvent;
Windows.OutputDebugString('EventSinkChanged2');
end;
procedure TEventCOM.Initialize;
begin
inherited Initialize;
FEvents := nil;
FConnectionPoints := TConnectionPoints.Create(Self);
if AutoFactory.EventTypeInfo <> nil then
FConnectionPoint := FConnectionPoints.CreateConnectionPoint(
AutoFactory.EventIID, ckSingle, EventConnect)
else FConnectionPoint := nil;
end;
procedure TEventCOM.BeginEvent;
var
StrTemp: WideString;
begin
Windows.OutputDebugString('procedure TEventCOM.BeginEvent;1');
if Assigned(FEvents) then
begin
FEvents.BeginEvent(StrTemp, StrTemp);
ShowMessage(StrTemp);
end;
if Assigned(FEvent) then
begin
FEvent.BeginEvent(StrTemp, StrTemp);
ShowMessage(StrTemp);
end;
Windows.OutputDebugString('procedure TEventCOM.BeginEvent;2');
end;
procedure TEventCOM.EndEvent;
begin
if Assigned(FEvents) then
begin
FEvents.EndEvent;
end;
end;
function TEventCOM.Get_Event: IUnknown;
begin
Result := FEvent as IUnknown;
end;
procedure TEventCOM.Set_Event(const Value: IUnknown);
begin
FEvent := Value as IEventCOMEvent;
end;
initialization
TAutoObjectFactory.Create(ComServer, TEventCOM, Class_EventCOM,
ciMultiInstance, tmApartment);
end.
客户端实现接口和通过InterfaceConnect传递进去:
TMyEventCOM = class(TComponent, IUnknown, IEventCOMEvent)
private
FObj: IEventCOM;
FConnEventsID: Integer;
protected
procedure BeginEvent(const OutStr: WideString; var InStr: WideString); safecall;
procedure EndEvent; safecall;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure myBeginEvent; overload;
procedure myEndEvent; overload;
end;
procedure TMyEventCOM.BeginEvent(const OutStr: WideString; var InStr: WideString);
begin
InStr := 'InStr: ' + OutStr;
end;
constructor TMyEventCOM.Create(AOwner: TComponent);
procedure InterfaceConnect(const Source: IUnknown; const IID: TIID;
const Sink: IUnknown; var Connection: Longint);
var
CPC: IConnectionPointContainer;
CP: IConnectionPoint;
begin
Connection := 0;
if Succeeded(Source.QueryInterface(IConnectionPointContainer, CPC)) then
if Succeeded(CPC.FindConnectionPoint(IID, CP)) then
CP.Advise(Sink, Connection);
end;
begin
inherited Create(AOwner);
FObj := CoEventCOM.Create;
FObj.Event := Self;
InterfaceConnect(FObj, IID_IEventCOMEvent, Self, FConnEventsID);
end;
destructor TMyEventCOM.Destroy;
begin
InterfaceDisconnect(FObj, IID_IEventCOMEvent, FConnEventsID);
inherited;
end;
procedure TMyEventCOM.EndEvent;
begin
end;
procedure TMyEventCOM.myBeginEvent;
begin
FObj.BeginEvent;
end;
procedure TMyEventCOM.myEndEvent;
begin
FObj.EndEvent;
end;
最终调用失败。。。出现灾难性错误。。。不知道你是否实际做过这样的组件呢,而这样的问题你是怎么解决的?