Save and restore event handlers

自闭症网瘾萝莉.ら 提交于 2019-12-12 11:32:53

问题


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.


回答1:


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.




回答2:


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);


来源:https://stackoverflow.com/questions/9585956/save-and-restore-event-handlers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!