把 DataModule 的事件放在 Form 中處理 例如: 把 DataModule 中的某個 DataSource 的 OnStateChange 事件 指定到 Form1 的自定函數 MyStateChange. 如此做法看似將 DataModule 及 Form 的關係複雜化 (增加藕合度), 但實則將 DataModule 公開出一個彈性的界面, 使得你無須在 DataModule 中存取 Form 的物件 注意事項: 如果在這些事件中發生了 Exception, 則無法單步追蹤到, 除非你在這 些事件中設立中斷點, 否則你可能會發生一些很奇怪的狀況, 例如: 資 料表無法開啟, 程式出現 Access violation...的訊息. 所以請盡量在 這些事件中事先檢查要使用的物件是否為NULL或者用try...except 把程式碼包住!!! 請看下面的範例: DMod 是一個 TDataModule 的物件, DMod 中有下列物件: DataSource1 Table1 程式如下: ----------------- type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); private public procedure MyStateChange(Sender: TObject); procedure MyDataChange(Sender: TObject; Field: TField); procedure MyAfterScroll(DataSet: TDataSet); end; var Form1: TForm1; implementation procedure TForm1.FormCreate(Sender: TObject); begin // 以下的三行敘述也可以放在 FormShow 或 FormActive 事件中 DMod.DataSource1.OnStateChange := MyStateChange; DMod.DataSource1.OnDataChange := MyDateChange; DMod.Table1.AfterScroll := MyAfterScroll; DMod1.Table1.Open; end; procedure TForm1.MyAfterScroll(DataSet: TDataSet); begin if Assigned(DataSet) and DataSet.Active then begin // 不管怎樣先檢查要用的物件是否已配置好, 安全第一 if StatusBar1 <> nil then StatusBar.SimpleText := IntToStr(DataSet.RecordCount); end; end; procedure TForm1.MyStateChange(Sender: TObject); var IsEditing: Boolean; begin // 用一個 try...except 確保 Exception 不會沒人處理而導致 // 其他更嚴重的錯誤 try if DMod.Table1.Active then begin IsEditing := (DMod.Table1.State in [dsEdit, dsInsert]); edAddress.Enabled := IsEditing; end; except // 忽略錯誤 end; end; procedure TForm1.MyDataChange(Sender: TObject; Field: TField); begin {....} end;