<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

    #

    博客開張了!
    以后會把我的一些經驗&一些想法發上來的,共同學習共同進步。主要是java&Delphi方面的吧,Delphi用了有將近三年了,用它做了兩個項目(都是呼叫中心),做了N多的小軟件,以后會陸續把他們貼上來的。現在在深圳一家比較有名的軟件工作做開發,用的是java,公司的自主研發的MDA平臺確實不錯,自己偷偷的學了不少東西,也模仿著做了一些東西,其中的各種感想也會及時與大家交流的。
    posted @ 2005-10-22 00:03 CowNew開源團隊 閱讀(310) | 評論 (1)編輯 收藏

     

    問世間情為何“物”

    ―――情人節的禮物

    發表于《電腦愛好者20032月刊》

    又一個情人節到了,阿當的MM非要阿當寫封情書送給她,說什么阿當平常工作忙,不浪漫,忽視她………阿當在強大的“武力”壓迫之下只有屈服!可是已經“封筆”多年的阿當寫情書真是個不小的難題呀,不過阿當就是阿當,他又打起了電腦的注意……

    專為不同階段,量身定做――唯美情書

    初戀時期,情書是愛的鼓動力;熱戀時期,情書是愛的奠基石;狂戀時期,情書是愛的醒腦劑;失戀時期,情書是起死回生的救命劑;成功時期,情書是愛的贊美詩(特別披露阿當之三“狗”階段:先是“癩皮狗”,再來是“哈巴狗”,最終進入“狼狗”,目前阿當正在向著“狼狗”這一偉大目標前進^O^)。情書在不同時期自然內容也不大相同啦,軟件內的上百封情書就是根據處于不同戀愛時期的人士而設計的。本軟件可將寫好的情書打包成EXEhtml,阿當覺得這個功能真的不錯,阿當的MM對電腦勉強來說是個菜鳥,直接生長EXE文檔,對她可方便多了,阿當也省去了很多解釋時的口水了^O^

    海量情書庫――魔術情書

    一萬封以上的情書,還可隨意擴充,真是海量呀,就憑這一點,阿當當然要重點推薦一下啦。軟件更精選了一百多封中外經典情書,可以任您使用。比較有趣的,軟件提供了發送匿名情書的功能,怎么樣,給你暗戀中的MM一個驚喜吧,如果還搞不定的話,那……(阿當也沒辦法啦^O^

    讓你的情書“開口說話”――浪漫情書(LoveLetter

    現在情書也可以“有聲有色”了,怎么樣?把“I LOVE YOU”“說”出來,MM不高興才怪,來試試這個軟件吧,它可是帶有一個強大的情話庫呀。

    “情書精靈”是軟件的一大特色,在第一次使用這個軟件的時候,您可對它進行設置,對于到底有什么用,您快去試試吧!

    它能及時地提醒您使用的方法。當您第一次使用“浪漫情書”時會出現一個初始化界面,您可以在其中輸入對她的稱呼、您的落款等信息。您還可以對它選擇你喜歡的情話庫!

    兩個人的世界,加密你的情書――心跳情書

    該軟件的情書書寫方法包括:組合式書寫,模板式書寫,英文情書書寫,腳本編程書寫,電腦自動書寫。如何?連英文的都可以寫呀,國外的MM……它還能對情書加密,這個功能不錯吧。這種東東除了心愛的MM外怎么可以給別人看呢。這個軟件的另一個“神奇”之處大家猜一猜在哪兒?去看看幫助文件吧,里面的東東保證你非常受用!

    戀愛物語之情書殺手BOY:內附“戀愛密技”,阿當很是受用,不可不看。

    情書.net:網戀必備之利器,能夠讓人歡喜讓人憂,不可不備。

    情書生成器:阿當使用的第一個情書軟件,全windows界面,一看就懂,寫出的情書可以說是至幽至默。

    posted @ 2005-10-21 23:54 CowNew開源團隊 閱讀(308) | 評論 (0)編輯 收藏


    1 光宗耀祖
    小菜同志近日迷戀上了編程,整天泡在電腦前忙的不亦樂乎。不過我發現昨天他好像一個晚上沒有睡好,今天又神神秘秘的,還要我陪他去他祖父的墓地。到了墓地,他沖著他祖父的墓碑磕了三個響頭,最里邊不知在嘟囔著什么,好像在說“光宗耀祖”、“請爺爺在天之靈為我保佑”之類的話,而且還流著眼淚。我怕他出事,就問他怎么了?他想了半天,才說:“兄弟,咱哥倆從小長到大,這次小弟我求大哥您一件事。”。“什么事呀?你說吧!”,我說。“你編程水平不錯,我又有商業頭腦,咱們開個軟件公司吧!”。“好呀,當然好了!不過咱們做什么東西呢?”,我問。他又一言不發,顯得很激動,過了好久才說:“咱們回家再說吧!”。
    到了他家,他急忙打開電腦,啟動Delphi,打開了一個他做的Delphi源碼,上面放著一個webbrowser控件和一個Edit輸入框。他很激動地說:“大哥,我昨天才發現做一個瀏覽器也并不是很難,只用一個控件就能辦到!所以,我想……我想成立一個軟件公司,專門做網頁瀏覽器!打敗微軟!為網景報仇!微軟呀微軟,我做的瀏覽器不比你的差!你用了這么多年開發IE,而我利用Delphi就能很快很好的做出來!我要挑戰微軟!祖輩呀!列祖列宗呀!我要光耀門楣了!我要打敗微軟了!”。這時他明顯已經處于癲狂狀態。我聽到這個,差點把肚皮笑破,不過我還是忍住了笑,假裝一本正經地說:“好呀!我也有個點子!”。說著,我把MediaPlayer控件裝到了Delphi地組件面板上,然后用了不到一分鐘,就“做”出了一個播放器,這時我發現他地眼都綠了。他狂叫著:“微軟呀,微軟!我也要在播放器領域與你分一倍羹!一分鐘做一個播放器,你們的開發人員能做到嘛?兄弟,你任我們公司多媒體開發部的經理!”,我聽了之后就暈了過去。過了半晌才醒過來。我剛睜開眼睛,就發現他正在擺弄著RealPlayer控件,并且用近乎神經質的聲音大喊著:“RealNetworks公司!你們也完了!列祖列宗呀!……”,還沒聽完,我又暈了過去。
    2 遞歸
    小菜同志經過兩個月的治療,終于回到了正常人的狀態。這兩天又開始學習編程。有一天他向我請教怎么求一個數的階乘,我隨口答道:“用遞歸!”,然后我就出去做別的事情去了。過了好半天我才回來,發現他正在電腦前忙乎著。見我進來,他狂嘯到:“什么遞歸呀!根本找不到遞歸這個控件!”,我再暈。
    3 大徹大悟
    小菜同志這兩天功力見長,目光已經不局限于一門語言。受“聰明的程序員用C++理解Delphi”思想的指導,開始研習C++。一日,見小菜同志在電腦前冥思苦想,他見我進來了,馬上裝出大徹大悟狀:“噢!這段C++代碼寫得不錯呀!又規范,效率又高!不錯!不錯!”。我走上前去,看見屏幕上顯示著:
    “package mypic
    import java.awt.*;
    ......”

     

     

    posted @ 2005-10-21 23:51 CowNew開源團隊 閱讀(410) | 評論 (0)編輯 收藏

     

    八講的內容這么快就講完了,通過這八講相信大家對于Delphi控件開發有了大體的了解。但是僅僅了解還不夠,要自己去發現:我做的程序中有沒有可以提煉成控件的東西?一旦發現有可以提煉成控件的東西,就要盡力將它抽象化成控件。這樣將能成倍甚至成十倍的提高系統的開發進度。
      這篇文章其實是我去年寫的,當時發在了我的個人網站上,但是由于空間到期了,我就一直沒有理他。昨天注冊了一個blog,所以想把這些東西再放出來,希望能給需要它的朋友帶來一點幫助。

      我在實際的開發系統中開發了很多實用的控件,這些組件列表如下:
    1、BigStringContainer:可以在程序中以資源的形式嵌入大尺寸的字符串,比如一篇文章,并且通過一個屬性就讀取出來。
    2、BrowseComputerDlg:選擇局域網中的所有計算機的對話框。
    3、CheckTreeView:節點前帶復選框的樹控件。
    4、DataSet2Excel:將DataSet中的數據導出為Excel文件。
    5、DataSetHTMLProducer:將DataSet中的數據導出為HTML。
    6、DBDateTimepk:可以做數據綁定的日期、時間選擇控件。
    7、DBLabelEdit:帶Label標簽的文本框,可以做數據綁定。
    8、DBOperatTool:帶有"添加""刪除""修改"“確認”“取消”的按鈕的數據庫操縱工具面板。其中【刪除】按鈕點擊的時候還會彈出一個帶“下次不再顯示此對話框”的確認對話框。
    9、DBSelectDlgEdit:此控件可以用來選擇數據庫中已有的數據,是彈出對話框選擇。
    10、ExcelCreator:可以生成Excel文件,在沒有安裝Excel的機器上也無可以運行。
    11、IconContainer:可以在程序中以資源的形式嵌入圖標,并且通過一個屬性就讀取出來。
    12、LincoClock:表盤時鐘控件。
    13、PopupMsg:像QQ一樣可以在右下角彈出消息框,并且會超時自動縮回。
    14、qqpanel:QQ風格的面板。
    15、selectdirdlg:選擇文件夾目錄的對話框控件。
    16、switch:長得像按鈕開關一樣的控件。
    17、sysMenu:可以將一個PopMenu設置到窗口的系統菜單中顯示,和“最大化”、“最小化”那些菜單在一起。
    18、trayicon:原創的系統拖盤圖標控件。比市面上流行的TrayIcon更小巧,功能一點都不弱,安裝也更加簡單。
    19、urllabel:長得像超鏈接的Label,用戶點擊label的時候自動打開網址。
    20、URLRichEdit:自動識別超鏈接并添加下劃線的URLRichEdit控件。
    21、窗口設計器,可以實現類似于Delphi那樣的控件拖放效果。

    以上控件、源碼每份30元(不帶售后服務,只提供源碼),如果需要提供售后服務每份再加30元,售后服務只包括安裝、使用指導、修改Bug等售后服務,不包括增加新功能、修改功能、講解代碼等,如果需要安裝、使用指導、修改Bug等售后服務,費用面議。

    以上源碼打包購買只需要300元,另加200元提供售后服務(不包括增加新功能、修改功能、講解代碼等)。

    以上代碼是個人開發,從未上傳到網上,因此不用費勁去網上找泄露版,找不到的。這么長的《Delphi控件開發淺入深出》系列文章已經免費提供了,希望大家能夠諒解。上面的源碼、控件都是我的心血之作,我免費提供是我的無私之心,收費提供是我的本分,因此請不要說黑不黑的問題,花幾百元買一件衣服怎么從來沒有罵過服裝商黑呢?我也要養家。

    購買請到CowNew的淘寶網店: http://item.taobao.com/auction/item_detail.jhtml?x_id=0db2&item_id=2ee8dc9c5459bd770f598989568ce745

    比如需要購買DataSet2Excel和PopupMsg的源碼,并且需要購買PopupMsg的售后,只要拍下3件“CowNew技術服務”即可,拍下后我們將盡快向你提供源碼和售后服務.我們還支持手機充值卡支付,詳見http://www.rupeng.com/index.php/action-channel-name-pengbishop

    posted @ 2005-10-21 23:49 CowNew開源團隊 閱讀(2818) | 評論 (26)編輯 收藏

    ?

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

    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 @ 2005-10-21 23:39 CowNew開源團隊 閱讀(2940) | 評論 (4)編輯 收藏

    ?

    對話框控件的制作

    Delphi中有很多對話框組件,例如TopenDialogTfontDialog等。這些控件的特點就是雖然是不可視控件,但是在運行時都有一個可視化的效果,比如TopenDialog的可視化效果就是一個打開對話框。我們這次將開發一個日期對話框控件,當我們調用控件的Execute方法(不一定非要使用Execute方法,不過大部分對話框控件都是使用這個方法,我們也就按照慣例來了)時,就會彈出一個可以選擇日期的對話框,我們選擇一個日期后,點擊“確定”則Execute返回True,點擊“取消”則Execute返回False。我們可以讀取Date屬性來得到用戶選擇的日期,也可以修改此屬性來改變對話框的初始日期。

    1、新建一個對話框。在對話框窗體上放置一個TmonthCalendar組件,命名為Cal,窗體名稱改為FormDate。在窗體上放置兩個按鈕,一個按鈕的Caption為“確定(&O)”,ModalResultmrOk,一個按鈕的Caption為“取消(&C)”,ModalResultmrCancel。設計好的窗體如下圖所示:

    delphicomdev7-1.jpg

    2、為窗體添加兩個Public訪問級的方法:

    ??? function GetSelDate: TDate;

    ??? procedure SetInitDate(AValue: TDate);

    代碼如下:

    function TFormDate.GetSelDate: TDate;

    begin

    ? result := cal.Date;

    end;

    ?

    procedure TFormDate.SetInitDate(AValue: TDate);

    begin

    ? cal.Date := AValue;

    end;

    3、新建一個控件,派生自Tcomponent

    代碼如下:

    unit DateDialog;

    ?

    interface

    ?

    uses

    ? SysUtils, Classes, Controls, frmDlg;

    ?

    type

    ? TDateDialog = class(TComponent)

    ? private

    ??? FDlg: TFormDate;

    ??? function GetDate: TDate;

    ??? procedure SetDate(AValue: TDate);

    ? protected

    ? public

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

    ??? function Execute: Boolean;

    ? published

    ??? property Date: TDate read GetDate write SetDate;

    ? end;

    ?

    procedure Register;

    ?

    implementation

    procedure Register;

    begin

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

    end;

    constructor TDateDialog.Create(AOwner: TComponent);

    begin

    ? inherited Create(AOwner);

    ? FDlg := TFormDate.Create(self);

    end;

    ?

    function TDateDialog.Execute: Boolean;

    begin

    ? result := (FDlg.ShowModal = mrOK);

    end;

    ?

    function TDateDialog.GetDate: TDate;

    begin

    ? result := FDlg.GetSelDate;

    end;

    ?

    procedure TDateDialog.SetDate(AValue: TDate);

    begin

    ? FDlg.SetInitDate(AValue);

    end;

    end.

    代碼比較簡單就不多解釋了。

    思考題:

    1、做一個模仿TcolorDialog的對話框控件。

    posted @ 2005-10-21 23:37 CowNew開源團隊 閱讀(1461) | 評論 (0)編輯 收藏

    ?

    六、控件手拉手――控件關聯的實現

    控件的關聯在Delphi中也是很常見的,我們可以設定一個控件的某個屬性指向另一個控件。比如我們在窗體上放上Tedit,TpopupMenu兩個控件,然后設定TeditPopupMenu屬性為TpopupMenu控件,運行后在Tedit點擊右鍵就會彈出剛才設定的那個TpopupMenu菜單,也就是說Tedit,TpopupMenu聯手完成了任務。再比如TDBEdit控件的DataSource屬性就可以指向一個TdataSource控件,這樣就可以在TDBEdit控件中顯示TdataSource輸出的某個字段的值了。

    ? 下面我們將寫一個簡單的實現控件關聯的控件。這個控件派生于Tedit,它可以與一個Tlabel控件關聯,在控件的編輯框中輸入文字時,與它關聯的Tlabel控件的文字將隨著它而變化。代碼如下:

    unit MyEdit;

    interface

    uses

    ? SysUtils, Classes, Controls, StdCtrls;

    type

    ? TMyEdit = class(TEdit)

    ? private

    ??? FLinkLabel: TLabel;

    ??? procedure FSetLinkLabel(AValue: TLabel);

    ? protected

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

    ????????? override;

    ??? procedure Change;override;

    ? public

    ? published

    ??? property LinkLabel: TLabel read FLinkLabel write FSetLinkLabel;

    ? end;

    ?

    procedure Register;

    ?

    implementation

    procedure Register;

    begin

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

    end;

    procedure TMyEdit.Change;

    begin

    ? inherited;

    ? if LinkLabel <> nil then

    ??? LinkLabel.Caption := Text;

    end;

    ?

    procedure TMyEdit.FSetLinkLabel(AValue: TLabel);

    begin

    ? FLinkLabel := AValue;

    ? if AValue <> nil then

    ??? FLinkLabel.FreeNotification(self);

    end;

    ?

    procedure TMyEdit.Notification(AComponent: TComponent;

    ? Operation: TOperation);

    begin

    ? inherited;

    ? if (Operation = opRemove) and (AComponent = LinkLabel) then

    ??? LinkLabel := nil;

    end;

    end.

    代碼解釋:

    1)、我們只要將控件的任意一個屬性的類型設定為另外一個控件的類名稱,那么我們就可以在控件的Object Inspector中將這個屬性指向那個控件(或那個控件的派生控件)的一個實例。比如本例中我們增加了LinkLabel屬性,它的類型為 Tlabel,所以我們就可以把LinkLabel屬性指向一個標簽控件。

    2)、請注意FsetLinkLabel中的這段代碼:

    ?if AValue <> nil then

    FLinkLabel.FreeNotification(self);

    如果我們將控件關聯屬性指向了一個控件,可是后來又將被指向的控件刪除了,那么我們的控件關聯屬性是不會自動刪除的,這樣就會造成控件關聯屬性指向的控件不存在的現象。我們必須自動感知被關聯控件的刪除并重新設定控件關聯屬性為不指向任何控件,這樣就避免了錯誤的發生。

    FLinkLabel.FreeNotification(self);的作用就是這樣的。它調用控件的FreeNotification方法(在Tcomponent中定義)向被指向的控件注冊一個“消息”,當被指向控件被刪除時,會向所有向他注冊的控件發送一個它被刪除的消息,此時向他注冊的控件就會觸發Notification方法,這樣我們就可以自動感知被指向控件的狀態了。這是設計模式中Observer(觀察者)模式的典型應用。

    既然向他注冊的控件就會觸發Notification方法,我們就覆蓋父類的Notification方法,寫出如下的代碼:

    ? if (Operation = opRemove) and (AComponent = LinkLabel) then

    ??? LinkLabel := nil;

    這句話的意思是:如果控件被刪除并且被刪除的控件(因為我們的控件可能向多個控件注冊了消息)是LinkLabel,那么我們就設定LinkLabel屬性不指向任何控件。

    3)覆蓋父類的Change調度方法。在此方法里為連接的LinkLabelCaption賦值就達到我們的目的了。

    思考題:

    1、做一個Label控件,給它增加一個DataSource屬性,該屬性可以指向一個TdataSource類型的控件,它有一個GetRecordCount方法。當調用此方法時,就在Label控件中顯示這個DataSource對應的數據集中的記錄的條數。

    posted @ 2005-10-21 23:34 CowNew開源團隊 閱讀(2141) | 評論 (0)編輯 收藏

    ?

    五、復合控件

    復合控件是Delphi控件中非常重要的一種控件,復合控件就是將兩個或兩個以上的控件重新組合成一個新的控件。例如TspinEditTlabeledEditTDBNavigator等就是復合控件,TDBNavigator其實就是在一個Panel放上若干個Button而已。制作一個復合控件時,我們一般從TwinControl派生控件。

    我們這次做的控件是擁有一個Edit編輯框和一個Button按鈕的復合控件,在用戶在編輯框中輸入文字的過程中,Button將隨時顯示編輯框中文字的長度。我們把控件的源碼先展示給大家。

    unit EditButton;

    interface

    uses

    ? SysUtils, Classes, Controls, StdCtrls, Messages;

    type

    ? TEditButton = class(TWinControl)

    ? private

    ??? FEdit: TEdit;

    ??? FButton: TButton;

    ??? FText: string;

    ??? procedure FSetText(AValue: string);

    ??? procedure OnEditChange(Sender: TObject);

    ? protected

    ??? procedure WMSize(var Msg: TMessage);message WM_SIZE;

    ? public

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

    ??? destructor Destroy;override;

    ? published

    ??? property Text: string read FText write FSetText;

    ? end;

    ?

    procedure Register;

    implementation

    ?

    procedure Register;

    begin

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

    end;

    ?

    constructor TEditButton.Create(AOwner: TComponent);

    begin

    ? inherited;

    ? FEdit := TEdit.Create(nil);

    ? FEdit.Parent := self;

    ? FEdit.Top := 0;

    ? FEdit.Left := 0;

    ? FEdit.Height := Height;

    ? FEdit.Width := Width div 2;

    ? FEdit.OnChange := OnEditChange;

    ? FButton := TButton.Create(nil);

    ? FButton.Parent := self;

    ? FButton.Top := 0;

    ? FButton.Left := Width div 2;

    ? FButton.Height := Height;

    ? FButton.Width := Width div 2;

    end;

    ?

    destructor TEditButton.Destroy;

    begin

    ? FEdit.Free;

    ? FButton.Free;

    ? inherited;

    end;

    ?

    procedure TEditButton.FSetText(AValue: string);

    begin

    ? FEdit.Text := AValue;

    end;

    ?

    procedure TEditButton.OnEditChange(Sender: TObject);

    begin

    ? FButton.Caption := IntToStr(Length(FEdit.Text));

    end;

    ?

    procedure TEditButton.WMSize(var Msg: TMessage);

    begin

    ? FEdit.Height := Height;

    ? FEdit.Width := Width div 2;

    ? FButton.Left := Width div 2;

    ? FButton.Height := Height;

    ? FButton.Width := Width div 2;

    end;

    end.

    代碼解釋:

    1)、我們首先定義了兩個變量??

    ?? ?FEdit: TEdit;

    ??? FButton: TButton;

    ? 分別代表復合控件中的文字編輯框和按鈕。

    2)所謂復合控件說簡單一點就是在一個共同的基板上將組成復合控件的各個控件(可以叫做子控件)畫出來。所以我們在構造函數中建立各個子控件,然后分別設定它們的位置等屬性。

    以文字編輯框為例:

    FEdit := TEdit.Create(nil);

    的作用是建立編輯框控件。如果Create的參數指定為nil,則子控件在設計狀態是可以響應用戶的操作的;而如果設定為self(即設定子控件的父控件為基板),則子控件在設計時時不可響應用戶操作的,如果設定為self則析構函數中就不用Fedit.Free來銷毀對象了,對象會自動銷毀。

    ? FEdit.Parent := self;的作用是設定子控件的父控件,如果沒有這一句則控件是無法顯示的。

    ? FEdit.Top := 0;

    ? FEdit.Left := 0;

    ? FEdit.Height := Height;

    ? FEdit.Width := Width div 2;

    這四句是設定控件在基板上的相對位置的,這里的Top,Left不是相對于窗體的,而是相對于基板的。

    ? FEdit.OnChange := OnEditChange;

    則是設定編輯框控件的OnChange(文字改變事件)的處理句柄為OnEditChange

    (1)??? 用戶有可能在設計時或運行時通過代碼改變控件的大小,這時控件中子控件的順序就會變得亂七八糟,所以需要相應控件的WM_SIZE事件(控件大小發生變化的事件)重新設定子控件的位置,大小等。函數WMSize的作用就是這樣的。

    安裝控件后發現控件已經可以正確運行了,但是還有一個問題,就是這個控件沒有了Onclick,Onchange等必須的屬性。我們只要為控件增加事件處理句柄屬性,然后把事件處理句柄屬性的讀寫方法都指向子控件的事件處理句柄屬性即可。例如我們為控件增加OnClick事件,這個事件發生在用戶單擊按鈕時,我么只要在Pulished部分增加如下代碼:

    property? OnClick:? TnotifyEvent read GetOnClick write SetOnClick

    Private中增加如下方法聲明:

    function GetOnclick: TnotifyEvent;

    procedure SetOnclick(AValue: TnotifyEvent);

    這兩個方法的實現分別為:

    function? TeditButton. GetOnclick: TnotifyEvent;

    begin

    ? result := Fbutton.Onclick;

    end;

    procedure TeditButton. SetOnclick(AValue: TnotifyEvent);

    begin

    ? Fbutton.OnClick := Avalue;

    end;

    思考題:

    1、做一個模仿播放器中的操作按鈕的復合控件,控件由三個按鈕組成,分別是“播放”、“暫停”、“停止”,請按照正常的邏輯關系,處理這三個按鈕的可用/不可用關系。(提示:可以參考TDBNavigator的源代碼)

    posted @ 2005-10-21 23:32 CowNew開源團隊 閱讀(3252) | 評論 (0)編輯 收藏

    ?

    四、對特定字符串敏感的Edit控件

    我們這個控件將演示控件的自定義事件的書寫。這個控件有一個類型為stringSensitiveText屬性,當用戶在輸入框中輸入的文字為InvalidText時就會觸發OnSensitiveText事件。按照慣例,我先把源碼展示給大家:

    unit TextSenseEdit;

    ?

    interface

    ?

    uses

    ? SysUtils, Classes, Controls, StdCtrls;

    type

    ? TSensitiveTextEvent = procedure(AText: string) of object;//方法指針

    ? TTextSenseEdit = class(TEdit)

    ? private

    ??? FSensitiveText: string;

    ??? FOnSensitiveText: TSensitiveTextEvent;

    ??? procedure SetSensitiveText(AValue: string);

    ? protected

    ??? procedure Change;override;

    ? public

    ? published

    ??? property SensitiveText: string read FSensitiveText write SetSensitiveText;

    ??? property OnSensitiveText: TSensitiveTextEvent read FOnSensitiveText write FOnSensitiveText;

    ? end;

    ?

    procedure Register;

    ?

    implementation

    ?

    procedure Register;

    begin

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

    end;

    procedure TTextSenseEdit.Change;

    begin

    ? inherited;

    ? if Text = SensitiveText then

    ??? if Assigned(OnSensitiveText) then

    ????? OnSensitiveText(Text);

    end;

    ?

    procedure TTextSenseEdit.SetSensitiveText(AValue: string);

    begin

    ? FSensitiveText := AValue;

    end;

    end.

    代碼解釋:

    1)、SensitiveText屬性的添加方法大家已經熟悉了,這里不多解釋。

    2)、正如大家猜測的,Change方法正是編輯框文字發生變化時的調度方法,它將引起OnChange事件。我們可以在這個方法中監控編輯框文字發生的變化,當文字等于SensitiveText就觸發OnSensitiveText事件(具體的實現方法在后邊解釋)。

    3)、Delphi中的控件的事件機制是通過方法指針來實現的。聲明方法指針的格式為:

    方法指針名稱 = procedure(參數列表) of object;

    聲明事件屬性的方法與聲明普通屬性的方法相同。在我們這個例子中,我們首先聲明一個FOnSensitiveText: TSensitiveTextEvent;私有變量,然后property OnSensitiveText: TSensitiveTextEvent read FOnSensitiveText write FOnSensitiveText; 聲明事件屬性。這樣注冊控件后,當用戶把控件放到窗體中后,就會在Object InspectorEvnets頁中出現OnSensitiveText事件,我們就可以像使用其他事件一樣使用這個事件了。

    ? 但是我們現在只是聲明了一個事件屬性,并沒有書寫任何代碼來激發這個事件。我們應該在合適的時候激發此事件,顯而易見我們應該在Change方法中激發此事件:

    procedure TTextSenseEdit.Change;

    begin

    ? inherited;

    ? if Text = SensitiveText then

    ??? if Assigned(OnSensitiveText) then

    ????? OnSensitiveText(Text);

    end;

    if Text = SensitiveText時就判斷控件使用者是否為OnSetSensitiveText寫代碼了(準確的說是是否為OnSetSensitiveText事件句柄賦值了),如果寫代碼了則調用OnSetSensitiveText(Text);來激發OnSetSensitiveText事件,并把控件的Text傳遞給方法的Avalue參數。正如“方法指針”這個名字一樣,被聲明為方法指針類型的變量可以當作方法使用,用來激發事件。VCL已經為我們預定義了一些常用的事件句柄,我們直接拿來使用:TnotifyEventTmouseEventTmouseMoveEventTkeyPressEvent等,具體可以參考VCL源碼。

    思考題:

    1、做一個支持累加運算的文本編輯框控件,用戶可以在編輯框中輸入正整數。當用戶按回車時,如果編輯框中輸入的不是正整數(為負數、小數或一般字符串)則觸發控件的OnError事件;如果輸入的是正整數,則開始計算從1到用戶輸入的那個正整數中所有整數的和(用123+……這種累加的辦法實現,不要用(1+n)*n/2這種直接計算的方法),并且在計算工程中如果發現計算的中間結果位數是5,則觸發OnTailFive事件。

    posted @ 2005-10-21 23:30 CowNew開源團隊 閱讀(1587) | 評論 (0)編輯 收藏

    ?

    三、開關控件TlincoSwitch

    用過Delphi1(好古老的東東呀!)的人相信都記得這個開關控件 r_delphicomdev3-1.jpg,不知道當初Borland為什么把這么一個在開發普通應用程序中應用不到的工控控件放到Delphi中,而且在Delphi2及其以后的版本中再也沒有見過它的身影。讓我們懷著懷舊的心情把這位“開國元老”請出來吧!

    1、建立位圖資源文件:

    Image Editor建立一個Res文件,并在文件中分別建立下面兩個位圖r_delphicomdev3-1.jpgr_delphicomdev3-2.jpg,并分別命名為SWITCHONSWITCHOFF。保存此Res到控件單元所在目錄下。

    2、寫控件代碼。

    unit LincoSwitch;

    interface

    uses

    ? SysUtils, Classes, Controls, Graphics, Windows;

    ?

    type

    ? TLincoSwitch = class(TCustomControl)

    ? private

    ??? FIsOn: Boolean;

    ??? FPicOn: Graphics.TBitmap;

    ??? FPicOff: Graphics.TBitmap;

    ??? procedure FSetIsOn(AValue: Boolean);

    ? protected

    ??? procedure Click;override;

    ??? procedure Paint;override;

    ? public

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

    ??? destructor Destroy;override;

    ? published

    ??? property IsOn: Boolean read FIsOn write FSetIsOn;

    ??? property OnClick;

    ??? property OnKeyDown;

    ??? property OnKeyPress;

    ??? property OnKeyUp;

    ??? property OnCanResize;

    ??? property OnDblClick;

    ??? property OnMouseDown;

    ??? property OnMouseMove;

    ??? property OnMouseUp;

    ??? property OnMouseWheel;

    ??? property OnResize;

    ? end;

    ?

    procedure Register;

    implementation

    {$R *.res}

    procedure LoadBitmapFromRes(ABitmapId: string; ABitmap: Graphics.TBitmap);

    begin

    ? ABitmap.LoadFromResourceName(hInstance, ABitmapId);//從資源文件中讀取位圖

    end;

    ?

    constructor TLincoSwitch.Create(AOwner: TComponent);

    begin

    ? inherited Create(AOwner);

    ? FPicOn := Graphics.TBitmap.Create;

    ? FPicOff := Graphics.TBitmap.Create;

    ? LoadBitmapFromRes('SWITCHON', FPicOn);

    ? LoadBitmapFromRes('SWITCHOFF', FPicOff);

    ? Invalidate;

    end;

    ?

    destructor TLincoSwitch.Destroy;

    begin

    ? FPicOn.Free;

    ? FPicOff.Free;

    ? inherited;

    end;

    ?

    procedure TLincoSwitch.Click;

    begin

    ? IsOn := not IsOn;//改變按鈕的狀態

    ? Invalidate;

    ? inherited;

    end;

    ?

    procedure TLincoSwitch.Paint;

    begin

    //畫開關圖案?

    if IsOn then

    ???

    ????? StretchBlt(Canvas.Handle, 0, 0, self.Width, self.Height, FPicOn.Canvas.Handle,

    ???????????? 0, 0, FPicOn.Width, FPicOn.Height,SRCCOPY)

    ? else

    ????? StretchBlt(Canvas.Handle, 0, 0, self.Width, self.Height, FPicOff.Canvas.Handle,

    ???????????? 0, 0, FPicOff.Width, FPicOff.Height,SRCCOPY);

    end;

    ?

    ?

    procedure TLincoSwitch.FSetIsOn(AValue: Boolean);

    begin

    ? FIson := AValue;

    ? Invalidate;

    end;

    ?

    procedure Register;

    begin

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

    end;

    end.

    3、代碼分析

    ? 1)、因為我們要在控件表面上將按鈕的圖案畫出來,所以我們選擇TcustomControl做為父類控件,因為它有個Canvas屬性,我們可以利用Canvas在控件表面作圖。不選用Tcontrol的原因是因為它有很多我們不需要的屬性。

    2)、ABitmap.LoadFromResourceName(hInstance, ABitmapId);是從資源文件中讀取IdAbitmapId的位圖,關于資源文件的使用請參考其他相關資料。注意代碼中的“{$R *.res}”,它的作用是將資源文件編譯到程序文件中,如果沒有這個預編譯條件,程序將會出現錯誤。

    3)、StretchBlt是將位圖畫到畫板上,使用方法請參考MSDN

    4)、我們為控件增加了IsOn屬性。這個布爾屬性用來表示開關的狀態(開/關)。

    property IsOn: Boolean read FIsOn write FSetIsOn;我們可以看出這個屬性是個可讀可寫的屬性。當讀這個屬性時會將FisOn的值返回給調用者,而寫屬性時則會調用FsetIsOn方法,并將賦給屬性的值做為參數傳遞給FsetIsOn。在FsetIsOn方法中,有如下實現代碼:

    ? FIson := AValue;

    ? Invalidate;

    首先將Fison設置為參數傳遞來的值,然后調用? Invalidate;要求重畫控件,以告訴用戶控件的狀態已經改變,這一點是使用寫字段無法做到的。

    5???

    ??? FPicOn: Graphics.TBitmap;

    FPicOff: Graphics.TBitmap;

    是聲明兩個.Tbitmap類型變量以保存控件的開關兩種狀態的圖案。

    6

    ??? procedure Click;override;

    procedure Paint;override;

    分別是覆蓋父類中相應的調度方法。當控件被鼠標單擊時,Click方法會被調用,我們將在Click中改變控件的開關狀態;Paint方法則在用戶調用? Invalidate方法或控件發生重畫時調用,我們一般在這個方法繪制控件的圖案。

    7)、TcustomControl中又很多事件處理句柄。比如OnClickOnKeyDown等,但是它把他們聲明成了Protected保護級別,所以我們在Object Inspector中看不到他們,如果我們要他們可以在Object Inspector中被用戶編輯的話,只要在Published中重新聲明他們即可,不用寫他們的讀寫方法,只要使用:Property? 屬性名;

    這樣的方法就可以。比如這個例子中的:Property Onclick;

    思考題:

    1、??????? 做一個有特效的按鈕控件,當鼠標按下時按鈕是一個紅色邊框的空心圓,當鼠標松開時按鈕是一個淡綠色邊框的空心圓。

    2、??????? 對于父類控件中為protected的屬性,如果想將它在子類控件中公布,應該怎么做?請思考Delphi為什么要將一些屬性設為protected級別?

    posted @ 2005-10-21 23:29 CowNew開源團隊 閱讀(2458) | 評論 (0)編輯 收藏

    僅列出標題
    共30頁: First 上一頁 22 23 24 25 26 27 28 29 30 下一頁 
    主站蜘蛛池模板: 在线观看亚洲免费| 自拍偷自拍亚洲精品第1页| 免费无码又爽又刺激高潮的视频| 国产乱人免费视频| 久久精品国产亚洲AV无码娇色 | 免费真实播放国产乱子伦| 国产亚洲精品国产| 色窝窝亚洲av网| 久久久久久精品成人免费图片 | 久久夜色精品国产嚕嚕亚洲av| 亚洲欧美国产精品专区久久| 亚欧日韩毛片在线看免费网站| 免费无码一区二区三区蜜桃| 色婷婷7777免费视频在线观看| 国产亚洲精AA在线观看SEE| 亚洲AV无码成人网站在线观看| 免费一看一级毛片人| 日亚毛片免费乱码不卡一区| 中文字幕亚洲第一| 日韩免费在线观看视频| 亚洲春色另类小说| 在线观看免费毛片| 十八禁的黄污污免费网站| 亚洲无线码一区二区三区| 97国产在线公开免费观看| 亚洲日本久久久午夜精品| 亚洲AV成人潮喷综合网| 免费无码H肉动漫在线观看麻豆| 亚洲噜噜噜噜噜影院在线播放| 成年在线网站免费观看无广告| 免费无码一区二区| 亚洲欧洲国产精品你懂的| 毛片a级毛片免费观看免下载| 毛片亚洲AV无码精品国产午夜 | 亚洲成A人片在线观看WWW| 亚欧在线精品免费观看一区| 国产亚洲一卡2卡3卡4卡新区 | 亚洲精品无码久久毛片 | 全免费a级毛片免费看无码| 一个人看的免费视频www在线高清动漫 | 特级毛片全部免费播放a一级|