Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I assign the method of an extended record to an event in Delphi?

Given the following record type:

type
  TMyRecord = record
  private
    procedure SomeMethod(_Sender: TObject);
  end;

should it be possible to assign this method as the event handler?

var
  MyRecord: TMyRecord;
begin
  Button1.OnClick := MyRecord.SomeMethod;
end;

In Delphi 2007 I get an internal compiler error C1264 after the assignment.

I am not sure whether the internal structure of a Record's method fulfill the requirements for being assigned to an event pointer.

EDIT: As David Heffernan pointed out, this is a compiler bug in Delhpi 2007. I ended up using the following workaround:

type
  TMyRecord = record
  private
    procedure SomeMethod(_Sender: TObject);
    function GenerateNotifyEvent(_CodePtr: pointer): TNotifyEvent;
  end;

function TMyRecord.GenerateNotifyEvent(_CodePtr: pointer): TNotifyEvent;
var
  Method: TMethod;
begin
  Method.Data := @Self;
  Method.Code := _CodePtr;
  Result := TNotifyEvent(Method);
end;

var
  MyRecord: TMyRecord;
begin
  Button1.OnClick := MyRecord.GenerateNotifyEvent(@TMyRecord.SomeMethod);
end;

Not as nice as a simple assignment, but good enough. I just wish I could simply update to a newer version of Delphi where that bug has been fixed.

like image 828
dummzeuch Avatar asked Apr 13 '15 13:04

dummzeuch


2 Answers

Yes, you should be able to do this. You can assign the following type of methods:

  • Instance methods of classes.
  • Class methods of classes.
  • Instance methods of records.
  • Instance methods of objects, that is the deprecated types introduced with the object keyword.

Since this is an internal compiler error, this would appear to be a compiler bug in Delphi 2007. Certainly your code will compile in later versions of Delphi.

QC#59807 seems to be very similar to your issue. According to that bug report it was resolved in build 11.0.2902.10471. Then again, perhaps it is this one: QC#60621 which is reported as being resolved in build 12.0.0.15784.

If you cannot upgrade to a compiler that does not have the fault, then do this:

var
  Method: TMethod;
....
Method.Code := @TMyRecord.SomeMethod;
Method.Data := @MyRecord;
Button1.OnClick := TNotifyEvent(Method);
like image 97
David Heffernan Avatar answered Nov 09 '22 09:11

David Heffernan


It works in XE7. No warnings. Method content executes as expected on button click.

like image 21
Lars Fosdal Avatar answered Nov 09 '22 09:11

Lars Fosdal