元件製作之二(一個簡單元件的製作過程)

接下來要動手來做一個元件了,我想了一個計數器元件,功能方面是比較簡單的,但這不是本章的重點,這一章的重點是說明一個元件的製作全過程。在其中可以學到很多元件製作的技巧,當然這些也是我從書上學得的。好了,開始製作吧:
 
這是一個可以計數的元件,為了簡單,我以秒為單位,當開始時,他就從0開始增加,並顯示出來,到3600時,它又回到0,如此迴圈。當然它也可以停止,暫 停,繼續。另外,他還有一個時間事件,即可以設定每隔多少時間來觸發這個事件,這倒是一個好的功能,我們可以設半個小時觸發事件,在事件處理函數中來一個 聲音,然後睡個覺,半個小時後,就由這個聲音來提醒你起床了。
 
我們一開始不要新建元件單元,而是把它當成一個工程中的一個類來應用,這樣更易於調試,於是我們新建一個工程,又新建一個空白單元用於放置這個類
 
一、確定父類:

接下來給這個類起名叫TTimeCount,那麼它的父類應該是什麼呢,它要能顯示出來,得有一個容量來讓他顯示,TPanel是個不錯的選擇,我看了一 下源碼,發覺TPanel什麼也沒有做,只是把它的父類TCustomPanel的屬性顯化出來(這個等一下講),TCustomPanel把好多的屬性 聲明為Protected,為他的子類提供了選擇,他的子類如果要使這些屬性能在物件察看器中看到,可以在Published重新聲明一下,如果不想,則 不用去理會他。而我們的計數器元件正好不用那麼多屬性,正好合適。於是我決定用TCusomPanel為父類
類建立如下:
TTimeCount=class(TCustomPanel)
  private
  protected
  public
  published
end;
 
二、確定成員,方法和屬性和事件
 
FCount; 唯讀私有成員,保存計數值
FActive:Boolean; /確定是否發生類的時間間隔事件
FInterval:TInterval; 這個可以設置時間事件觸發間隔,本來用整型值會好一些,但會了學習起見,這裏用了一個枚舉形的,在Type中聲明如下:
TInterval=(TenM,TwentyM,ThirtyM,FortyM,FiftyM,SixtyM);
分別表示十分鐘到六十分鐘。
TimeLen,TimeNum:integer;這兩個用在類的時間事件發生的確定上,與外界隔絕。
FTimeOut:TNotifyEvent;時間間隔事件的方法指針,通過調度方法實現他與外部的處理函數關聯。
 
我們要它能以秒為單位來計數,則要涉及到時間的應用,所以就有了這個最重要的成員:
FTimer:TTimer;
這個成員物件要在類構造函數中實例化它,並賦與他的屬性值,還要在析構函數在釋放它。
如下:

//構造函數,繼承父類的構造函數,並初始化類中的成員。
constructor TTimeCount.Create(AOwner:TComponent);
//創建時間控制項並設置相關的參數
  procedure CreateTimer;
  begin
    FTimer:=TTimer.Create(self);
    FTimer.Enabled:=False;
    FTimer.Interval:=1000;
    FTimer.OnTimer:=FTimerTimer;
  end;
begin
  inherited Create(AOwner);
  CreateTimer;
end;

//析構函數,先釋放時間控制項,再繼承父類的析構函數
destructor TTimeCount.Destroy;
begin
  FTimer.Free;
  inherited Destroy;
end;

構造函數中還要設置該元件的外觀和預設值,這裏把它刪去,到源代碼再貼出來。
其中
FTimerTimer;是很重要的函數,在該類中有聲明:
procedure FTimerTimer(Sender:Tobject);//時間控制項的事件處理函數
在這個處理函數中,實現了計數值的遞增並顯示到容器中,此外,還在判斷類的時間事件是否有足夠條件觸發了,如果有則調用DoTimeOut;過程,這個就是事件的調度函數啦:
//事件調度函數,將外部的事件處理函數和該類的事件方法指針聯繫起來
procedure TTimeCount.DoTimeOut;
begin
  if Assigned(FTimeOut) then
     FTimeOut(Self);
end;
 
而屬性則是根據私有成員來設定了:
public
  property Count:Integer read FCount default 0; //計數值的唯讀屬性,這個屬性不能聲明在Published中,因為它是唯讀的,只在程式運行時通過它來得到計數值。
published
  property Interval:TInterval read FInterval write SetInterval Default TenM;
  property Active:boolean read FActive write SetActive default false;
  property OnTimeOut:TNotifyEvent read FTimeOut write FTimeOut;
 
