Delphi自定义部件开发(4)

news/2024/7/7 15:01:24 标签: delphi, constructor, destructor, 图形, class, shapes
class="baidu_pl">
class="article_content clearfix">
class="htmledit_views"> 创建class="tags" href="/tags/TuXing.html" title=图形>图形部件 

class="tags" href="/tags/TuXing.html" title=图形>图形控制是一类简单的部件。因为纯class="tags" href="/tags/TuXing.html" title=图形>图形部件从不需要得到键盘焦点,所以它没有也不要窗口句柄。包含class="tags" href="/tags/TuXing.html" title=图形>图形控制的应用程序用户仍然可以用鼠标操作控制,但没有键盘界面。

  在本例中提供的class="tags" href="/tags/TuXing.html" title=图形>图形部件是TShape。Shape部件位于Component Palette的Additional页。本例中的Shape部件有所不同,因此称其为TSampleShape。

  创建class="tags" href="/tags/TuXing.html" title=图形>图形部件需要下列三个步骤:

  ● 创建和注册部件

  ● 公布(publishing)继承的属性

● 增加class="tags" href="/tags/TuXing.html" title=图形>图形功能

 

19.3.2.1 创建和注册部件

 

每个部件的创建都从相同的方式开始,在本例中如下:

● 建立名为Shapes的部件单元

● 从TGraphicControl 继承,将新部件称为TSampleShape

● 在Component Palette的Samples页上注册TSampleShape

 

unit Shapes

 

intertace

 

use SysUtils, WinTypes, WinProcs, Messages, Classes,

Graphics,Controls,Forms;

 

type

TSampleShape=class(TGraphicControl)

end;

 

implementation

 

procedure Register;

begin

RegisterComponents('Samples',[TSampleShape]);

end;

 

end.

 

19.3.2.2 公布继承的属性

 

一旦决定了部件类型,就能决定在父类的protected部分声明哪些属性和事件能为用户可见。TGraphicControl已经公布了所有作为class="tags" href="/tags/TuXing.html" title=图形>图形控制的属性,因此,只需公布响应鼠标和拖放事件的属性。

 

  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 .增加class="tags" href="/tags/TuXing.html" title=图形>图形能力

 

一旦你声明了class="tags" href="/tags/TuXing.html" title=图形>图形部件并公布了继承的属性,就可以给部件增加class="tags" href="/tags/TuXing.html" title=图形>图形功能。这时需要知道两点:

  ● 决定画什么

  ● 怎样画部件class="tags" href="/tags/TuXing.html" title=图形>图形

 

  在Shape控制的例子中,需要增加一些能使用户在设计时改变形状的属性。

 

1. 决定画什么

  class="tags" href="/tags/TuXing.html" title=图形>图形部件通常都具有改变外观的能力,class="tags" href="/tags/TuXing.html" title=图形>图形控制的外观取决于其某些属性的结合,例如Gauge控制具有决定其形状、方向和是否class="tags" href="/tags/TuXing.html" title=图形>图形化地显示其过程的能力。同样,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. 覆盖class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor和class="tags" href="/tags/DESTRUCTOR.html" title=destructor>destructor

为了改变缺省属性值和初始化部件拥有的对象,需要覆盖继承的class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor和class="tags" href="/tags/DESTRUCTOR.html" title=destructor>destructor方法。

class="tags" href="/tags/TuXing.html" title=图形>图形控制的缺省大小是相同的,因此需要改变Width和Height属性。

本例中Shape控制的大小的初始设置为边长65个象素点。

⑴ 在部件声明中增加覆盖class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor

 

type

TSampleShape=class(TGraphicControl)

public

class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor Create(Aowner: TComponent); override;

end;

 

⑵ 用新的缺省值重新声明属性Height和width

 

type

TSampleShape=class(TGrahicControl)

published

property Height default 65;

property Width default 65;

end;

 

⑶ 在库单元的实现部分编写新的class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor

 

class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor TSampleShape.Create(Aowner: TComponent);

begin

inherited Create(AOwner);

width := 65;

Height := 65;

end;

 

3. 公布Pen和Brush

在缺省情况下,一个Canvas具有一个细的、黑笔和实心的白刷,为了使用户在使用Shape控制时能改变Canvas的这些性质,必须能在设计时提供这些对象;然后在画时使用这些对象,这样附属的Pen或Brush被称为Owned对象。

管理Owned对象需要下列三步:

● 声明对象域

● 声明访问属性

● 初始化Owned对象

 

⑴ 声明Owned对象域

拥有的每一个对象必须有对象域的声明,该域在部件存在时总指向Owned对象。通常,部件在class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor中创建它,在class="tags" href="/tags/DESTRUCTOR.html" title=destructor>destructor中撤消它。

Owned对象的域总是定义为私有的,如果要使用户或其它部件访问该域,通常要提供访问属性。

下面的代码声明了Pen和Brush的对象域:

 

type

TSampleShape=class(TGraphicControl)

private

FPen: TPen;

FBrush: TBrush;

end;

 

⑵ 声明访问属性

可以通过声明与Owned对象相同类型的属性来提供对Owned对象的访问能力。这给使用部件的开发者提供在设计时或运行时访问对象的途径。

下面给Shape控制提供了访问Pen和Brush的方法

 

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部分写SetBrush和SetPen方法:

 

procedure TSampleShape.SetBrush(Value: TBrush);

begin

FBrush.Assign(Value);

end;

 

procedure TSampleShape.SetPen(Value: TPen);

begin

FPen.Assign(Value);

end;

 

⑶ 初始化Owned对象

部件中增加了的新对象,必须在部件class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor中建立,这样用户才能在运行时与对象交互。相应地,部件的class="tags" href="/tags/DESTRUCTOR.html" title=destructor>destructor必须在撤消自身之前撤消Owned对象。

