1. 程式人生 > >Delphi 製作自定義資料感知控制元件並裝入包(dpk檔案)中(與DBText類似的資料感知控制元件)

Delphi 製作自定義資料感知控制元件並裝入包(dpk檔案)中(與DBText類似的資料感知控制元件)

一、基礎知識簡介:

1、包的命名介紹:

                包的命名沒有規則,但是建議遵守包的命名約定:包的命名與包的版本相關,包的名稱前面幾個字元通常表示作者或公司名,也可以是控制元件的一個描述詞,後面緊跟的Std表示執行期包,Dsgn表示設計期包,然後是版本號。如:MyDataEditStd60,MyDataEditDsgn60。

 

2、物件瀏覽器【Object Inspector】中一個屬性感知一類控制元件的原理:

                控制元件屬性的感知只不過是將它的一個屬性宣告為將要感知的控制元件類而已,例如要感知Image控制元件,則:property MyImage:TImage read GetImage write SetImage;這樣之後,窗體中的所有的TImage型別的控制元件,它都能感知到。

 

3、資料感知控制元件與其他相關控制元件進行互動的方法:

                資料感知控制元件通過DataLink物件與DataSource進行互動,所以為控制元件增加資料感知能力需要建立一個TDataLink(或其派生類)物件作為控制元件的成員,併為控制元件建立公開的DataField和DataSource屬性;然後需響應TDataLink物件的OnDataChange和OnUpdateData事件。

                我們用到了一個重要的類TFieldDataLink。它是控制元件內部的資料聯接物件,從TDataLink繼承下來,它的作用是與TDataSource元件相互通訊,連線單個欄位進行資料提取。我們將要處理這個物件的OnDataChange事件,這樣,當欄位或記錄有所改變時就會得到通知,進行相應的資料處理。

 

4、當其中一個控制元件被刪除或者斷開時,通知其他控制元件的通知函式:

                感知元件需要和DataSource資料來源控制元件和DataSet資料集控制元件相組合才能實現

資料庫資料的讀寫,那麼當刪除其中一個時,如果其他兩個控制元件不知道,就會出現異常,甚至導致宕機。那麼我們怎樣才能做到通知其他元件呢?Value.FreeNotification(Self)就是做這個工作的!FreeNotification(self)將會把我們的元件置入其通知物件列表中,被撤消時,它會依次呼叫通知物件列表中所有物件的Notification方法。每個資料控制元件都有一個Notification方法,當某一控制元件從窗體上移走時,DELPHI的IDE呼叫該方法通知其它控制元件。

 

二、製作資料感知控制元件的具體步驟:

本文以製作一個類似於DBEdit的控制元件為例。

1、 建立元件,並安裝在新包中。

1>、首先使用元件嚮導從TEdit(StdCtrls)下繼承下來,命名TMyDataBaseEdit,單元名為MyDataBaseEdit.pas,

2>、安裝在一個新的包檔案中,起名為MyDataEditStd60.Dpk。 (此種不需要dpr工程)

      (【Delphi 編寫Pas檔案型別的元件】 中的 【二、製作一個簡單的元件基本步驟】 有介紹)

 

2、 新增屬性。

1>、宣告一個內部資料連線物件:TfieldDataLink,用於與TDataSource進行通訊。

         在Private中新增程式碼:  FDataLink: TFieldDataLink; // Uses DBCtrls;

2>、新增資料來源感知屬性:DataSource 和欄位感知屬性:DataField ;其值就顯示Text中,處理事件是DataChange

         和UpdateData。

         只需在Pubished域新增以下程式碼:

                  property DataSource: TDataSource read GetDataSource write SetDataSource;// Uses DB:

                  property DataField: string read GetDataField write SetDataField;

3>、按下【shift +ctrl+ C】組合鍵完成屬性的自動結構化功能,

         private域自動新增四個函式:

                  procedure SetDataSource(const Value: TDataSource);

                  function GetDataSource: TDataSource;

                  procedure SetDataField(const Value: string);

                  function GetDataField: string;

4>、上面四個函式的實現方法:

         function TMyDataBaseEdit.GetDataSource: TDataSource;

         begin

           Result := FDataLink.DataSource;

         end;

 

         procedure TMyDataBaseEdit.SetDataSource(const Value: TDataSource);

         begin

           if not(FDataLink.DataSourceFixed and (csLoading in ComponentState)) then

           begin

             FDataLink.DataSource := Value;

          end;

          if Value <> nil then

          begin

             // 將會把我們的元件置入其通知物件列表中,被撤消時,它會依次呼叫通知物件列表

             // 中所有物件的Notification方法,

             Value.FreeNotification(Self);

          end;

         end;

 

         function TMyDataBaseEdit.GetDataField: string;

         begin

          Result := FDataLink.FieldName;

         end;

 

         procedure TMyDataBaseEdit.SetDataField(const Value: string);

         begin

            FDataLink.FieldName := value;

         end;

 

3、 新增方法:

 1>、實現通知函式(必須的)。

當某一控制元件從窗體上移走時,DELPHI的IDE呼叫該方法通知其它控制元件。這樣,當關聯的參考控制元件被刪除時,控制元件就會得到訊息,來處理事件,防止異常的發生,否則將會導致Delphi開發環境的不穩定甚至宕機。

在protected中新增程式碼:

         procedure Notification(AComponent: TComponent;Operation: TOperation);override;

