views:

69

answers:

1

Is it possible to use interface method as event handlers in Delphi 2007? The simple versions don't work:

type
  TMyEvent = procedure of object;

  IMyInterface = interface
    procedure Handler;
  end;

  TMyClass = class(TInterfacedObject, IMyInterface)
  public
    procedure Handler;
  end;

var
  ev: TMyEvent;
  obj: TMyClass;
  intf: IMyInterface;
begin
  obj := TMyClass.Create;
  intf := obj;
  ev := obj.Handler; // compiles
  ev := intf.Handler; // <== Error E2010 (incompatible types)
end.

Adding @ or Addr changes the error to E2036 (variable required).

Update: This

procedure IntRefToMethPtr(const IntRef; var MethPtr; MethNo: Integer);
type
  TVtable = array[0..999] of Pointer;
  PVtable = ^TVtable;
  PPVtable = ^PVtable;
begin
  //QI=0, AddRef=1, Release=2, etc
  TMethod(MethPtr).Code := PPVtable(IntRef)^^[MethNo];
  TMethod(MethPtr).Data := Pointer(IntRef);
end;

var
  ev: TMyEvent;
  intf: IMyInterface;
begin
  intf := TMyClass.Create;
  IntRefToMethPtr(intf, ev, 3);
  ev;
end.

works. However I'm not too fond of the magic 3 in there.

+1  A: 

A cleaner solution is to implement IInterfaceComponentReference, or something similar for your base class, and uses that to get the class ref.

The above code will not work on e.g. FPC and other compatibles. Their VMT structure is slightly different. And even on Delphi a future language extension might cause this.

A perfect solution would be to have a completely separate "interface" methodvar type for this, but I wonder if that is worth the trouble.

Marco van de Voort
Sounds reasonable. Maybe I'll modify this to a GetHandler method instead of a GetSelf. Thanks!
Ulrich Gerhardt