<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    如鵬網 大學生計算機學習社區

    CowNew開源團隊

    http://www.cownew.com 郵件請聯系 about521 at 163.com

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      363 隨筆 :: 2 文章 :: 808 評論 :: 0 Trackbacks
    ?

    八、數據敏感控件的制作。

    Delphi的一大亮點就是它的數據庫開發能力。而數據敏感組件則在這中間起著很重要的作用。在DelphiData Control頁面下的控件都是用于顯示和編輯數據庫中的數據的。相信大家已經體會到數據敏感控件的好處了。我們這一節就給大家演示一下數據敏感控件的開發方法。

    需要提醒大家的是,不像其他體系的控件,數據敏感控件并沒有一個統一的基類,只要是從TwinControl類或其子類派生就可以,數據敏感控件的特殊之處就在于我們下面提到的數據連接。

    相信用Delphi開發過數據庫的人一定對delphi中沒有一個日期數據敏感控件而惱火。每次都要我們自己處理數據的更新與顯示。所以我們就來開發一個DBDateTimePicker控件。

    新建一個控件,從TdateTimePicker派生,源代碼如下:

    {*******************************************************}

    {?????? Linco TDBDateTimePicker

    {?????? mail me: about521@163.com?????????????????????? }

    {*******************************************************}

    unit DBDateTimePicker;

    interface

    uses

    ? SysUtils, Classes, Controls, ComCtrls, DBCtrls, Messages, DB;

    type

    ? TDBDateTimePicker = class(TDateTimePicker)

    ? private

    ??? FDataLink: TFieldDataLink;

    ??? procedure CMGetDataLink(var Msg: TMessage);message CM_GETDATALINK;

    ??? procedure DataChange(Sender: TObject);

    ??? procedure EditingChange(Sender: TObject);

    ??? procedure FSetDataField(AValue: string);

    ??? procedure FSetDataSource(AValue: TDataSource);

    ??? procedure FSetReadOnly(AValue: Boolean);

    ??? procedure ShowData;

    ??? procedure UpdateData(Sender: TObject);

    ??? function FGetDataField: string;

    ??? function FGetDataSource: TDataSource;

    ??? function FGetField: TField;

    ??? function FGetReadOnly: Boolean;

    ? protected

    ??? procedure Change;override;

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

    ? public

    ??? constructor Create(AOwner: TComponent); override;

    ??? destructor Destroy; override;

    ??? property Field: TField read FGetField;

    ? published

    ??? property DataField: string read FGetDataField write FSetDataField;

    ??? property DataSource: TDataSource read FGetDataSource write FSetDataSource;

    ??? property ReadOnly: Boolean read? FGetReadOnly write FSetReadOnly;

    ? end;

    procedure Register;

    implementation

    uses? Variants;

    constructor TDBDateTimePicker.Create(AOwner: TComponent);

    begin

    ? inherited Create(AOwner);

    ? FDataLink := TFieldDataLink.Create;

    ? FDataLink.OnDataChange := DataChange;

    ? FDataLink.Control := self;

    ? FDataLink.OnEditingChange := EditingChange;

    ? FDataLink.OnUpdateData := UpdateData;

    ? self.DateTime := Now();

    end;

    ?

    destructor TDBDateTimePicker.Destroy;

    begin

    ? FDataLink.Free;

    ? inherited;

    end;

    ?

    procedure TDBDateTimePicker.CMGetDataLink(var Msg: TMessage);

    begin

    ? Msg.Result := Integer(FDataLink);

    end;

    ?

    procedure TDBDateTimePicker.DataChange(Sender: TObject);

    begin

    ? if Field<>nil then

    ??? if Field.Value = null then

    ????? if (DataSource.DataSet.State = dsEdit)

    ??????? or (DataSource.DataSet.State = dsInsert) then

    ??????? Field.AsDateTime := Now();

    ? ShowData;

    end;

    ?

    procedure TDBDateTimePicker.EditingChange(Sender: TObject);

    begin

    ? if (DataSource <> nil) and (DataField <> '') then

    ??? FDataLink.Edit;

    end;

    ?

    procedure TDBDateTimePicker.FSetDataField(AValue: string);

    begin

    ? FDataLink.FieldName := AValue;

    end;

    ?

    procedure TDBDateTimePicker.FSetReadOnly(AValue: Boolean);

    begin

    ? FDataLink.ReadOnly := AValue;

    end;

    ?

    procedure TDBDateTimePicker.ShowData;

    begin

    ? if (DataSource <> nil) and (DataField <> '') and(Field<>nil)then

    ? begin

    ??? case Kind of

    ??? dtkDate: if Field.AsString <> '' then

    ?????????????? self.Date := Field.AsDateTime

    ???????????? else

    ?????????????? self.Date := Now();

    ??? dtkTime: if Field.AsString <> '' then

    ??????? ???????self.Time := Field.AsDateTime

    ???????????? else

    ?????????????? self.Time := Now();?

    ??? else

    ????? self.DateTime := Now();

    ??? end;

    ? end;

    end;

    ?

    procedure TDBDateTimePicker.FSetDataSource(AValue: TDataSource);

    begin

    ? FDataLink.DataSource := AValue;

    ? if AValue <> nil then

    ??? AValue.FreeNotification(self);

    end;

    ?

    procedure TDBDateTimePicker.Change;

    begin

    ? if (DataSource <> nil) and (DataField <> '') then

    ? begin

    ??? FDataLink.Edit;

    ??? Field.Value := self.Text;

    ? end;

    ? inherited Change;

    end;

    ?

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

    begin

    ? if (Operation = opRemove) and (FDataLink <> nil) and

    ????? (AComponent = DataSource) then

    ??? DataSource := nil;

    end;

    ?

    procedure TDBDateTimePicker.UpdateData(Sender: TObject);

    var

    ? t: TFieldType;

    begin

    ? if (DataSource <> nil) and (DataField <> '') then

    ? begin

    ??? t := FDataLink.Field.DataType;

    ??? case t of

    ??? ftTime: FDataLink.Field.AsDateTime := self.Time;

    ??? ftDate: FDataLink.Field.AsDateTime := self.Date;

    ??? ftDateTime: FDataLink.Field.AsDateTime := self.DateTime;

    ??? end;

    ? end;

    end;

    ?

    function TDBDateTimePicker.FGetDataField: string;

    begin

    ? result := FDataLink.FieldName;

    end;

    ?

    function TDBDateTimePicker.FGetDataSource: TDataSource;

    begin

    ? result := FDataLink.DataSource;

    end;

    ?

    function TDBDateTimePicker.FGetField: TField;

    begin

    ? result := FDataLink.Field;

    end;

    ?

    function TDBDateTimePicker.FGetReadOnly: Boolean;

    begin

    ? result := FDataLink.ReadOnly;

    end;

    procedure Register;

    begin

    ? RegisterComponents('Linco', [TDBDateTimePicker]);

    end;

    end.

    ?

    談到開發數據敏感控件就不得不說數據連接(DataLink),數據連接有很多種,開發數據敏感控件最常用到的就是字段數據連接(TFieldDataLink)。數據連接是聯系數據敏感控件和數據庫的通道。在數據敏感控件中就是憑借著數據連接來處理數據的更新和顯示的。從后邊我們的描述中您將更加能體會到,正是數據連接把數據在數據庫中的表示反映到用戶界面中,也是數據連接把數據從用戶界面更新到數據庫中。數據連接就是一個“大媒人”(這其實是設計模式中Mediator中介者模式的典型應用)。

    既然字段數據連接這么重要,我們就先來系統的介紹一下它吧!TfieldDataLink閃亮登場!!!

    TfieldDataLink的屬性:

    1)、property CanModify: Boolean;表示這個字段是不是只讀的。

    2)、property Control: TComponent;指定這個字段數據連接被連接到哪個數據敏感控件。因為字段數據連接要把它的狀態改變通知包含它的數據敏感控件。

    3)、property Editing: Boolean; 表示這個字段是不是可以被編輯。

    4)、property Field: TField;表示這個字段數據連接連接的字段。

    5)、property Active: Boolean;表示字段數據連接連接的數據集是否處于激活狀態。

    6)、property FieldName: String;字段名。

    7)、property DataSource: TDataSource;表示它連接的數據源。

    8)、property DataSet: TDataSet;表示它負責維護的數據集。

    方法:

    1)、function Edit: Boolean;嘗試設置字段為編輯狀態。如果設置成功則返回True,反之返回False;

    事件:

    1)、property OnActiveChange: TNotifyEvent;Active屬性變化的時候發生此事件。

    2)、property OnDataChange: TNotifyEvent;當數據集發生變化的時候發生。

    3)、property OnEditingChange: TNotifyEvent;當數據源從編輯狀態變為其他狀態或從其他狀態變為編輯狀態的時候發生。

    4)、property OnUpdateData: TNotifyEvent;當向數據庫提交對數據庫的修改時發生此事件。

    代碼分析:

    1)、做為一個數據敏感控件,它首先要實現的功能就是允許用戶將此控件連接到一個數據源(DataSource)。我們還要用戶能選擇這個控件綁定到哪個字段。

    將控件連接到一個數據源,而數據源又是一個控件,所以這就是一個關聯控件屬性方法的應用。FsetDataSourceFDataLink.DataSource := AValue;這句代碼是最重要的。就像我們前面講到的數據連接就是一個在數據源和數據敏感控件之間的媒人,所以數據源(DataSource)要告訴媒人是它要被連接到數據敏感控件,而不是別人,告訴媒人的唯一方法就是設定媒人的DataSource為自己(即要綁定的數據源)。因為我們的顯示日期的控件只能顯示一個字段,還要告訴媒人自己的哪個字段要綁定到數據敏感控件,這個通過數據敏感控件的FieldName屬性來進行。即:

    procedure TDBDateTimePicker.FSetDataField(AValue: string);

    begin

    ? FDataLink.FieldName := AValue;

    end;

    2)、我們還可以為控件增加一個Field屬性,這樣用戶就可以通過DBDateTimePicker.Field.AsString = ‘ok’;這樣的方式對字段進行操作了。當然了,這最終還是通過數據連接的Field屬性來進行的。

    3)、由于VCL內部通信機制的要求,數據敏感控件要響應CM_GETDATALINK事件。只要在事件相應函數里邊把消息的Result域賦值為DataLink的地址就可以了。也就是:

    procedure TDBDateTimePicker.CMGetDataLink(var Msg: TMessage);

    begin

    ? Msg.Result := Integer(FDataLink);

    end;

    4)、就像DBEdit一樣,在用戶通過改變控件中的日期時,應該能將改動保存到數據庫字段中。我們覆蓋控件的調度方法Change(在顯示的數據變化時被調用)以將變化保存到數據庫中。

    procedure TDBDateTimePicker.Change;

    begin

    ? if (DataSource <> nil) and (DataField <> '') then

    ? begin

    ??? FDataLink.Edit;//設置數據連接為編輯狀態,由這個媒人將數據庫綁定的字//段設置為編輯狀態

    ??? Field.Value := self.Text;//設定數據字段的值

    ? end;

    ? inherited Change;

    end;

    5)、回頭再來看看構造函數吧!

    ?? ?FDataLink.OnDataChange := DataChange;

    ?? FDataLink.OnEditingChange := EditingChange;

    ? FDataLink.OnUpdateData := UpdateData;

    ? FDataLink.Control := self;

    前三句是設定響應數據連接事件處理句柄,正是這三句把數據庫中的數據與用戶界面聯系了起來。關于這三個事件處理句柄的實現請參加源代碼,這里就不多說了。

    思考題:

    1、做一個顯示是/否的數據敏感控件,當這個控件與一個布爾類型的字段連接的時候,如果字段的值是0則顯示“否”,如果字段的值是1則顯示“是”;同時可以接受用戶的修改,當用戶在控件上單擊一次鼠標,布爾值就翻轉一次。

    posted on 2005-10-21 23:39 CowNew開源團隊 閱讀(2939) 評論(4)  編輯  收藏

    評論

    # re: Delphi控件開發淺入深出(八) 2005-10-22 09:53 王翠蓮
    老大,就是老大,真的很棒!
    可惜俺看不懂!
    努力,努力,努力!  回復  更多評論
      

    # re: Delphi控件開發淺入深出(八) 2005-11-18 12:46 知識恐慌
    good
    我也是Delphi學習者。剛剛開始,還請多指教。
    sealmantis@163.com  回復  更多評論
      

    # re: Delphi控件開發淺入深出(八) 2005-11-24 10:12 誰憶雪
    非常感謝您的這一系列的文章,讓我收獲頗多!
    我只是剛開始學習DELPHI,有許多的問題和困惑,以后還請您多多關照!

    jzrxy771212@sohu.com

    你有QQ嗎?,能發給我嗎?
    感覺還有好多問題想請教你

    再次謝謝你!  回復  更多評論
      

    # re: Delphi控件開發淺入深出(八) 2005-11-24 15:41 Java & Delphi 聯合王國
    我的qq:57077490  回復  更多評論
      


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: free哆拍拍免费永久视频 | 67194成是人免费无码| 色屁屁www影院免费观看视频| 99久久久国产精品免费无卡顿| 免费a在线观看播放| 亚洲色在线无码国产精品不卡 | 国产成人涩涩涩视频在线观看免费| 亚洲AV无码一区二区三区在线| 美女视频黄的全免费视频网站| 亚洲国产成人精品无码一区二区 | 亚洲欧洲国产日韩精品| 免费精品无码AV片在线观看| 亚洲成AⅤ人影院在线观看| 日本系列1页亚洲系列| 亚洲国产香蕉人人爽成AV片久久| 中文字幕在线观看亚洲视频| 无码av免费一区二区三区试看| 亚洲欧洲日韩国产综合在线二区| 91精品免费在线观看| 蜜桃传媒一区二区亚洲AV | 亚洲国产二区三区久久| 亚洲高清免费在线观看| 2017亚洲男人天堂一| 免费一级毛片一级毛片aa| 99在线视频免费观看| 亚洲免费闲人蜜桃| 免费a级毛片在线观看| 久久久久久AV无码免费网站| 亚洲人成77777在线播放网站不卡 亚洲人成77777在线观看网 | 国产亚洲情侣一区二区无| 曰批全过程免费视频在线观看无码 | 久久永久免费人妻精品下载 | 国产AV无码专区亚洲AV手机麻豆| 久久国产免费一区| 亚洲另类无码一区二区三区| 亚洲乱亚洲乱妇无码麻豆| 免费看黄视频网站| 国产裸体美女永久免费无遮挡| 91亚洲自偷在线观看国产馆| 四虎影视永久免费视频观看| 91视频免费网址|