程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Data-Browse型Data-Aware控件的制作

Data-Browse型Data-Aware控件的制作

編輯:Delphi

Data-Browse型Data-Aware控件的制作


在MIS系統中,使用得最常見的當屬數據感知控件了。學習如何編寫自已的組件,一條很重要的原則就是從自己熟悉的
組件入手,派生出新的合乎自己要求的控件。在數據感知控件中,Data-Browse型是非常簡單而又實用的。所以下面
我們就講解一個一個自定義的TSunDBText(功能等同於TDBText)的編寫:

TSunDBText = class(TCustomLabel)
 {...}
end;

因為DBText僅起著顯示數據的作用,即是個具有數據感知功能的標簽,又根據Delphi的習慣,從Custom系列控件派生,
所以我們選擇了TCustomLabel。

如何具有數據感知功能,其實大部分的書上都沒有講得很明白,包括Delphi Help。大致上有這麼幾點,我們慢慢敘述:
一:選擇一個能數據感知的DataLink對象,通常我們選用TFieldDataLink,表示僅與一個數據庫字段關聯
二:組件必須提供DataSource和DataField兩個設計時可讀寫屬性
三:組件必須處理FDataLink的OnDataChange事件,以反映數據字段的變化
四:必須提供Notification重載方法,以便當關聯的TDataSource組件在設計期或者運行期刪除時,能得到通知,並且
      反映出這種改變
五:習慣上,我們還要處理CM_GETDATALINK消息,以符合VCL內部通信的要求
六:為了組件的靈活性,建議提供一個Field屬性,以便可以利用TField的方法來增強編程的適用性

下面我們就來一一講解:
private
   FDataLink:TFieldDataLink;
  
constructor Create(AOwner:TComponent);override;
begin
   inherited;
   FDataLink := TFieldDataLink.Create; {創建一個TFieldDataLink的對象}
   FDataLink.OnDataChange := DataChange;
   {
  
    將TFieldDataLink對象的OnDataChange事件處理交給TSunDBText的DataChange來處理
    這樣就要以感知數據庫字段的變化,並且進行自己想要的處理
   
   }
end;

destructor Destroy;override;
begin
  {
    這裡很簡單,僅僅是回收資源而已
  }
   FDataLink.Free;
   FDataLink := nil;
   inherited;
end;

從上面我們已經看到,數據感知的關鍵就在於DataChange事件,大致上我們可以知道,是需要將該字段的顯示值賦予
本標簽組件的Caption屬性即可,所以下面的代碼便是做這部分工作的。
(注意,之所以要用GetFieldText來完成賦值工作,是出於多方面的考慮,包括設計期和運行期,及異常情況)
procedure TSunDBText.DataChange(Sender: TObject);
begin
  Caption := GetFieldText; {read only displaytext when make an data browing component}
end;

function TSunDBText.GetFieldText: String;
begin
  {
 
  正常情況下,只需要取得FDataLink所代表的Field的DisplayText即可,如果你開發的不是Data-Browse控件,請用其他
  Field屬性
 
  }
  if(FDataLink <> nil) then
    Result := FDataLink.Field.DisplayText
  else if(csDesigning in ComponentState) then Result := Name else Result := ;
  {
   如果是處在設計期,則標簽中顯示的是組件的名稱,如果是運行期,則標簽為空;當然,這只是習慣而已,但對於使用Delphi IDE的人來說,
   幾乎就是規則。
  }
end;

如果沒有DataSource和DataField這兩個屬性,那麼控件幾乎就沒法使用了。這也是重要步驟。

    property DataSource:TDataSource read GetDataSource write SetDataSource;
    property DataField:String read GetDataField write SetDataField;
   
    這些方法十分簡單,只要存取TFieldDataLink之DataSource和FieldName屬性則可。
   
 function TSunDBText.GetDataSource: TDataSource;
begin
  Result := FDataLink.DataSource;
  {僅需簡單地返回TFieldDataLink之DataSource屬性
   從這就可以看出,DataSource屬性的寫方法也是對FDataLink賦值}
end;

procedure TSunDBText.SetDataSource(Value: TDataSource);
begin
  FDataLink.DataSource := Value; {如上所雲,對DataSource屬性賦值}

  if(Value <> nil) then Value.FreeNotification(self);
  {
    這裡很重要,TComponent提供了一個FreeNotification(AComponent:TComponent)方法,這樣,當Value釋放時,就會自動調用AComponent的Notification
    方法,我們就可以調整對應的Data-Browse控件,以反映這種變化。如TSunDBText對應的DataSource組件刪除掉,則應該反映在標簽上
  }
end;

function TSunDBText.GetDataField: String;
begin
  Result := FDataLink.FieldName;  {獲得TFieldDataLink之FieldName屬性,也就知道了連接的是哪一個數據庫字段名稱}
end;

procedure TSunDBText.SetDataField(const Value: String);
begin
  FDataLink.FieldName := Value; {這應該不用解釋了}
end;

接上面的,我們說過Notification的由來,下面就進行相關的處理:
procedure TSunDBText.Notification(AComponent: TComponent;
  Operation: TOperation);
begin
  inherited;
  if(Operation = opRemove) and (FDataLink <> nil) and (AComponent = DataSource) then
    DataSource := nil;
end;

當關聯組件被刪除時,而且被刪除的正好是本身關聯的DataSource組件,就應該設置其DataSource屬性為空

function TSunDBText.GetField: TField;
begin
  Result := FDataLink.Field;
end;

最後,數據感知控件還要響應CM_GETDATALINK消息。通常處理是將TDataLink作為Message的Result域返回
procedure CMGetDataLink(var Message:TMessage);message CM_GETDATALINK;

procedure CMGetDataLink(var Message:TMessage);
begin
    Message.Result := Integer(FDataLink);
end;
到此,基本上組件的功能就已齊備了,然而,有一點許多組件編寫者都沒有注意到,即Action的應用。如果自定義組件能融入VCL的Action機制,
必然可以使自定義控件的功能更強大,更為一些高級使用者喜歡。

下一次,我們就來講一講Action之來龍去脈。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved