Сохранить и восстановить обработчики событий - PullRequest
4 голосов
/ 06 марта 2012

Мой класс содержит набор данных (TDataSet).Пользователи моего класса могут назначать обработчики событий для этого набора данных:

ds.FieldByName('ID').OnChange := @ID_OnChange;

Затем мне нужно заново открыть набор данных:

ds.Close;
ds.Open;

После этого все обработчики событий исчезнут:

if Assigned(ds.FieldByName('ID').OnChange) //returns false

Итак, мне нужно сохранить обработчики и восстановить их после повторного открытия.Для этого я использую TStringList:

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

Проблема в том, как восстановить обработчики:

ds.FieldByName('ID').OnChange := TFieldNotifyEvent(ObjToInt(EventHandlers.Objects[0]));//Invalid typecast error

Как назначить сохраненный адрес обработчику событий?Спасибо.

Ответы [ 2 ]

4 голосов
/ 06 марта 2012

Если вы действительно хотите сохранить события, вы можете использовать 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.

Первый щелчок на Btn2 покажет "Я копирую кота!" и второй покажет Hello World.

Edit: улучшено назначение события MTD (TMethod). Более простые и разрешить события из других объектов.

2 голосов
/ 06 марта 2012

Я сам подкласс своего собственного набора данных и имеет опции для создания всех полей перед открытием таблицы и сопоставлением событий поля. При этом поле (и его события) не исчезнут после закрытия.

Это также можно сделать в событии OnBeforeOpen.

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