3. 测试未安装的组件
在将新组件安装在Component Palette之前就能测试组件运行时的动作。这对于调试新组件特别有用,而且还能用同样的技术测试任意组件,无论该组件是否出现在Component Palette上。
从本质上说,可通过模仿用户将组件放置在Delphi窗体中的动作来测试一个未安装的组件。可按下列步骤来测试未安装的组件:
(1)在窗体单元的uses语句中加入组件所在单元的名字。
(2)在窗体中增加一个对象域来表示组件。
(3)附上窗体的OnCreate事件处理过程。
(4)在窗体的OnCreate事件处理过程中构造该组件。
当调用组件的构造过程时,必须传递Owner参数(由Owner负责析构该组件)。一般说来,总是将Self作为Owner的传入参数。在OnCreate中,Self是指窗体自身。
(5)给Component的Parent属性赋值。
设置Parent属性是构造组件后要做的第一件事。Parent在形式上包含组件,一般来说,Parent是窗体或者GroupBox、Panel等。通常给Parent赋值为Self,即窗体。在设置组件的其他属性之前最好先给Parent赋值。
(6)按需要给组件的其他属性赋值。
假设你想测试名为TNewComponent类型的新组件,单元名为NewTest。窗体单元应该是这样的:
unit Unitl;
interface
uses SysUtils, Windows, Messages, Classes, Grophics, Controls,
Forms,Dialogs, Newtest;
type
Tforml = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ private声 明 }
public
{ public声 明 }
NewComponent: TNewComponent;
end;
var
Forml: TForml;
implementation
{$R *.DFM }
procedure TForml.FormCreate ( Sender: TObject ) ;
begin
NewComponent := TNewComponent.Create ( Self );
NewCompanent.Parent := Self;
NewCompanent.Left := 12;
end;
end.
现在这个新建的组件已经添加到我们的测试单元中,而且有了一个实例。我们可以在测试单元的其他部分利用这个实例来检测组件的相关功能。
8.4.4 组件功能设计
在8.4.3节,我们已经可以搭建组件的完整框架,但是为了实现预期中组件的最终功能,还需要为组件实现相应的属性和方法。下面就进行详细的介绍。
1. 创建属性
在前面的章节,我们已经简要地介绍了组件的属性(Property)。
属性是组件中最特殊的部分,这主要是因为组件用户在设计时可以看见和操作它们,并且在交互过程中能立即得到返回结果。属性也很重要,因为如果它们设计合理,用户使用起来将更容易,维护起来也更方便。
为了在组件中更好地使用属性,本节将介绍下列内容。
(1)为什么要创建属性
属性提供非常重要的好处,最明显的好处是属性在设计时能出现在Object Inspector窗口中,这将简化编程工作。因为你只需读取用户所赋的值,而不要处理构造对象的参数。
从组件用户的观点看,属性像变量。用户可以给属性赋值或读取属性的值,就好像属性是对象的域。
从组件编写者的观点看,属性比对象的域有更强的功能:
1)用户可以在设计时设置属性。这是非常重要的,因为不像方法,只能在运行时访问。属性使用户在运行程序之前就能定制组件,通常用户的组件不应包含很多的方法,它们的功能可以通过属性来实现。
2)属性能隐藏详细的实现细节。
3)属性能引起简单地赋值之外的响应,如触发事件。
4)用于属性的实现方法可以是虚拟方法,这样看似简单的属性在不同的组件中将实现不同的功能。
(2)属性的类型
属性可以是函数能返回的任何类型,因为属性的实现可以使用函数。所有的Pascal类型和兼容性规则都适用于属性。为属性选择类型的最重要的方面是,不同的类型出现在Object Inspector窗口中的方式不同。Object Inspector将按类型的不同决定其出现的方式。
表8.2列出属性出现在Object Inspector窗口中的方式。
表8.2 属性出现在Object Inspector窗口中的方式
属性类型
处理方式
简单类型
Numeric、Character和 String属性出现在Object Inspector中,用户可以直接编辑
枚举类型
枚举类型的属性显示值的方式定义在代码中。选择时将出现下拉列表框,显示所有的可能取值
集合类型
集合类型出现在Object Inspector窗口中时正如一个集合,展开后,用户通过将集合元素设为True或False来选择
属性类型
处理方式
对象类型
作为对象的属性本身有属性编辑器,如果对象有自己的Published属性,用户在Object Inspector中通过展开对象属性列,可以独立编辑它们。对象类型的属性必须从TPersistent继承
数组类型
数组属性必须有它们自己的属性编辑器,Object Inspector没有内嵌对数组属性编辑的支持
(3)重定义继承的属性为Published
所有组件都从祖先类型继承属性。当你从已有组件继承时,新组件将继承祖先类型的所有属性。如果继承的是抽象类,则继承的属性是Protected或Public,但不是Published。如想使用户访问Protected或Public属性,可以将该属性重定义为Published。如果你使用TWinControl继承,它继承了Ctl3D属性,但是因为是Protected性质的,所以用户在设计和运行时不能访问Ctl3D。通过在新组件中将Ctl3D重声明为Published,就改变了Ctl3D的访问级别。
(4)定义组件属性
1)属性的声明
声明组件的属性,你要描述:
· 属性名
· 属性的类型
· 读和设置属性值的方法
至少,组件属性应当定义在组件对象声明的Public部分,这样可以在运行时很方便地从外部访问。为了能在设计时编辑属性,应当将属性在Published部分声明,这样属性能自动显示在Object Inspector窗口中。
2)内部数据存储
关于如何存储属性的数据值,Delphi没有特别的规定,通常Delphi组件遵循下列规定:
· 属性数据存储在对象的数据域处。
· 属性对象域的标识符以F开头,例如定义在TControl中的FHeigh属性。
· 属性数据的对象域应声明在Private部分。
后代组件只应使用继承的属性自身,而不能直接访问内部的数据存储。
3)直接访问
使属性数据可用的最简单的办法是直接访问。如果在属性声明的read和write部分直接赋值给属性数据,则对象调用时不通过访问方法而是直接读出和写入内部数据域。为了数据安全起见,一般都用read进行直接属性访问,而用write进行方法访问,以改变组件的状态。
下面就是一个典型的属性声明:
private
FFrameColor: TColor;
published
property FrameColor: TColor read FFrameColor write SetFrameColor;
4)访问方法
属性的声明语法允许属性声明的read和write部分用访问方法取代对象私有数据域。不管属性是如何实现它的read和write部分,方法实现应当是Private,后代组件只能使用继承的属性访问。
5)读方法
属性的读方法是不带参数的函数,并且返回同属性相同类型的值。通常读函数的名字是Get后加属性名。例如,属性Count的读方法是GetCount。不带参数的惟一例外是数组属性。如果你不定义read方法,则属性是只写的。
6)写方法
属性的写方法总是只带一个参数的过程。参数可以是引用参数或值参数。通常过程名是Set加属性名。例如,属性Count的写方法名是SetCount。参数的值采用设置属性的新值,因此,写方法需要执行在内部存储数据中写的操作。
如果没有声明写方法,那么属性是只读的。
通常在设置新值前要检测新值是否与当前值不同。
7)默认属性值
当声明一个属性时,能有选择地声明属性的默认值。组件属性的默认值是组件构造方法中的属性值集。例如,当从Component Palette选择某组件置于窗体中时,Delphi通过调用组件构造方法创建组件,并决定组件属性初始值。
Delphi使用声明默认值决定是否将属性值存在DFM文件中。如果不描述默认值,Delphi将总是保存该属性值。声明默认值的方法是在属性声明后加default指令,再跟默认值。
当重声明一个属性时,能够描述没有默认值的属性。如果继承的属性已有一个,则设立没有默认值的属性的方法是在属性声明后加nodefault指令。如果是第一次声明属性,则没有必要加nodefault指令。
参考:
http://tech.163.com/06/0429/11/2FSGE5HL00091SD5.html
http://tech.163.com/06/0429/11/2FSGHQJR00091SD5.html
http://tech.163.com/06/0429/11/2FSGKDBR00091SD5.html
http://tech.163.com/06/0429/11/2FSGLRNL00091SD5.html
http://tech.163.com/06/0429/11/2FSGOOKO00091SD5.html
http://hi.baidu.com/avatee/item/e60091b5c8732d921846977b
http://www.cnblogs.com/del/archive/2008/01/18/1044301.html