2012-03-06 35 views
3

我的類包含數據集(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'中。事件處理程序是對象的一種方法。這意味着它是兩個指針。 – 2012-03-06 14:53:56

+0

對不起,忘了提及:Delphi 6. – IceHar 2012-03-06 15:00:25

+0

@DavidHeffernan好的,我可以創建兩個指針記錄(TMethod?)的列表。如何從該記錄保存和恢復處理程序? – IceHar 2012-03-06 15:06:08

回答

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會顯示「我模仿他人!」第二個將顯示Hello World。

編輯:將分配事件改進爲MTD(TMethod)。更簡單,並允許來自其他對象的事件。

+0

這正是我需要的。謝謝。 – IceHar 2012-03-07 07:26:00

+0

如果您只是將'MTD'聲明爲'TNotifyEvent'類型,那麼您可以避免使用類型轉換。 – 2012-03-07 09:19:36

+0

@MarjanVenema我保存不同類型的事件,所以類型轉換就可以了。 – IceHar 2012-03-07 09:38:49

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 2012-03-06 16:22:18