4

私のクラスにはデータセット(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

保存されたアドレスをイベントハンドラーに割り当てるにはどうすればよいですか?ありがとう。

4

2 に答える 2

5

本当にイベントを保存したい場合は、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 を最初にクリックすると、「I am copy cat!」と表示されます。2 つ目は Hello World を表示します。

編集:MTD(TMethod)への割り当てイベントを改善します。よりシンプルで、他のオブジェクトからのイベントを許可します。

于 2012-03-06T16:30:06.933 に答える
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);
于 2012-03-06T15:00:05.550 に答える