新增實現的程式碼:

         procedure TMyDataBaseEdit.Notification(AComponent: TComponent; Operation: TOperation);

         begin

           inherited Notification(AComponent, Operation);

           // 當與控制元件相連的TdataSource控制元件被刪除時將控制元件的DataSource屬性置為空

           if (Operation = opRemove) and (FDataLink <> nil) and (AComponent = DataSource) then

               DataSource := nil;

         end;

 

2>、實現資料處理過程

當DataSet的記錄改變(如在DBGrid中滑動滾輪的瀏覽記錄)時觸發OnDataChange事件,DataChange作為該事件的事件處理控制代碼。

在Private中新增程式碼:

         procedure DataChange(Sender: TObject);

新增實現的程式碼:

         procedure TMyDataBaseEdit.DataChange(Sender: TObject);

         begin

           //若控制元件連線了的DataSet,則資料集變動時控制元件顯示當前記錄的相應欄位值

           if FDataLink.Field <> nil then

           begin

             Text := FDataLink.Field.Text;

           end;

         end;

 

3>、實現資料更新過程:

更新DataSet前將觸發OnUpdateData事件,UpdateData將作為該事件的事件處理控制代碼;

在Private中新增程式碼:

         procedure UpdateData(Sender: TObject);

新增實現的程式碼:

         procedure TMyDataBaseEdit.UpdateData(Sender: TObject);

         begin

           // 用控制元件中的Text更新到相應的欄位

           FDataLink.Field.Text := Text;

         end;

 

4>、實現控制元件失去焦點時的訊息處理函式:

當控制元件失去焦點時觸發CM_EXIT訊息

在private中新增程式碼:

         procedure CMExit(var Message: TCMExit);Message CM_Exit;

新增實現的程式碼:

         procedure TMyDataBaseEdit.CMExit(var Message: TCMExit);

         begin

           try

              // 控制元件失去焦點時更新DataSet,這將觸發OnUpdateData事件

             FDataLink.UpdateRecord;

          except

             setFocus;

             //這裡是將發生的異常顯現出來。因為用了try except end後就不會顯示出異常和錯誤。

             raise;

           end;

           DoExit;

         end;

 

5>、重新編寫建構函式:

在建構函式中建立DataLink物件,連線OnDataChange、OnUpdateData事件處理控制代碼。

在public中新增程式碼:

         constructor Create(AOwner: TComponent);Override;

新增實現的程式碼:

         constructor TMyDataBaseEdit.Create(AOwner: TComponent);

         begin

           inherited Create(AOwner);  //必須加上這句話;

           //建立DataLink物件,連線OnDataChange、OnUpdateData事件處理控制代碼

           FDataLink := TFieldDataLink.Create;

           FDataLink.OnDataChange := DataChange;

           FDataLink.OnUpdateData := UpdateData;

         end;

 

6>、重新編寫解構函式:

在解構函式中銷燬DataLink物件,並釋放對OnDataChange、OnUpdateData事件的連線。確保使用完之後銷燬FDataLink的例項,釋放空間,無論是寫元件還是寫程式我們都要嚴格注意宣告的物件,一定要在使用完之後釋放!

在public中新增程式碼:

         destructor Destroy;override;

新增實現的程式碼:

         destructor TMyDataBaseEdit.Destroy;

         begin

           FDataLink.OnDataChange := nil;

          FDataLink.OnUpdateData := nil;

           FreeAndNil(FDataLink);

         Inherited ;

         end;

 

三、DPK檔案型別(包)的除錯

1、在建立新包dpk或者選擇已經存在的包之後,點選【Ok】之後會出現安裝【dpk檔案對話方塊】,按其中的【Compile】就可以檢查你編寫的程式碼是否存在錯誤,但不能檢測邏輯錯誤。

2、【Project】—>【Build XXX】也能檢測程式碼中的錯誤。但是直接開啟Pas檔案,這個按鈕不可用。可以先點選開啟其所在的dpk,然後開啟pas檔案, 但不能檢測邏輯錯誤.

3、安裝完自定義控制元件後,在自定義控制元件的Pas中修改程式碼,會直接影響到呼叫他的程式中,所以可以直接在自定義控制元件的Pas檔案中設定斷點,進入除錯, 可以檢測邏輯錯誤;

4、在自定義控制元件的Pas檔案中,新增的新屬性、事件。在應用程式中能通過程式碼直接呼叫,但是在物件監控器【Object Inspector】中不會顯示,只能重新載入自定義控制元件,才能顯示。

 

 四、安裝dpk檔案型別的元件:

第一種方法:

1、【File】-> 【Open Project】命令,然後在對話方塊中選擇檔案型別為【*.dpk;*.dpkw】的檔案;

2、然後【開啟】,會出現【dpk檔案對話方塊】,點選【Compile】—>【Install】,進行安裝.。

 

第二種方法:

1、直接在dpk檔案上雙擊,就會出現【dpk檔案對話方塊】,點選【Compile】—>【Install】,進行安裝.。

 

五、刪除控制元件:

1、【Component】—>【Install Packages】,出現一個對話方塊。

2、然後在【Designs Packages】 中找到當前包相對應的同名bpl檔案。

3、然後【Edit】->【Yes】,開啟【dpk檔案對話方塊】,然後選擇對應的檔案,點選【Remove】刪除。

     然後再編譯安裝。

  (也可以直接找到相應的DPK檔案,雙擊進入【dpk檔案對話方塊】,一般預設在lib下)

 

檢視元件所屬的包:

                     在【元件面板】上相應的元件上【右擊】—>【Properties】,然後開啟對話方塊,可以在【Palette】中,右側欄中看【Components】中看到name,和它所處的包。