繼上次我們學習開發一個簡單的畫線控件後,基本的制作控件步驟已經清楚了,這次我們繼續加深學習控件的制作。我們打開Delphi 7建立一個應用程式,拖動LineTo控件到窗體上,仔細看左邊的對象設計器,可以看到預設的屬性Properties有11個,而事件Events沒有一個,如下圖所示:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cGcq5SNkNTY5YDM5AjMjNzMzQmYxM2NmljNiZDOhZTNjVDM18CXyAzLchDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL5M3Lc9CX6MHc0RHaiojIsJye.jpg)
TControl = class(TComponent)
private
FLeft: Integer;
FTop: Integer;
FVisible: Boolean;
FOnClick: TNotifyEvent;
{中間代碼太長,省略,具體請看Delphi源代碼}
protected
procedure Click; dynamic;
property OnClick: TNotifyEvent read FOnClick write FOnClick stored IsOnClickStored;
{中間代碼太長,省略,具體請看Delphi源代碼}
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Visible: Boolean read FVisible write SetVisible stored IsVisibleStored default True;
{中間代碼太長,省略,具體請看Delphi源代碼}
published
property Left: Integer read FLeft write SetLeft;
property Top: Integer read FTop write SetTop;
property Width: Integer read FWidth write SetWidth;
property Height: Integer read FHeight write SetHeight;
property Cursor: TCursor read FCursor write SetCursor default crDefault;
property Hint: string read FHint write FHint stored IsHintStored;
property HelpType: THelpType read FHelpType write FHelpType default htContext;
property HelpKeyword: String read FHelpKeyword write SetHelpKeyword stored IsHelpContextStored;
property HelpContext: THelpContext read FHelpContext write SetHelpContext stored IsHelpContextStored default 0;
end;
可以看到TControl派生自元件基類TComponent,而類TControl有四個保留字聲明,控制着類中對象的通路權限。我們可以看到其published聲明中的屬性與我們所建立的TLineTo畫線控件的預設屬性一緻,這是發行類型成員。其他一般控件有的屬性被TControl聲明為public,比如Visible屬性被聲明成public,要使我們建立的控件帶有Visible屬性,就必須把Visible重聲明為published。
type
TLineTo = class(TGraphicControl)
{省略····}
published
property Visible;
end;
而在TControl的protected聲明裡包含了最基本的标準事件,比如OnClick、OnDblClick、OnMouseDown等等。如果我們要讓建立的元件在對象設計器可以對相應的标準事件進行響應的話,就必須要重聲明事件屬性的保護級别,比如把OnClick聲明為published,就可以在對象設計器的Events中對元件進行事件響應。
type
TLineTo = class(TGraphicControl)
{省略······}
published
property OnClick;
end;
假設我們要讓建立的元件在内部自己實作對标準事件的響應,意思是改寫标準事件處理過程,那麼可以重寫事件處理代碼,所有标準事件在TControl中都定義了相應的Protected動态方法,隻是沒有加On,例如OnClick事件調用名為Click的方法,是以我們隻要覆寫TControl的Click方法,就可以重寫此事件響應。
type
TLineTo = class(TGraphicControl)
protected
procedure Click; override;
end;
implementation
procedure TLineTo.Click;
begin
inherited Click; {執行标準處理,包括調用事件處理過程}
end;
我們所做的畫線控件,線筆寬度被固定了,是以我們得添加一個畫筆寬度PenWidth,以改變畫線的粗細。在此,我們建立的TLineTo控件,為它添加PenWidth屬性,開放Visible屬性,開放OnClick事件,重寫它的Click消息,具體的完整源碼如下:
unit LineTo;
interface
uses
SysUtils, Classes, Controls, Dialogs;
type
TLineTo = class(TGraphicControl)
private
FPenWidth: Integer;
procedure SetPenWidth(Value: Integer);
protected
procedure Paint; override;
procedure Click; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property PenWidth: Integer read FPenWidth write SetPenWidth default 1; {如果值是1的話就不寫進窗體DFM檔案,節省空間}
property Visible;
property OnClick;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TLineTo]);
end;
constructor TLineTo.Create(Aowner: TComponent);
begin
inherited Create(AOwner);
{一些字段可以在這裡初始化}
FPenWidth := 1;
end;
destructor TLineTo.Destroy;
begin
{一些資源可以在這裡釋放}
inherited Destroy;
end;
procedure TLineTo.Paint;
begin
with Canvas do
begin
MoveTo(0, 0);
LineTo(Self.Width, Self.Height);
end;
end;
procedure TLineTo.Click;
begin
inherited Click; {執行标準處理,包括調用事件處理過程}
ShowMessage('畫線控件 V1.0 by 無幻'); {需要uses Dialogs}
end;
procedure TLineTo.SetPenWidth(Value: Integer);
begin
if FPenWidth <> Value then
begin
FPenWidth := Value;
Canvas.Pen.Width := FPenWidth;
Invalidate;
end;
end;
end.
由于在上一次,我們已經安裝過TLineTo控件了,是以這次我們隻需重新編譯下TLineTo元件就可以了。打開dclusr.dpk,選中LineTo.pas再點選編譯Compile,沒有彈出錯誤就是重新編譯成功。儲存關閉檔案。
下面建立一個應用程式來測試,拖動TLineTo控件到窗體上,左邊的對象設計器如下圖所示:
可以看到屬性Properties多了PenWidth和Visible屬性,事件多了OnClick,我們添加對TLineTO元件的OnClick事件處理,如下代碼:
procedure TForm1.lnt1Click(Sender: TObject);
begin
ShowMessage('你點選了TLineTo控件');
end;
運作結果如下圖所示: