我的类包含数据集(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
如何将存储的地址分配给事件处理程序? 感谢。
答案 0 :(得分:4)
如果您确实要保存事件,可以使用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。
编辑:改进MTD(TMethod)的分配事件。更简单,允许来自其他对象的事件。
答案 1 :(得分:2)
我自己将自己的数据集子类化,并且可以在打开表格和映射字段事件之前创建所有字段。在这样做时,场(及其事件)不会在关闭后消失。
这也可以在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);