My class contains dataset (TDataSet). Users of my class can assign event handlers for this dataset:
ds.FieldByName('ID').OnChange := @ID_OnChange;
Then I have to reopen dataset:
ds.Close;
ds.Open;
After this all event handlers are gone:
if Assigned(ds.FieldByName('ID').OnChange) //returns false
So, I need to save handlers and restore them after reopen. I use TStringList for it:
var
EventHandlers: TStringList;
...
//I do this for every event of every field
if Assigned(ds.FieldByName('ID').OnChange) then
EventHandlers.AddObject('ID', @ds.FieldByName('ID').OnChange);
The problem is how to restore handlers:
ds.FieldByName('ID').OnChange := TFieldNotifyEvent(ObjToInt(EventHandlers.Objects[0]));//Invalid typecast error
How can I assign stored address to event handler?
Thanks.
If you really want to save the events, you can use TMethod Record:
unit Unit6;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm6 = class(TForm)
btn1: TButton;
btn2: TButton;
procedure btn1Click(Sender: TObject);
procedure btn2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
MTD : TMethod;
end;
var
Form6: TForm6;
implementation
{$R *.dfm}
procedure TForm6.btn1Click(Sender: TObject);
begin
ShowMessage('Hello World!');
end;
procedure TForm6.btn2Click(Sender: TObject);
begin
ShowMessage('I am copy cat!');
MTD := TMethod(btn1.OnClick);
btn2.OnClick := TNotifyEvent(MTD);
end;
end.
The First Click on Btn2 will show "I am copy cat!" and The 2nd one will show Hello World.
Edit : Improve assign event to MTD(TMethod). More simple and allow events from other objects.
I myself subclass my own dataset and has options to create all fields before opening the table and mapping the field events. In doing so, the field (and their events) will not disappear after close.
This can also be done in OnBeforeOpen Event.
If CreateFIeldBeforeOpen
If FieldDefs.Count = 0 then
FieldDefs.Update;
for I := 0 to FieldDefs.Count - 1 do
If not Assigned(FindField(FieldDefs[I].Name)) then
FieldDefs[I].CreateField(Self, nil, FieldDefs[I].Name);