2012-03-06 27 views
3

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

どのバージョンのDelphiですか?現代のDelphiジェネリックコンテナクラスは必要な仕事をします。また、イベントハンドラを 'Integer'に入れることもできません。イベントハンドラはオブジェクトのメソッドです。つまり、それは2つの指針です。 –

+0

申し訳ありませんが、言って忘れてしまった:デルファイ6。 – IceHar

+0

@DavidHeffernan [OK]を、私は2つのポインタのレコード(TMethod?)のリストを作成することができます。そのレコードからハンドラを保存して復元する方法は? – IceHar

答えて

3

、あなたはTMethod録音を使用することができます。

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にまずクリックして表示され、「私は猫をコピーします!」 2番目にHello Worldが表示されます。

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

+0

これは私が必要とするものです。ありがとうございました。 – IceHar

+0

'MTot'を' TNotifyEvent'型として宣言しただけでは、型キャストをやめることができます。 –

+0

@MarjanVenema私はさまざまなタイプのイベントを保存していますので、タイプキャストはOKです。 – IceHar

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

ありがとう、私はこれを試してみます。 – IceHar

関連する問題