後一頁
前一頁
回目錄
回首頁
第十九章 Delphi自定義部件開發(四)

19.3.2 建立圖形部件 

圖形控制是一類簡單的部件。因為純圖形部件從不需要得到鍵盤焦點,所以它沒有也不要視窗句柄。包含圖形控制的應用程式用戶仍然可以用滑鼠操作控制,但沒有鍵盤介面。

  在本例中提供的圖形部件是TShapeShape部件位於Component PaletteAdditional頁。本例中的Shape部件有所不同,因此稱其為TSampleShape

  建立圖形部件需要下列三個步驟:

  ● 建立和註冊部件

  ● 公佈(publishing)繼承的屬性

增加圖形功能

 

19.3.2.1 建立和註冊部件

 

每個部件的建立都從相同的方式開始,在本例中如下:

建立名為Shapes的部件單元

TGraphicControl 繼承,將新部件稱為TSampleShape

Component PaletteSamples頁上註冊TSampleShape

 

unit Shapes

 

intertace

 

use SysUtils, WinTypes, WinProcs, Messages, Classes,

GraphicsControlsForms;

 

type

TSampleShape=class(TGraphicControl)

end;

 

implementation

 

procedure Register;

begin

RegisterComponents('Samples'[TSampleShape]);

end;

 

end.

 

19.3.2.2 公佈繼承的屬性

 

一旦決定了部件型式,就能決定在父類的protected部分聲明哪些屬性和事件能為用戶可見。TGraphicControl已經公佈了所有作為圖形控制的屬性,因此,只需公佈響應滑鼠和拖放事件的屬性。

 

  type

TSampleShape=class(TGraphicControl)

published

property DragCursor;

property DragMode;

property OnDragDrop;

property OnDragOver;

property ONEndDrag;

property OnMouseDown;

property OnMouseMove;

property OnMouseup;

end;

 

這樣,該Shape控制具有通過滑鼠和拖放與用戶互動的能力。

 

19.3.2.3 .增加圖形能力

 

一旦你聲明了圖形部件並公佈了繼承的屬性,就可以給部件增加圖形功能。這時需要知道兩點:

  ● 決定畫什麼

  ● 怎樣畫部件圖形

 

  Shape控制的例子中,需要增加一些能使用戶在設計時改變形狀的屬性。

 

1. 決定畫什麼

  圖形部件通常都具有改變外觀的能力,圖形控制的外觀取決於其某些屬性的結合,例如Gauge控制具有決定其形狀、方向和是否圖形化地顯示其過程的能力。同樣,Shape控制也應有決定顯示各種形狀的能力.

給予Shape控制這種能力,增加名為Shape的屬性。這需要下列三步:

聲明屬性型式

聲明屬性

編寫實現方法

 

  ぇ 聲明屬性型式

  當聲明一個用戶自定義型式的屬性時,必須首先聲明屬性型式。最普通地用於屬性的自定義型式是枚舉型式。

  對Shape控制來說,需要聲明一個該控制能畫形狀的枚舉,下面是枚舉型式的聲明:

 

type

TSampleShapeType=(sstRectangle, sstSquare, sstRoundRect,

sstRoundSquare, sstEllipse, sstCircle);

TSampleShape = class(TGraphicControl)

end;

 

這樣,就可以用該型式來聲明屬性。

聲明屬性

當聲明一個屬性時,通常需要聲明私有欄位來存檔屬性值,然後描述讀寫屬性值的方法。

對於Shape控制,將聲明一個欄位存檔目前形狀,然後聲明一個屬性通過方法呼叫來讀寫欄位值。

 

type

TSampleShape=class(TGrahpicControl)

private

FShape: TSampleShapeType;

procedure SetShape(value: TSampleShapeType);

published

property Shape: TSampleShapeType read FShape write SetShape;

end;

 

現在,只剩下SetShape的實現部分了。

編寫實現方法

下面是SetShape的實現:

 

procedure TSampleShape.SetShape(value: TSampleShapeType);

begin

if FShape<>value then

begin

FShape := value;

Invalidate(True); { 強制新形狀的重畫 }

end;

end;

 

2. 覆蓋constructordestructor

為了改變缺省屬性值和初始化部件擁有的物件,需要覆蓋繼承的constructordestructor方法。

圖形控制的缺省大小是相同的,因此需要改變WidthHeight屬性。

本例中Shape控制的大小的初始設定為邊長65個像素點。

在部件聲明中增加覆蓋constructor

 

type

TSampleShape=class(TGraphicControl)

public

constructor Create(Aowner: TComponent); override;

end;

 

用新的缺省值重新聲明屬性Heightwidth

 

type

TSampleShape=class(TGrahicControl)

published

property Height default 65;

property Width default 65;

end;

 

在庫單元的實現部分編寫新的constructor

 

constructor TSampleShape.Create(Aowner: TComponent);

begin

inherited Create(AOwner);

width := 65;

Height := 65;

end;

 

3. 公佈PenBrush