此外還有幾個自定義方法即
procedure pause; //暫停計數
procedure Resume; //從暫停的計數開始計數。
procedure stop; //停止
procedure start; //開始計數
都比較簡單。
 
三、父類屬性的顯化:
 
TCustomPanel及其父類有好多的屬性設為Protected,使其子類可以有更靈活的選擇,是否把這些屬性顯示到物件察看器中,如果想,則到 Published中重新聲明這些屬性就可以,我參考了一下TPanel的源碼,並按需要選擇了其中的一些屬性聲明到Published中,注意哦,事件 也是屬性,只要你把它顯化出來,就可以設置處理事件了。
 
四、以下是計數元件的源碼,相信有了上面的講解,應該不會很難了:
 
unit CountUnit;

interface

uses
  SysUtils, Classes, Graphics, Controls, ExtCtrls;

type
  //用於設置時間事件發生的間隔
  TInterval = (TenM, TwentyM, ThirtyM, FortyM, FiftyM, SixtyM);

  TTimeCount = class(TCustomPanel)
  private
    FTimer: TTimer;
    FCount: integer; //唯讀私有成員,計數值
    FInterval: TInterval; //時間事件發生的間隔
    FActive: Boolean;  //決定是否發生間隔事件
    TimeLen: Integer;  //發生事件的時間長度,以秒為單位。
    TimeNum: integer; //計數值,和TimeLen一起有用,以判斷是否事件該發生了
    FTimeOut: TNotifyEvent; //事件的方法指針
    procedure SetInterval(I: TInterval);
    procedure SetActive(A: boolean);
    procedure FTimerTimer(Sender: Tobject); //時間控制項的事件處理函數
  protected
    procedure DoTimeOut; dynamic; //調度方法,用於關聯事件。
  public
    procedure pause; //暫停計數
    procedure Resume; //從暫停的計數開始計數。
    procedure stop; //停止
    procedure start; //開始計數
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property Count: Integer read FCount; //計數值的唯讀屬性
  published
    property Interval: TInterval read FInterval write SetInterval default TenM;
    property Active: boolean read FActive write SetActive default false;
    property OnTimeOut: TNotifyEvent read FTimeOut write FTimeOut;
    //顯示祖先類的一些屬性在物件察看器中
    property BevelInner;
    property BevelOuter;
    property BevelWidth;
    property Color;
    property Font;
    property PopupMenu;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property Visible;
    property OnClick;
    property OnDblClick;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
  end;

implementation

//構造函數,繼承父類的構造函數,並初始化類中的成員。
constructor TTimeCount.Create(AOwner: TComponent);
//創建時間控制項並設置相關的參數
  procedure CreateTimer;
  begin
    FTimer := TTimer.Create(self);
    FTimer.Enabled := False;
    FTimer.Interval := 1000;
    FTimer.OnTimer := FTimerTimer;
  end;

  //以下是設置外觀的
  procedure setView;
  begin
    Width := 100;
    Height := 50;
    Color := $000000;
    Font.Color := $FFFFFF;
    Font.Size := 14;
    Font.Style := [fsBold, fsUnderline]; ;
    BevelOuter := bvLowered;
    Caption := '0';
  end;
begin
  inherited Create(AOwner);
  FCount := 0;
  FInterval := TenM;
  FActive := False;
  TimeLen := 600; //十分鐘,六百秒
  TimeNum := 0;
  CreateTimer;
  setView;
end;

//解構函數,先釋放時間控制項,再繼承父類的析構函數

destructor TTimeCount.Destroy;
begin
  FTimer.Free;
  inherited Destroy;
end;

//設置時間事件發生間隔,財時要賦相應的間隔秒數
procedure TTimeCount.SetInterval(I: TInterval);
begin
  if FInterval <> I then
  begin
    FInterval := I;
    case FInterval of
      TenM: TimeLen := 600;
      TwentyM: TimeLen := 1200;
      ThirtyM: TimeLen := 1800;
      FortyM: TimeLen := 2400;
      FiftyM: TimeLen := 3000;
      SixtyM: TimeLen := 3600;
    end;
  end;
end;

procedure TTimeCount.SetActive(A: boolean);
begin
  if FActive <> A then
  begin
    FActive := A;
    TimeNum := 0;
  end;
end;

procedure TTimeCount.pause;
begin
  if FTimer.Enabled then
    FTimer.Enabled := False;
