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

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

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

    如鵬網(wǎng) 大學(xué)生計算機(jī)學(xué)習(xí)社區(qū)

    CowNew開源團(tuán)隊

    http://www.cownew.com 郵件請聯(lián)系 about521 at 163.com

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

    八、數(shù)據(jù)敏感控件的制作。

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

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

    相信用Delphi開發(fā)過數(shù)據(jù)庫的人一定對delphi中沒有一個日期數(shù)據(jù)敏感控件而惱火。每次都要我們自己處理數(shù)據(jù)的更新與顯示。所以我們就來開發(fā)一個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.

    ?

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

    既然字段數(shù)據(jù)連接這么重要,我們就先來系統(tǒng)的介紹一下它吧!TfieldDataLink閃亮登場?。?!

    TfieldDataLink的屬性:

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

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

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

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

    5)、property Active: Boolean;表示字段數(shù)據(jù)連接連接的數(shù)據(jù)集是否處于激活狀態(tài)。

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

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

    8)、property DataSet: TDataSet;表示它負(fù)責(zé)維護(hù)的數(shù)據(jù)集。

    方法:

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

    事件:

    1)、property OnActiveChange: TNotifyEvent;當(dāng)Active屬性變化的時候發(fā)生此事件。

    2)、property OnDataChange: TNotifyEvent;當(dāng)數(shù)據(jù)集發(fā)生變化的時候發(fā)生。

    3)、property OnEditingChange: TNotifyEvent;當(dāng)數(shù)據(jù)源從編輯狀態(tài)變?yōu)槠渌麪顟B(tài)或從其他狀態(tài)變?yōu)榫庉嫚顟B(tài)的時候發(fā)生。

    4)、property OnUpdateData: TNotifyEvent;當(dāng)向數(shù)據(jù)庫提交對數(shù)據(jù)庫的修改時發(fā)生此事件。

    代碼分析:

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

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

    procedure TDBDateTimePicker.FSetDataField(AValue: string);

    begin

    ? FDataLink.FieldName := AValue;

    end;

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

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

    procedure TDBDateTimePicker.CMGetDataLink(var Msg: TMessage);

    begin

    ? Msg.Result := Integer(FDataLink);

    end;

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

    procedure TDBDateTimePicker.Change;

    begin

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

    ? begin

    ??? FDataLink.Edit;//設(shè)置數(shù)據(jù)連接為編輯狀態(tài),由這個媒人將數(shù)據(jù)庫綁定的字//段設(shè)置為編輯狀態(tài)

    ??? Field.Value := self.Text;//設(shè)定數(shù)據(jù)字段的值

    ? end;

    ? inherited Change;

    end;

    5)、回頭再來看看構(gòu)造函數(shù)吧!

    ?? ?FDataLink.OnDataChange := DataChange;

    ?? FDataLink.OnEditingChange := EditingChange;

    ? FDataLink.OnUpdateData := UpdateData;

    ? FDataLink.Control := self;

    前三句是設(shè)定響應(yīng)數(shù)據(jù)連接事件處理句柄,正是這三句把數(shù)據(jù)庫中的數(shù)據(jù)與用戶界面聯(lián)系了起來。關(guān)于這三個事件處理句柄的實現(xiàn)請參加源代碼,這里就不多說了。

    思考題:

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

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

    評論

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

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

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

    jzrxy771212@sohu.com

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

    再次謝謝你!  回復(fù)  更多評論
      

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


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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 国产成人yy免费视频| 亚洲日本在线播放| 日韩毛片免费在线观看| a毛片免费播放全部完整| 久久精品国产亚洲AV未满十八| 亚洲色大成网站www永久| 国产gv天堂亚洲国产gv刚刚碰| 在线播放高清国语自产拍免费| 0588影视手机免费看片| 免费一级毛片无毒不卡| 无码免费又爽又高潮喷水的视频| 亚洲人成网站色7799| 亚洲福利一区二区三区| 亚洲AV午夜福利精品一区二区| 亚洲视频人成在线播放| 免费国产不卡午夜福在线| 国产自产拍精品视频免费看| 欧洲精品成人免费视频在线观看 | 国产黄色片在线免费观看| 成人免费大片免费观看网站| 免费A级毛片av无码| 日韩成人免费视频| 国产一级淫片a免费播放口| 中文字幕无码免费久久9一区9 | 国产精品酒店视频免费看| 午夜网站免费版在线观看| 成年人在线免费看视频| 毛片免费全部免费观看| 成年性生交大片免费看| 精品剧情v国产在免费线观看| 成年18网站免费视频网站| 午夜无遮挡羞羞漫画免费| 日本人护士免费xxxx视频| 日韩在线天堂免费观看| 国产精品久久久久影院免费| 免费人成在线观看播放国产 | 在线观看免费亚洲| 香蕉97碰碰视频免费| xxxxx做受大片视频免费| 成人网站免费大全日韩国产| 色播在线永久免费视频网站|