在缺省情況下,一個Canvas具有一個細的、黑筆和實心的白刷,為了使用戶在使用Shape控制時能改變Canvas的這些性質,必須能在設計時提供這些物件;然後在畫時使用這些物件,這樣附屬的PenBrush被稱為Owned物件。

管理Owned物件需要下列三步:

聲明物件欄位

聲明存取屬性

初始化Owned物件

 

聲明Owned物件欄位

擁有的每一個物件必須有物件欄位的聲明,該欄位在部件存在時總指向Owned物件。通常,部件在constructor中建立它,在destructor中復原它。

Owned物件的欄位總是定義為私有的,如果要使用戶或其它部件存取該欄位,通常要提供存取屬性。

下面的代碼聲明了PenBrush的物件欄位:

 

type

TSampleShape=class(TGraphicControl)

private

FPen: TPen;

FBrush: TBrush;

end;

 

聲明存取屬性

可以通過聲明與Owned物件相同型式的屬性來提供對Owned物件的存取能力。這給使用部件的開發者提供在設計時或執行時存取物件的途徑。

下面給Shape控制提供了存取PenBrush的方法

 

type

TSampleShape=class(TGraphicControl)

private

procedure SetBrush(Value: TBrush);

procedure SetPen(Value: TPen);

published

property Brush: TBrush read FBrush write SetBrush;

property Pen: TPen read FPen write SetPen;

end;

 

然後在庫單元的implementation部分寫SetBrushSetPen方法:

 

procedure TSampleShape.SetBrush(Value: TBrush);

begin

FBrush.Assign(Value);

end;

 

procedure TSampleShape.SetPen(Value: TPen);

begin

FPen.Assign(Value);

end;

 

初始化Owned物件

部件中增加了的新物件,必須在部件constructor中建立,這樣用戶才能在執行時與物件互動。相應地,部件的destructor必須在復原自身之前復原Owned物件。

因為Shape控制中加入了PenBrush物件,因此,要在constructor中初始化它們,在destructor中復原它們。

Shape控制的constructor中建立PenBrush

 

constructor TSampleShape.Create(Aowner: TComponent);

begin

inherited Create(AOwner);

Width := 65;

Height := 65;

FPen := TPen.Create;

FBrush := TBrush.Create;

end;

 

在部件物件的聲明中覆蓋destructor

 

type

TSampleShape=class(TGraphicControl)

public

construstor.Create(Aowner: TComponent); override;

destructor.destroy; override;

end;

 

在庫單元中的實現部分編寫新的destructor

 

destructor TSampleShape.destroy;

begin

FPen.Free;

FBrush.Free;

inherited destroy;

end;

 

設定Owned物件的屬性

處理PenBrush物件的最後一步是處理PenBrush發生改變時對Shape控制的重畫問題。PenBrush物件都有OnChange事件,因此能夠在Shape控制中聲明OnChange事件指向的事件處理過程。

下面給Shape控制增加了該方法並更新了部件的constructor以使PenBrush事件指向新方法:

 

type

TSampleShape = class(TGraphicControl)

published

procdeure StyleChanged(Sender: TObject);

end;

 

implemintation

 

constructor TSampleShape.Create(AOwner:TComponent);

begin

inherited Create(AOwner);

Width := 65;

Height := 65;

Fpen := TPen.Create;

FPen.OnChange := StyleChanged;

Fbrush := TBrush.Create;

FBrush.OnChange := StyleChanged;

end;

 

procedure TSampleShape.StyleChanged(Sender: TObject);

begin

Invalidate(true);

end;

 

當變化發生時,部件重畫以響應PenBrush的改變。

 

4. 怎樣畫部件圖形

圖形控制基本要素是在螢幕上畫圖形的方法。抽象類TGraphicControl定義了名為Paint的虛方法,可以覆蓋該方法來畫所要的圖形。

Shape控制的paint方法需要做:

使用用戶選擇的PenBrush

使用所選的形狀

調整座標。這樣,方形和圓可以使用相同的WidthHeight

 

覆蓋paint方法需要兩步:

在部件聲明中增加Paint方法的聲明

implementation部分寫Paint方法的實現

 

下面是Paint方法的聲明:

 

type

TSampleShape = class(TGraphicControl)

protected

procedure Paint; override;

end;

 

然後,編寫Paint的實現:

 

procedure TSampleShape.Paint;

begin

with Canvas do

begin

Pen := FPen;

Brush := FBrush;

case FShape of

sstRectangle, sstSquare :

Rectangle(0, 0, Width, Height);

sstRoundRect, sstRoundSquare:

RoundRect(0, 0, Width, Height, Width div 4, Height div 4);

sstCircle, sstEllipse :

Ellipse(0, 0, Width, Height);

end;

end;

end; 

無論任何控制需要更新圖形時,Paint就被呼叫。當控制第一次出現,或者當控制前面的視窗消失時,Windows會通知控制畫自己。也可以通過呼叫Invalidate方法強制重畫,就象StyleChanged方法所做的那樣。


後一頁
前一頁
回目錄
回首頁