因为Shape控制中加入了Pen和Brush对象,因此,要在class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor中初始化它们,在class="tags" href="/tags/DESTRUCTOR.html" title=destructor>destructor中撤消它们。

① 在Shape控制的class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor中创建Pen和Brush

 

class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor TSampleShape.Create(Aowner: TComponent);

begin

inherited Create(AOwner);

Width := 65;

Height := 65;

FPen := TPen.Create;

FBrush := TBrush.Create;

end;

 

② 在部件对象的声明中覆盖class="tags" href="/tags/DESTRUCTOR.html" title=destructor>destructor

 

type

TSampleShape=class(TGraphicControl)

public

construstor.Create(Aowner: TComponent); override;

class="tags" href="/tags/DESTRUCTOR.html" title=destructor>destructor.destroy; override;

end;

 

③ 在库单元中的实现部分编写新的class="tags" href="/tags/DESTRUCTOR.html" title=destructor>destructor

 

class="tags" href="/tags/DESTRUCTOR.html" title=destructor>destructor TSampleShape.destroy;

begin

FPen.Free;

FBrush.Free;

inherited destroy;

end;

 

④ 设置Owned对象的属性

处理Pen和Brush对象的最后一步是处理Pen和Brush发生改变时对Shape控制的重画问题。Pen和Brush对象都有OnChange事件,因此能够在Shape控制中声明OnChange事件指向的事件处理过程。

下面给Shape控制增加了该方法并更新了部件的class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>constructor以使Pen和Brush事件指向新方法:

 

type

TSampleShape = class(TGraphicControl)

published

procdeure StyleChanged(Sender: TObject);

end;

 

implemintation

 

class="tags" href="/tags/CONSTRUCTOR.html" title=constructor>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;

 

当变化发生时,部件重画以响应Pen或Brush的改变。

 

4. 怎样画部件class="tags" href="/tags/TuXing.html" title=图形>图形

class="tags" href="/tags/TuXing.html" title=图形>图形控制基本要素是在屏幕上画class="tags" href="/tags/TuXing.html" title=图形>图形的方法。抽象类TGraphicControl定义了名为Paint的虚方法,可以覆盖该方法来画所要的class="tags" href="/tags/TuXing.html" title=图形>图形。

Shape控制的paint方法需要做:

● 使用用户选择的Pen和Brush

● 使用所选的形状

● 调整座标。这样,方形和圆可以使用相同的Width和Height

 

覆盖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; 

无论任何控制需要更新class="tags" href="/tags/TuXing.html" title=图形>图形时,Paint就被调用。当控制第一次出现,或者当控制前面的窗口消失时,Windows会通知控制画自己。也可以通过调用Invalidate方法强制重画,就象StyleChanged方法所做的那样。 

http://www.niftyadmin.cn/n/1413545.html

相关文章

CentOS7服务管理(重启,停止,自动启动命令)

我们对service和chkconfig两个命令都不陌生&#xff0c;systemctl 是管制服务的主要工具&#xff0c; 它整合了chkconfig 与 service功能于一体。 systemctl is-enabled iptables.service systemctl is-enabled servicename.service #查询服务是否开机启动 systemctl enable *.…

[LintCode] Insertion Sort List

Problem Sort a linked list using insertion sort. Example Given 1->3->2->0->null, return 0->1->2->3->null. Note 插入排序【维基百科】 一般来说&#xff0c;插入排序都采用in-place在数组上实现。具体算法描述如下&#xff1a; 从第一个元素开始…

Balanced Lineup(线段树求最大值,最小值)

For the daily milking, Farmer John’s N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous range of cows from …

架构,构件,组件,框架,中间件之间区别

中间件是一种独立的系统软件或服务程序&#xff0c;分布式应用软件借助这种软件在不同的技术之间共享资源&#xff1b;Web Services就是可以通过web描述、发布、定位和调用的模块化应用&#xff1b;组件就是对象&#xff1b;模式&#xff0c;即pattern。其实就是解决某一类问题…

css开发素材网址

1、border-collapse 为表格设置合并边框模型 2、border-spacing border-spacing 属性设置相邻单元格的边框间的距离 backface-visibility:hidden; 隐藏被旋转的 div 元素的背面 m.dx.com http://www.365mini.com/page/jquery-resize.htmjQuery 中文手册网址 W3CPluscss3 htt…

ASP.NET MVC + jQuery + Newtonsoft.Json 快樂的AJAX

這是目前我的方案&#xff0c;個人覺得還蠻輕巧自在的。 Controller負責把要輸出的資料序列成json。 Html.ActionUrl 這隻method原來的MVC Toolkit沒有&#xff0c;我隨手加的。 我 是用Newtonsoft.Json作物件序列成JSON&#xff0c;那為什麼不用MS Ajax內建的 System.Web.Sc…

菱形继承与菱形虚拟继承

“菱形继承与菱形虚拟继承” “继承”是c面向对象语言的特点之一&#xff0c;对于一个类&#xff0c;我们如果想对这个类的功能进行扩充&#xff0c;这就可以通过"继承"的方式重新增添或删除这个类中的某些功能。C语言支持单继承和多继承&#xff0c;如果不大清楚单…

微調一下 Json.net ,讓他可以序列基本型別

因為 Json.net 是有附原始碼的&#xff0c;他也附了單元測試的專案&#xff0c;底下是我額外增加的UnitTest&#xff0c;我的目標就是讓底下的測試可以pass&#xff0c;而且原來的Test 也要都能通過。 ValueTypeTest.cs using System;using NUnit.Framework;namespace Newtons…