end;

procedure TTimeCount.Resume;
begin
  if not FTimer.Enabled then
    FTimer.Enabled := True;
end;

procedure TTimeCount.stop;
begin
  FTimer.Enabled := False;
  FCount := 0;
  TimeNum := 0;
  caption := '0'
end;

procedure TTimeCount.start;
begin
  if (not FTimer.Enabled) and (TimeNum = 0) then
    FTimer.Enabled := True;
end;

//最重要的時間函數,用於調用該類的事件觸發高度函數。
//以及在容器中顯示計數值
procedure TTimeCount.FTimerTimer(Sender: TObject);
begin
  inc(FCount);
  if (FCount mod 3600) = 0 then FCount := 0;
  Caption := InttoStr(FCount);  //這個就是顯示計數值
  inc(TimeNum);
  if (TimeNum = TimeLen) and (FActive) then
  begin
    DoTimeOut;
    TimeNum := 0;
  end;
end;

//事件調度函數,將外部的事件處理函數和該類的事件方法指針聯繫起來
procedure TTimeCount.DoTimeOut;
begin
  if Assigned(FTimeOut) then
    FTimeOut(Self);
end;

end.

 
五、組件註冊安裝與刪除。
 
元件類編寫完畢,接著就要測試了,這個從略,可以在剛才的工程中動態創建它,設置相應屬性,指定時間事件,看看是否正確。上面是經過測試的。
到確定正確後,就要來看看裝元件的步驟了:
 
首先,我們要把元件單元放在一個指定的檔夾中,以便以後管理,和IDE統一指定路徑。
我在Delphi目錄下新建了MyCom檔夾,用來存放元件單元
然後選:
Component—>New Component;
啟動Component Wizard
在Ancestor type(父類):中填TCustomPanel
Class Name(你的組件類名)中填:TimeCount
Palette Page,默認為Samples,我就用這個吧,當然也可以自己創建一個。
Unit File Name(元件類所在的單元名),就寫TimeCount吧。
Search Path(搜索路徑),必須把上面所建的檔夾路徑包含進去,編譯時才能能過。
點擊旁邊的”…”按鈕,出現一個對話方塊,裏面的編輯框旁邊又有一個”…“按鈕,點擊它出現流覽檔夾框,在其中選中上面建的檔夾的路徑,點確定,再點OK,回去New Component;。

這時再點下面的OK就行啦,出現代碼如下:
unit TimeCount;

interface

uses
  messages, SysUtils, Classes, Graphics, Controls, ExtCtrls;

type
  TTimeCount = class(TCustomPanel)
  private
  published
  public
  published
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TTimeCount]);   //註冊控制項用的函數,自動幫你產生
end;

end.
這時再把上面的元件類替換掉這個類就行啦(當然上面的註冊函數可要保留呀)。然後保存到上面所建的文件夾中。
 
接著就要安裝組件了,點Component->install Component
對話方塊中第一項Unit file Name,是元件單元.pas文件的路徑名字。其他只要按預設值。
記得第三項的。。\delphi7\Lib\dclusr.dpk,這個就是存放元件的專案名稱,等一下刪除組件時用到的
接下來點OK,就可以了,看看Samples是不是有了一個新元件啦。
                   
不過面板上的元件圖示似乎不好看,應該給他一個新的圖示了:
但之前應該把它先從面板刪除,File->Open…打開dclusr.dpk.
選中其中的Contains下的TimeCount.pas,點上面的Remove。將其刪除
然後再點Compile,重新將包編譯一次。就行啦。Samples上的新組件就消失了。
 
接下來是做元件圖示:
打開Image Eidtor,新建一個DCR檔,在其中建一個24×24的點陣圖,畫上你喜歡的圖示,將點陣圖的名字起為元件類名一樣,而且用大寫,即:TTIMECOUNT
將DCR檔起名為元件類所在單元名一樣,而且大寫,即:TIMECOUNT。
保存檔到單元所在的檔夾中,
最後依上面的方法再裝一次,看是不是有一個漂亮的圖示啦
 
 
六、講完了,大家應該有一個清楚的概念了吧,其中涉及到了好多的技巧。在以後的篇章中將不再講這些內容了,只把主要精力花在組件實現技術上。因為我們這個元件還是比較簡單,沒有涉及到多少高級的主題。但沒有關係,跟著我慢慢地做下來,你們會瞭解元件製作的方方面面的。

转载于:https://www.cnblogs.com/jason820/articles/231589.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值