Delphi组件开发指南.doc_第1页
Delphi组件开发指南.doc_第2页
Delphi组件开发指南.doc_第3页
Delphi组件开发指南.doc_第4页
Delphi组件开发指南.doc_第5页
已阅读5页,还剩25页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

组件开发指南第一章 组件制作概述本章表述了组件设计的概论和编写Delphi应用程序组件的过程。 这里的材料将让你各更熟悉Delphi和它的标准组件。 Class library(类库) Components and classes(组件和类) Creating components(创建组件) What goes into a component?() Creating a new component(创建新组件) Testing uninstalled components(卸载组件) Testing installed components(安装组件) Installing a component on the Component palette(在组件栏安装组件) 要获得更多的安装新组件的信息,请参考开发者指南第 1610页“安装组件包”一节。Delphi的组件包括VCL(虚拟组件库)和CLX(跨平台组件库)。图1.1显示了构成VCL层的所选类之间的关系。CLX 层类似于VCL 层但是 Windows 控件称为 widgets (因此,例如, WinControl叫TwidgetControl ), 并且有其他差别。 对一个类阶层和继承类之间的关系的更详细的讨论,请参考第2章,组件编写者的面向对象的程序设计。 针对层之间相互差别的概述, 在开发者的指南的15-7 页上WinCLX 与VisualCLX一节以及CLX 在线获取更详细的组件说明。TComponent 类在组件库是每个组件所共同拥有的祖先。 Tcomponent类提供最少而且是必要的性质和事件以使组件能在IDE上工作。 库的各类分支提供了组件其他更专业化的功能。当你创造一个新组件时,你将通过从层的现有的类类型中得到一个新类来添加到组件库中。由于组件都是类,组件的开发者处在程序开发的不同的水平上。创建新组件需要你得自新类。简要的说,在创建组件和在程序中应用组件之间存在这两个主要的区别。当我们创建组件时 Ø你所处理的是应用程序程序员几乎不涉及的类的部分 Ø你需要在你的组件里增加新的部分(比如说新的属性)由于这些差别,你需要知道更多的(程序)内部转换并且得考虑程序开发员将怎样使用你所编写的组件。一个组件可能是一个程序中你想要在设计期内使用的任何方案的组成部分。创建一个新组件意味着从一个已知存在的类获得。你能以这几种方式重构一个新组件: 修改已存在的控制方式 创建窗口控制方式 创建图形控制方式 子类窗口控制方式 创建非可视组件你也可以通过那些不能在 Form 上操作的组件重构类,比如 TregInifile 和 Tfont。最简单的创建组件的方式是在一个已存在的组件上自定义。你能从任何一个在组件库中存在的组件上重构一个新组件。一些控制方式,例如 List Boxes 和 Grids,基于数个不通的主题。这样的话,组件库包含了从自定义的版本得到的抽象类(在此类中,以 custom 为其名,如 TcustomGrid)。例如,你想创建一个不含有标准 TlistBox 类某些属性的特定的 ListBox。你不能移除(隐藏)一个继承自祖先类的属性,因此,你需要从 TlistBox 之上的类得到你的组件。组件库提供了 TcustomListBox 它实现了 ListBox 的属性但并不完全将这些属性全部都显示出来 而不是迫使你从 TwinControl(或者是 CLX 应用程序中的TwidgetControl)类上重新编写所有的 ListBox 功能。当你从像 TcustomListBox 那样的抽象类上得到新组件时,你可以在你的组件上发布你想要的那些属性,而把你不需要的留下“藏”起来。第3章,“Creating properties”解释了发布继承属性的方法。 第9章,“Modifying an existing component”和第11章,“Customizing a grid”演示了如何修改组件中已存在控制方式的例子。在组件库中的窗口控制是在运行期出现的对象,用户能与之互动。每个窗口控制都有通过 Handle 属性进行处理的窗口句柄,这些句柄能够被操作系统所识别和控制。如果使用了VCL 控制,句柄就允许控制接收输入焦点并且能被 Widows API 函数所使用。CLX 控制是基于窗口小部件的控制方式。每个基于窗口部件的控制都具有一个通过以小窗口为基础的 Handle 属性处理的句柄。所有的窗口控制都源于 TwinControl 类(在VCL 的 TwidgetControl 上)。这些控制包含了大多数标准的窗口控制,如pushbuttons(按钮),list box(列表框)和edit box(编辑框)。当你从TwinControl(在 VCL 的 TwdgetControl 上)能直接得到一个常用的控制,为此,Delphi 提供了一个TcustomControl 组件。TcustomControl 是使画复杂可视化图形变得更简单的专业窗口控制方式。第11章,“Customizing a grid”,提供了创建窗口控制的一个例子。如果你的控制并不需要接收输入焦点,你可以把它做成一个图表控制。图表控制和窗口控制很相似但是它没有窗口句柄,因此占用的系统资源也更少。如 Tlabel 控件 从不接收输入焦点 就是一个图表控制。尽管这些控制不能接受焦点,你也能让它们对鼠标消息产生反应(亦即对鼠标消息敏感)。你可以通过 TgraphicControl 组件创建一个自定义的控制。TgraphicControl 是基于 Tcontrol 的抽象类。尽管你可以直接从 Tcontrol 得到控制方式,但是,从提供了对 Windows 不停进行重画的 canvas 方法,以 WM_PAINT 为句柄的 TgraphicControl 来开始编写将是更好的选择:你所需要做的只是重写 Paint 方法。第10章,“Creating a graphic control”演示了创建图表控制的例子。在传统 Windows 程序中,你通过定义一个新的窗口类并使用 Windows 进行注册来创建一个自定义控制。窗口类(在面向对象编程中类似于对象或者类)包含了被相同类控制实例共享的信息;基于一个已存在类上而建立的新的窗口类被称为子类。你可以把你的控制方式放到一个动态链接库(DLL)中,如同标准 Windows 控制,并为它提供接口。你可以在任何已有的窗口类上创建组件“封装”,所以如果你有一个自定义控制库需要在 Delphi 应用程序中使用,那么你可以创建一个你自己的 Delphi 组件,正如你像使用其他组件一样方便有效。那些在子类窗口控件使用的技术,如在 StdCrls 单元中所描述的标准 Windows 控件,如 Tedit。对 CLX 应用程序来说,如在 QStdCtls(单元中进行)描述。为使你的组件可以在 Delphi 环境中可用,你需要在设计时遵循一定的原则。这部分我们将讨论以下几个问题: Removing dependencies/消除依赖性 Setting properties, methods and events/设置属性、方法和事件 Encapsulating graphics/封装图形 Registering components/注册组件使组件可用的一种方法是在他们的代码中的某一部分添加限制。通过他们的自身特性,组件以不同的组合,次序和上下文方式被添加进应用程序。你应该在在任何条件下无条件地设计组件的功能(言下之意:将组件的功能设计放在组件设计的首位)。移除依赖的一个典型例子就是 TwinControl 的 Handle 属性。如果你曾经写过 Windows 应用程序,你就明白使一个程序可执行最难和最容易出现错误的方面正是你不能妥善处理好窗口控制,除非你已经通过呼叫 CreateWindow 的 API 函数来创建它。当有效窗口句柄需要被使用时,Delphi 窗口控制减少了用户的工作。通过使用描述窗口句柄的属性,无论窗口是否创建都可以用控制来进行检查:如果句柄无效,那么控制就创建一个窗口而后返回到次窗口句柄。因此,每当应用程序代码处理句柄属性时,我们都必须保证这是一个有效的句柄(即此窗口句柄必须有效才能让程序代码处理)。通过移除像创建窗口那样的后台任务,Delphi 组件才能让开发人员将自己的注意力集中在他们真正想做的事情上。在将一个窗口句柄传递给 API 函数之前,你并不需要认证句柄是否存在或者是创建窗口。应用程序开发人员能确保是有效的而无需经常地检查是否会产生错误。尽管创建一个消除依赖性的组件很耗时间,但是这毕竟还是值得的,它不仅使程序开发人员免受重复作业的苦工,而且它还能减少你的编写软件文献和技术支持的负担。除了在设计窗体中的可视化图形外,组件最显著的特征就是它的属性,事件和方法了。每一个特征都将在本书中详细讨论,但下面的讨论解释了某些使其作用的源动力。属性给于程序开发员设置或者读取变量值的能力。当处理这些值时,属性允许组件编写者隐藏基础数据结构或者对其进行特殊处理。使用属性具有以下几点优势:1 属性在设计期是可用的。应用程序开发人员能在不书写代码的情况下设置或变更属性的原始值。2 当程序员在给属性赋值时,属性能检查或初始化值。在设计期验证输入能避免产生错误。3 组件能根据需求创建合适的值。也许程序员常犯的最普遍的错误就是引用了一个未定义的变量。通过属性值预设,你能确保当前值总是符合需求的。4 属性允许你使用简单,一致的接口隐藏数据。你能在属性中改变组织信息的方式而无需让程序员看到你的修改方法(隐秘性)。 第3章,“Creating properties”,详细解释了如何在你的组件中添加属性的方法。 类方法是在类上而不是在类的具体实例上操作的程序和函数。例如,每个组件的创建方法(Create)是类方法。组件方法是在组件自身上操作的那些程序和函数。应用程序开发人员对组件使用方法以完成特定的动作或是返回一个数值而不被任何属性所包含。由于方法需要执行代码,故它们只能在执行时使用。方法因如下的原因而有用方法在数据存放的同一对象内封装为组件的功能。方法能把错综复杂的程序隐藏在一个简单,一致的接口下面。程序员可以在不知道方法如何工作或是它和另外一个组件的 AlignControls 方法之间的区别而直接使用该组件的 AlognControls 方法。方法允许使用一个简单的调用更新数个属性。第5章,“Creating methods”,将详细介绍如何在你的组件中添加新方法。事件是一个在运行期调用代码以响应输入或者其他行为的特殊属性。事件提供了开发人员一种特殊的方式配置在特定运行期所需产生的代码段,如鼠标行为和按键。当事件发生时,事件句柄将启动所需执行的代码。事件允许应用程序开发人员对不同的输入响应而不需要定义新组件。第4章,“Creating events”,阐述了如何引用标准事件和如何定义新事件的方法。Delphi 通过在 canvas 中封装不同的图形工具简化了 Windows 图形操作。Canvas 描述窗口或是控制的制图接口并且包含着其他的类,如 pen,brush,font。Canvas 如同一个 Windows 设备目录,但是它为你管理所有的制图方法。如果你曾写过图形化窗口应用程序,你将对受 Windows 图形化设备界面(GDI)影响的需求感到熟悉。例如,GDI 限制了可用设备目录的数量而且你需要在销毁你所存储的图形化对象之前先初始化它们。有了 Delphi,你大可不必担心这些事情。你可以通过处理组件的 Canvas 属性在一个设计界面上或者是其他的组件制图、。如果你想自定义一个 pen 或者 brush,你可以设置它的颜色和风格。当你完成时,Delphi 完成资源配置。如果你的应用程序需要经常的使用相同类型的资源,Delphi 会缓存这些资源以避免你不断重建(即是避免不断重建时消耗的系统资源)。你仍然可以完全处理 Windows GDI,但是如果你使用 Delphi 组件内建的 canvas,你会发现你的代码非常简单并且运行得更快。CLX 图形化封装的工作方式各不相同。Canvas 实际上是一个涂抹的工具。在设计界面或者是其他组件上制图,你要处理组件的 Canvas 属性。Canvas 是一个属性,并且它也有个对象称之为 Tcanvas。Tcanvas 是通过Handle(句柄)属性包封的 Qt 涂抹工具。你能使用句柄来处理低级的 Qt 图形库函数。如果你想自定义 pen 或是 brush,你可以设置它的颜色和样式。当你完成是,Delphi 或 Kylix 会配置好资源。CLX 应用程序也为资源分配缓存。你能通过递减在 CLX 组件内建的 canvas 来使用它们。图形如何在组件中工作完全取决于你组件继承自的对象的 canvas。图形特征将在第6章,“Using graphics in components”中详细说明。在你在 IDE 上安装你的组件之前,你先要注册这些组件。注册告诉 Delphi 在组件栏的什么位置上放置组件。你也可以自定义 Delphi在你的设计界面文件上存储组件的方法。注册一个组件的相关内容信息,请参考第8章,“Making components available at design time”。你能通过两种方法创建一个新组件:1 使用组件向导创建组件2 手动创建一个组件你可以使用两种方法中的任何一种来创建出一个安装到组件栏上的具有最低程度功能的组件。在安装后,你可以添加这个新组件到你的设计界面以在设计期和运行期测试。你可以给组件添加更多的功能,升级组件栏然后继续测试组件。无论何时你创建一个新组件,都需要以下几个基本步骤。这些步骤如下:(本文档的例子的前提是假设你已经了解如何使用了这几个步骤。)1 为新组件创建一个单元文件。2 从一个已存在组件类型中继承你的组件。3 添加属性,方法和事件。4 在 IDE 上注册你的组件。5 为你的组件创建一个位图图标。6 创建一个包(一种特殊的动态链接库DLL)以使能在 IDE 上安装组件。7 为你的组件及其属性,方法和事件创建一个帮助文档。【注意】 创建教导组件用户如何使用该组件帮助文档可以有选择性的进行当你完成时,一个完整的组件应该包含如下文件:A package (.BPL) or package collection (.DPC) file A compiled package (.DCP) file A compiled unit (.DCU) file A palette bitmap (.DCR) file A Help (.HLP) file你也可以创建一个位图来描述你的新组件。具体见“Creating a bitmap for a component”。第五部分余下的几章说明了创建组件的方方面面,并且提供了一部分编写不同类型组件的完整例子。组件向导简化了创建组件时的初始化。当你使用组件向导时,请按照如下操作:1 新建组件的初始类(即是新建组件来自哪个父类)2 新组件的类名。3 用户定义组件所在的组件栏上的页。4 创建组件的单元文件名称。5 单元文件搜索的路径名。6 你需要放置组件的包名。 当你手动创建组件时,组件向导按照相同的方法进行操作:1 启动组件向导,选择其中的一种方式:- 选择 Component|New Component。- 选择 File|New|Other 然后双击组件。2 在组件向导中填写相关值:- 在 Ancestor Type 中,指定新组件的类来源。【注意】 在下拉列表中,列出的组件会以不同的单元名一个是 VCL 应用程序另一个是 CLX 应用程序被列出两次。CLX 会以 Q 作为开头标识(如 Qgraphics 而不是 Graphic)。请确认你的组件继承正确的组件(类)。- 在 Class Name 中,指定你的新组件类的名称。- 在 Palette Page 中,指定你想安装的组件在组件栏上的位置。- 在 Unit File Name 上,指定组件声明类的单元文件的名称。如果单元不在搜索的路径里,需要在 Search Path 上编辑搜索路径。3 在填写完组件向导后,还需要:- 点击安装。把组件放置在包内(已存在的或是新的包内都可以),点击 Component|Install 然后在出现的对话框中指定包。具体请看“Testing uninstalled components”。4 点击 OK。IDE 创建了一个新单元。【警告】 如果你从一个由“Custom”开头的类(如TcustomControl)派生出组件,尽量不要把新组件放置在设计界面上,除非你重写了原始组件所有的抽象类。Delphi 不能创建具有抽象属性或者方法的类的实例对象。要看到单元的源码,单击 View Unit(如果组件向导已经关闭,通过选择 File|Open 打开代码编辑器打开单元文件)。Delphi 创建一个包含类声明和 Register 过程的新单元文件,并且添加了包含在所有标准 Delphi 单元中的 uses 子句。单元如下所示:unit MyControl;interfaceuses Windows, Messages, SysUtils, Types, Classes, Controls;type TMyControl = class(TCustomControl) private Private declarations protected Protected declarations public Public declarations published Published declarations end;procedure Register;implementationprocedure Register;begin RegisterComponents(Samples, TMyControl); /In CLX, use a different page than “Samples”end;end.【注意】 CLX 应用程序使用单独的单元,它们被以 Q 开头的同名单元所代替。例如,Qcontrols 单元代替了 Controls 单元,唯一的不同之处就是 uses 子句。如下所示:最简单的创建组件的方法是使用组件向导。另外,你也可以手动实现这些步骤。手动创建组件安如下步骤进行:1 创建一个单元文件2 从组件派生3 注册组件单元是个单独编译的 Delphi 代码模块。Delphi 为些目的使用单元文件。每个窗体都有自己的单元,大多数组件(或者相关的组件)也都有它们自己的单元文件。 创建组件时,你既可以为新组件创建一个新单元,也可以为已存在的单元增加新组件。 为组件创建一个新单元: 1 选择其中一种: - 打开 File|New|Unit。 - 打开 File|New|Other 显示 New Items 对话框,选择 Unit,点击 OK。 IDE 创建了一个新单元并且已经用代码编辑器打开。 2 使用有意义的名字保存文件。 3 派生组件类。1 选择 File|Open 并选择你想要加入到组件的源码单元。【注意】 当添加组件到一个已存在的单元中时,请确定单元文件只包含组件源码。例如,添加组件代码到包含窗体子句的单元将会在组件栏上报错。 2 派生组件类。每个组件都是派生自 Tcomponent 或者已存在的组件类而形成的更加专一的子类(如 Tcontrol 或者TgraphicControl)。“Creating components”介绍了不同组件窗体所派生的类。 派生类在“Defining new classes”中解释得更为详细。 要派生一个组件,需在组件的 interface 部分添加对象类型声明。 一个简单的组件类是直接从 Tcomponent 中派生过来的非可视组件。 创建一个简单类,添加在组件中 interface 部分类声明,如下:type TNewComponent = class(TComponent)end; 目前为止,新组件和 Tcomponent 没有任何不同。你已经创建了可用于制作新控件的框架。 派生类将在“Defining new classes”中做更详细的介绍。注册是个告诉 IDE 哪个组件增加到组件库,(哪个组件)添加到组件栏中的哪页的简单程序。更详细说明,请参看第8章,“Making components available at design time”。 注册一个组件: 1 在组建单元的 interface 部分添加一个名为 Register 的程序(过程)。Register 不使用参量,所以声明它非常简单。如果你要把组件添加到已经含有组件的单元中去,此单元就已经有了声明了的 Register 过程,因此你无需再改变此声明。【注意】 尽管 Delphi 是对语言大小写不敏感的工具,但是 Register 过程仍然是对大小写敏感的,而且必须以大写字母 R 拼写。 2 在单元的 Implementation 部分编写 Register 程序,需为你要注册的组件调用 RegisterComponets。RegisterComponents 是具有两个参数的程序:组件页名称和组件类型。如果对已经存在的注册添加组件,你既可以在已存在状态上添加新组件,也可以调用 RegisterComponents 来添加新的。注册一个名为 TmyControl 的组件并要放在组件栏的 Samples 页上,你应使用如下包含 TmyControl 的 Register 程序声明:procedure Register;begin RegisterComponents(Samples, TNewControl);end;这个 Register 程序将 TmyControl 放在组件栏的 Samples 页上。 注册了组件,你就能把它编译成包文件(见第8章,“Making components available at design time”)并且能在组件栏上安装。每个组件在组件栏上都需要一张位图表示。如果你不指定自己的位图,IDE 就使用默认的位图标识。由于栏位图仅在设计期时使用,所以你不需要把它编译进组件编辑单元,而是以 .dcr(动态组件资源)扩展。你可以使用图形编辑器创建资源文件。 当创建新组件时,你可以为你的自定义组件定义你自己的位图。 创建新位图: 1 选择 Tools|Image Editor。 2 在 Image Editor 对话框中,选择 File|New|Component 资源文件 (.dcr)。 3 在 untitled1.dcr 对话框中,右键菜单选中 New|Bitmap。 4 在 Bitmaps Properties 对话框中,更改宽和高为24象素并保证 VGA(16 colors)被选中,点击 OK。5 Bitmap 和 Bitmap1 出现在目录下,选择 Bitmap1,右键,选中 Rename。将 Bitmap 的名称命名为组件的类名(保持一致哦),包括 T,并全部使用大写字母。例如,如果你的新类名是TmyNewButton,那么 bitmap 的名称就是 TMYNEWBUTTON。【注意】 无论你在新组件对话框中怎么拼写类名,都必须全部使用大写字母。 6 双击 TMYNEWNAME 显示一空位图的对话框。 7 使用 Image Editor 底部的颜色面板设计你的图标。 8 在你需要声明组件类的单元中,选择 File|Save As 并赋予资源文件(.dcr or .res)相同的基名。如,命名资源文件 MyNewButton.dcr。 9 选择 Component|New Component。按照使用组件向导创建新组件说明操作。保证组件源码 MyNewButton.pas 和 MyNewButton.dcr 在同一目录下。组件向导,以 TmyNewButton 命名的组件的源码,或单元 MyNewButton.pas 以默认方式放置在 LIB 目录下。单击 Browse 按钮查找放置此继承组件单元文件的新的路径。【注意】 如果你为位图使用了 .res 文件而不是 .dcr 文件,那么,需要对组件源码中添加相关的关联以约束(固定)资源。例如,如果在保证了 .pas 和 .res 文件在相同目录下,你的 .res 文件命名为 MyNewButton.res,你需要在MyNewButton.pas 的 type 部分添加如下的代码: *R *.res 10 选择 Component|Install Component 在新包或者已存在的包中安装组件。点击 OK。你的新包就被创建好了然后安装。描述使用组件向导所设计的新组件的位图出现在组件栏上。安装包中组件到组件栏上: 1 选择 Component|Install Component。 出现 Install Component 对话框。 2 选择适用页面安装已知包或新建包中的组件。 3 输入包含新组件的 .pas 文件的名称或者选择 Browse 按钮查找单元。 4 若新组件的 .pas 文件不在默认目录下则调整搜索路径。 5 输入需安装组件的包名或者选择 Browse 按钮查找包。 6 如果组件被安装在新包内,可随意输入有意义的包说明。 7 选择 OK 关闭 Install Component 对话框。编译/重建包并且在组件栏上安装组件。 【注意】 新安装的组件最初都出现在组件栏组件作者指定的页上。在组件在组件栏上用安装后你可以使用 Component|Configure Palette 对话框把组件移动到其他页面。 需要向用户发布组件并安装到组件栏的作者,情参考“Making source files available”。组件编写者应使所有的源码文件为组件所在目录中可用。这些文件包括源代码文件(.pas)和另外一些工程文件(.dfm/.xfm, .res, .rc 和 .dcr)。添加组件的过程导致产生了大量的文件。这些文件会自动放在 IDE 环境选项(使用菜单命令 Tools|Environment 选项,切换到 Library 页)指定的目录下。.lib 文件放在 DCP 输出路径下。如果添加组件必须创建一个新包(与在已知包上安装相反),.bpl 文件被放在 BPL 输出目录下。在安装组件到组件栏之前,你能在运行期测试此组件的性能。这对调试新建的组件非常有用,无论是不是已经在组件栏上,它对其他其他组件也一样适用。要了解测试已安装的组件,参考“Testing installed components”。当在组件栏上的被选择组件放置到设计界面上时,就可以通过 Delphi 运行测试。 1 在窗体单元的 uses 子句添加组件单元名称。 2 在窗体上添加对象字段表示组件。 这是手动添加组件和 Delphi 自动添加组件之间最主要的区别。在窗体类型声明底部的 Public 部分添加对象字段。而 Delphi 则把它加在上面的类型声明的部分。 不要在 Delphi 管理部分的窗体类型声明添加字段。在此部分的类型声明的项目与窗体文件中存储的项目相对应。添加不存在窗体上的组件的名称会导致你的窗体文件失效。 3 在窗体的 OnCreate 事件添加句柄。 4 在窗体的 OnCreate 句柄中构造组件。 当你使用组件构造器时,你必须传递一个指定给组件的参数(在需要时,该组件负责销毁组件)。你总是需要传递 Self 作为其所有者。作为一种方法,Self 是包含方法的对象的参考。既然如此,在窗体中 OnCreate 句柄,Self 与窗体相关。 5 分配 Parent(当前)属性。 设置Parent(当前)属性总是在构造控制后首先需要做的事情。父类是包含不可见控制的组件;通常是控制出现的窗体,但也可能是 Group Box 或者是 Panel。一般,你需要设置 Parent 为窗体的 Self。在设置控制的其他属性之前需要设置 Parent(当前)属性。【警告】 若你的控制不是组件(即 Tcontrol 不是祖先的一类),跳过这一步。如果你不经意地设置了窗体的Parent(当前)属性(而非组件的Parent(当前)属性)为 Self,将引起操作系统错误。 6 在设计时设置其他的组件属性。 假设你要测试一个在 MyControl 单元文件中的类型为 TmyControl 的新组件,创建一个新工程,而后按照如下步骤结束窗体单元:unit Unit1;interfaceuses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, MyControl; 1. Add NewTest to uses clause type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); 3. Attach a handler to OnCreate private Private declarations public Public Declarations MyControl1: TMyControl1; 2. Add an object field end;var Form1: TForm1;implementation$R *.DFMprocedure TForm1.FormCreate(Sender: TObject);begin MyControl1 := TMyControl.Create(Self); 4. Construct the component MyControl1.Parent := Self; 5. Set Parent property if component is a control MyControl1.Left := 12; 6. Set other properties. nue as needed end;end.在组件栏上安装了之后,你可以在设计期测试控件的性能。对调试新建的控件而言这非常有用,但无论组件是否在组件栏上,对于其他组件的测试也是使用相同的方法。想要了解更多未安装组件的测试信息,参考“Testing uninstalled components”。 安装后测试组件允许你在窗体上放置组件,但仅调试在设计期产生的异常。 使用 IDE 第二连续实例测试已安装的组件。 1 选择 Project|Options 在 Directories/Conditionals 上,在 Debug Source Path 上设置组件的源码文件路径。 2 选择 Tools|Debugger 选项。在 Language Exceptions 页上,使你想要跟踪的异常可用。 3 打开组件源码文件设置断点。 4 选择 Run|Parameters 并设置 Host Application 字段名称,定位 Delphi 执行文件的位置。 5 在 Run Parameteres 对话框中,点击 Load 按钮运行Delphi 的第二实例。 6 在窗体上安放在源码中出错的断点的组件继续。如果你曾经使用 Delphi 写过程序,你就应当明白一个类包含了数据和代码,而且你可以在设计期和运行期处理类。在本部分,你将扮演组件用户的角色。 当你新建组件时,你需要处理那些应用程序开发人员无需使用的类。你也要尽量对使用这些组件的开发人员隐瞒组件的内部工作方式。通过为你的组件选择适当的祖先,设计出只显示开发人员需要的属性和方法界面并按照本章其他的指导方法,你可以创建通用并可再生使用的组件。 在开始创建这些组件时,你需要熟悉这些关于面向对象编程(OOP)的文章: .定义新类 .祖先类,子类和类的层次 .访问控制 .分派方法 .抽象类成员 .类和指示器组建编写人员和应用程序开发人员的不同之处在于应用程序开发人员处理类的实例就相当于组件编写人员创建出新类。 一个类本质上是个类型。作为程序员,即使你从不使用类型和实例,你都需要处理它们。例如,你可以创建一个可变类型,如 Integer。类通常要比简单数据类型还要复杂,但它们工作的方式是一样的:通过分配不同的值给相同类型的实例来完成不同的功能。 例如,创建一个含有两个按钮的窗体 一个名为 OK 一个名为 Cancel。每个按钮都是 Tbutton 类的实例,但是在它们的 Caption 属性和 OnClick 事件 各自分配了不同的值和句柄,你使得这两个实例以不同的方式运作起来。重建新类有两个理由: .改变默认类以避免重复 .给类添加新功能 在任何一个案例中,目标都是建立可再生的对象。如果你在脑海中以设计可再生组件为先,那么在以后的工作中将会减少你的工作量。让你的类可用默认值,但是也要允许它们可以被自定义。 大多数程序员都试图避免重复。那么,如果你发现自己再三地重写相同的代码,你就可以把这些代码设计成子程序或是函数,亦或者是在程序中建立一个程序库使用。对组件而言这也是一个理由。如果你发现自己需要改变相同的属性或是调用相同的方法,你就可以创建一个把这些事情作为默认设置的组件了。 例如,假设你每次创建应用程序时,你都要添加一个对话框来执行特定的操作步骤。尽管每次重建对话框并不是很困难,但是这不是必需每次都如此的。你可以设计一个对话框,设置好它的属性并在组件栏上把它封装成相关联的组件。通过把对话框制作成可再生组件,你不仅可以消除重复的工作,而且能促进标准化,并能在每次重建对话框的情况下减少错误的可能性。第9章,“Modifying an existing component”,展示了一个如何改变默认属性的例子。【注意】 如果你只想修改已知组件的已知属性或是保存组件的特定事件句柄。你可以通过创建组件模板轻松搞定。 创建新组件一个普遍的原因是:在已知组件上添加没有的新功能。当你这么做时,你要从一个已知组件或是抽象基础类上获得新组件,如 Tcomponent 或是 Tcontrol。 从你包含所需特征最接近的子集的类中产生新组件。你可以对类添加新功能,但是却不能从中移除;因此,如果已知组件类包含你不需要的属性时,你要从此组件的祖先类开始编写。 例如,如果你想对 listbox 添加新功能,那么你要从 TlistBox 中获取新组件。然而,如果你想添加新组件但是要包含一些标准列表框的特征,你将不得不从 TcustomListBox TlistBox 的祖先,重写组件。然后你可以重建你想要的列表框功能,并添加新的特征。 第11章,“Customizing a grid”,展示了自定义抽象组件类的例子。包括标准组件,Delphi 也提供了许多为编写组件设计成基础类的抽象方法。下表显示了创建组件时你可以使用的一些类。 声明新组件类,需在组件单元文件添加类声明。 这里是对一个简单绘图组件的声明: type TSampleShape = class(TGraphicControl) end; 一个完整的组件声明通常包括在 end 之前的属性,事件和方法的声明。声明也是有效的,并且是提供组件额外特征的起始点。应用程序开发人员想当然的认为每个控制在窗体上都具有名为 Name 和 Left 的属性。他们并不关心所有的控制都继承自 Tcontrol 祖先类的属性。然而,当你创建组件时,你必须知道组件源自哪个类并继承它的哪些属性。你也要知道你的控制继承的每个细节,你才能不重建它们而利用这些继承来的特征。 你所创建的组件的祖先类被称为 Immediate Ancestor(直接祖先)。每个组件都继承自直接祖先,依此类推,直接祖先也是如此。所有继承自组件的类都源自被称为自祖先的类;组件是其祖先的子类。 总的来讲,在应用程序中,所有的父子关系组成了类层次。由于类继承了其祖先所有的一切,故层次中每一层都包含有它的祖先,然后在已知的类上添加新属性和方法或是重定义这些类。 如果你不想指定某一直接祖先,Delphi 允许你从默认的祖先 Tobject 上获得组件。在对象层次上,Tobject 是所有类的祖先。 选择从哪个对象上获得新组件的规则是很简单的:选择包含你所创建的组件特征尽可能多的对象,但在你的新对象中并不包含那些你不需要的特征。你可以在你的对象中添加这些特征,但是你不能抵充这些特征。Access Control(访问控制)通常称为 Visibility 在属性,方法和字段范围上有5个分级。Visibility 能控制代码访问类的部分。通过指定 Visibility,你可以对你的组件定义接口。 表2.1显示了 Visibility 从最严格限制到最多访问的级别: 当你只要它们在定义它们的类中可用就在 Private 下声明成员;当你想在类及其子类中可用就把它们作为 Protected 声明。记住,如果成员在单元文件中可以使用,那么在文件中无论在何处都可用。因此,如果在相同单元定义2个类,则在它们各自的方法中都可以互相访问。如果从它的祖先那儿在不同单元获得一个类,在此新单元的所有的类都能访问祖先的受保护方法。在 private 中声明的部分类只能在单元的代码中处理。在单元内部包含有声明,只要是公用的,代码能处理这些部分。 接下来的例子将展示一个作为 private 的字段如何避开应用程序开发人员视线。清单显示了两个 VCL 窗体单元。每个窗体都有 OnCreate 事件的句柄给 private 字段分配值。编译器只允许给那些声明过的字段指派。unit HideInfo;interfaceuses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs;type TSecretForm = class(TForm) declare new form procedure FormCreate(Sender: TObject); private declare private part FSecretCode: Integer; declare a private field end;var SecretForm: TSecretForm;implementation$R *.dfmprocedure TSecretForm.FormCreate(Sender: TObject);begin FSecretCode := 42; this compiles correctly end;end. end of unit -unit T

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论