【问题标题】:Save and restore event handlers保存和恢复事件处理程序
【发布时间】:2023-03-27 07:47:01
【问题描述】:

我的课程包含数据集 (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

如何将存储的地址分配给事件处理程序? 谢谢。

【问题讨论】:

  • Delphi 的哪个版本?现代 Delphi 通用容器类将完成您需要的工作。此外,您不能将事件处理程序放入Integer。事件处理程序是对象的方法。这意味着它是两个指针。
  • 对不起,忘了说:Delphi 6。
  • @DavidHeffernan 好的,我可以创建两个指针记录的列表(TMethod?)。如何从该记录中保存和恢复处理程序?

标签: delphi events delphi-6


【解决方案1】:

如果你真的想保存事件,可以使用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)。更简单,并允许来自其他对象的事件。

【讨论】:

  • 这正是我所需要的。谢谢。
  • 如果您简单地将MTD 声明为TNotifyEvent 类型,则可以取消类型转换。
  • @MarjanVenema 我正在保存不同类型的事件,所以类型转换是可以的。
【解决方案2】:

我自己对自己的数据集进行子类化,并且可以选择在打开表格和映射字段事件之前创建所有字段。这样做,该字段(及其事件)在关闭后不会消失。

这也可以在 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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-13
    • 2011-01-13
    • 1970-01-01
    相关资源
    最近更新 更多