当前位置:文档之家› 第十九章 Delphi自定义部件开发

第十九章 Delphi自定义部件开发

第十九章 Delphi自定义部件开发
第十九章 Delphi自定义部件开发

第十九章Delphi自定义部件开发(一)

Delphi除了支持使用可视化部件所见即所得地建立应用程序外,还支持为开发应用而设计自己的部件。

在本章中将阐述如何为Delphi应用程序编写部件。这一章将达到两个目的:

●教你如何自定义部件

●使你的部件成为Delphi环境的有机组合部分

19.1 Delphi部件原理

19.1.1 什么是部件

部件是Delphi应用程序的程序构件。尽管大多数部件代表用户界面的可见元素,但部件也可以是程序中的不可见元素,如数据库部件。为弄清什么是部件可以从三个方面来考察它:功能定义、技术定义和经验定义。

1. 部件的功能定义

从最终用户角度,部件是在Component Palette上选择的,并在窗体设计窗口和代码窗口中操作的元素。从部件编写者角度,部件是代码中的对象。在编写部件之前,你应用相当熟悉已有的Delphi部件,这样才能使你的部件适合用户的需要。编写部件的目标之一是使部件尽可能的类似其它部件。

2. 部件的技术定义

从最简单的角度看,部件是任何从TComponent继承的对象。TComponent 定义了所有部件必须要的、最基本的行为。例如,出现在Component Palette 上和在窗体设计窗口中编辑的功能。但是TComponent并不知如何处理你的部件的具体功能,因此,你必须自己描述它。

3. 部件编写者自己的定义。

在实际编程中,部件是能插入Delphi开发环境的任何元素。它可能具有程序的各种复杂性。简而言之,只要能融入部件框架,部件就是你用代码编写的一切。部件定义只是接口描述,本章将详细阐述部件框架,说明部件的有限性,正如说明编程的有限性。本章不准备教你用所给语言编写每一种部件,只能告诉编定代码的方法和怎样使部件融入Delphi环境。

19.1.2 编写部件的不同之处

在Delphi环境中建立部件和在应用程序中使用部件有三个重要差别:

●编写部件的过程是非可视化的

●编写部件需要更深入的关于对象的知识

●编写部件需要遵循更多的规则

1. 编写部件是非可视化的

编写部件与建立Delphi应用最明显的区别是部件编写完全以代码的形式进行,即非可视化的。因为Delphi应用的可视化设计需要已完成的部件,而建立这些部件就需要用Object Pascal 代码编写。

虽然你无法使用可视化工具来建立部件,但你能运用Delphi开发环境的所有编程特性如代码编辑器、集成化调试和对象浏览。

2. 编写部件需要更深的有关对象的知识

除了非可视化编程之外,建立部件和使用它们的最大区别是:当建立新部件时,需要从已存部件中继承产生一个新对象类型,并增加新的属性和方法。另一方面,部件使用者,在建立Delphi应用时,只是使用已有部件。在设计阶段通过改变部件属性和描述响应事件的方法来定制它们的行为。

当继承产生一个新对象时,你有权访问祖先对象中对最终用户不可见的部分。这些部分被称为protected界面的。在很大部分的实现上,后代对象也需要调用他们的祖先对象的方法,因此,编写部件者应相当熟悉面向对象编程特性。

3. 编写部件要遵循更多的规则

编写部件过程比可视化应用生成采用更传统的编程方法,与使用已有部件相比,有更多的规则要遵循。在开始编写自己的部件之前,最重要的事莫过于熟练应用Delphi自带的部件,以得到对命名规则以及部件用户所期望功能等的直观认识。部件用户期望部件做到的最重要的事情莫过于他们在任何时候能对部件做任何事。编写满足这些期望的部件并不难,只要预先想到和遵循规则。

19.1.3 建立部件过程概略

简而言之,建立自定义部件的过程包含下列几步:

●建立包含新部件的库单元

●从已有部件类型中继承得到新的部件类型

●增加属性、方法和事件

●用Delphi注册部件

●为部件的属性方法和事件建立Help文件

如果完成这些工作,完整的部件包含下列4个文件

●编译的库单元( .DCU文件)

●选择板位图(.DCR文件)

● Help文件(.HLP文件)

● Help-keyword文件(.KWF文件)

19.2 Delphi部件编程方法

19.2.1 Delphi部件编程概述

19.2.1.1 Delphi可视部件类库

Delphi的部件都是可视部件类库(VCL)的对象继承树的一部分,下面列出组成VCL的对象的关系。TComponent是VCL中每一个部件的共同祖先。TComponent提供了Delphi部件正常工作的最基本的属性和事件。库中的各条分支提供了其它的更专一的功能。

当建立部件时,通过从对象树中已有的对象继承获得新对象,并将其加入VCL 中。

19.2.1.2 建立部件的起点

部件是你在设计时想操作的任意程序元素。建立新部件意味着从已有类型中继承得到新的部件对象类。

建立新部件的主要途径如下:

●修改已有的控制

●建立原始控制

●建立图形控制

●建立Windows控制的子类

●建立非可视部件

下表列出了不同建立途径的起始类

表19.1 定义部件的起始点

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

途径起始类

─────────────────────────────

修改已有部件任何已有部件,如TButton、TListBox

或抽象部件对象如TCustomListBox

建立原始控制TCustomControl

建立图形控制TGraphicControl

建立窗口控制的子类TWinControl

建立非可视部件TComponent

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

也可以继承非部件的其它对象,但无法在窗体设计窗口中操作它们。Delphi 包括许多这种对象,如TINIFile、TFont等。

1. 修改已有控制

建立部件的最简单的方法是继承一个已有的、可用的部件并定制它。可以从Delphi提供的任何部件中继承。例如,可以改变标准控制的缺省属性值,如TButton。

有些控制,如Listbox和Grid等有许多相同变量,在这种情况下,Delphi 提供了抽象控制类型,从该类型出发可定制出许多的类型。例如,你也许想建立TListBox的特殊类型,这种部件没有标准TListBox的某些属性,你不能将属性从一个祖先类型中移去,因此你需要从比TListBox更高层次的部件继承。例如TCustomListBox,该部件实现了TCustomListBox的所有属性但没有公布(Publishing)它们。当从一个诸如TCustomListBox的抽象类中继承时,你公布那些你想使之可获得的属性而让其它的保护起来(protected)。

2. 建立原始控制

标准控制是在运行时可见的。这些标准控制都从TWinControl,继承来的,当你建立原始控制时,你使用TCustomControl作为起始点。标准控制的关键特征是它具有窗口句柄,句柄保存在属性Handle中,这种控制:

●能接受输入焦点

●能将句柄传送给Windows API函数

如果控制不需要接受输入焦点,你可把它做成图形控制,这可能节省系统资源。

3. 建立图形控制

图形控制非常类似定制的控制,但它们没有窗口句柄,因此不占有系统资源。对图形控制最大的限制是它们不能接收输入焦点。你需要从TGraphicControl继承,它提供了作图的Canvas和能处理WM_PAINT消息,你需要覆盖Paint方法。

4. 继承窗口控制

Windows中有一种称之为窗口类的概念,类似于面向对象的对象和类的概念。窗口类是Windows中相同窗口或控制的不同实例之间共享的信息集合。当你用传统的Windows编程方法创建一种新的控制,你要定义一个新的窗口类,并在Windows中注册。你也能基于已有的窗口类创建新的窗口类。这就称为从窗口类继承。在传统的Windows编程中,如果你想建立客户化的控制,你就必须将其做在动态链接库里,就象标准Windows控制,并且提供一个访问界面。使用Delphi,你能创建一个部件包装在已有窗口类之上。如果你已有客户化控制的库,并想使其运行在你的Delphi应用中,那你就能创建一个使你能使用已有控制和获得新的控制的部件。在库单元StdCtrls中有许多这样的例子。

5. 建立非可视化的部件

抽象对象类型TComponent是所有部件的基础类型。从TComponent直接继承所创建的部件就是非可视化部件。你编写的大多数部件都是可视控制。TComponent定义了部件在FormDesigner中所需的基本的属性和方法。因此,从TComponent继承来的任何部件都具备设计能力。

非可视部件相当少,主要用它们作为非可视程序单元(如数据库单元)和对话框的界面。

19.2.1.3 建立新部件的方法

建立新部件的方法有两种:

●手工建立部件

●使用Component Expert

一旦完成建立后,就得到所需的最小功能单位的部件,并可以安装在Component Palette上。安装完后,你就能将新部件放置在窗体窗口,并可在设计阶段和运行阶段进行测试。你还能为部件增加新的特征、更新选择板、重新测试。

1. 手工创建部件

显然创建部件最容易的方法是使用Component Expert。然而,你也能通过手工来完成相同步骤。

手工创建部件需要下列三步:

●创建新的库单元

●继承一个部件对象

●注册部件

⑴创建新的库单元

库单元是Object Pascal代码的独立编译单位。每一个窗体有自己的库单元。大多数部件(在逻辑上是一组)也有自己的库单元。

当你建立部件时,你可以为部件创建一个库单元,也可将新的部件加在已有的库单元中。

①为部件创建库单元,可选择File/New... ,在New Items对话框中选择Unit,Delphi将创建一个新文件,并在代码编辑器中打开它

②在已有库单元中增加部件,只须选择File/OPen为已有库单元选择源代码。在该库单元中只能包含部件代码,如果该库单元中有一个窗体,将产生错误

⑵继承一个部件对象

每个部件都是TComponent的后代对象。也可从TControl、TGraphicControl 等继承。

为继承一个部件对象,要将对象类型声明加在库单元的interface部分。

例如,建立一个最简单的从TComponent直接继承非可视的部件,将下列的类型定义加在部件单元的interface部分。

type

TNewComponent=class(TComponent)

……

end;

现在你能注册TNewComponent。但是新部件与TComponent没什么不同,你只创建了自己部件的框架。

⑶注册部件

注册部件是为了告诉Delphi什么部件被加入部件库和加入Component Palette的哪一页。

为了注册一个部件:

①在部件单元的interface部分增加一个Register过程。Register不带任何参数,因此声明很简单:

procedure Register;

如果你在已有部件的库单元中增加部件,因为已有Register 过程,因此不须要修改声明。

②在库单位的implementation部件编写Register过程为每一个你想注册的部件调用过程RegisterComponents,过程RegisterComponents带两个参数:Component Palette的页名和部件类型集。例如,注册名为TNewComponent 的部件,并将其置于Component Palette的Samples页,在程序中使用下列过程:

procedure Register;

begin

RegisterComponents('Samples', [TNewComponent]);

end;

一旦注册完毕,Delphi自动将部件图标显示在Component Palette上。

2. 使用Component Expert(部件专家)

你能使用Component Expert创建新部件。使用Component Expert简化了创建新部件最初阶段的工作,因为你只需描述三件事:

●新部件的名字

●祖先类型

●新部件要加入的Component Palette页名

Component Expert执行了手工方式的相同工作:

●建立新的库单元

●继承得到新部件对象

●注册部件

但Component Expert不能在已有单元中增加部件。

可选择File/New... ,在New Items对话框中选择Component,就打开Component Expert对话框。

填完Component Expert对话框的每一个域后,选择OK。Delphi建立包括新部件和Register过程的库单元,并自动增加uses语句。

你应该立刻保存库单元,并给予其有意义的名字。

19.2.1.4. 测试未安装的部件

在将新部件安装在Component Palette之前就能测试部件运行时的动作。这对于调试新部件特别有用,而且还能用同样的技术测试任意部件,无论该部件是否出现在Component Palette上。

从本质上说,你通过模仿用户将部件放置在窗体中的Delphi的动作来测试一个未安装的部件。

可按下列步骤来测试未安装的部件

1. 在窗体单元的uses语句中加入部件所在单元的名字

2. 在窗体中增加一个对象域来表示部件

这是自己增加部件和Delphi增加部件的方法的主要不同点。

你将对象域加在窗体类型声明底部的public部分。Delphi则会将对象域加在底部声明的上面。

你不能将域加在Delphi管理的窗体类型的声明的上部。在这一部分声明的对象域将相应在存储在DFM文件中。增加不在窗体中存在的部件名将产生DFM 文件无效的错误。

3. 附上窗体的OnCreate事件处理过程

4. 在窗体的OnCreate处理过程中构造该部件

当调用部件的构造过程时,必须传递Owner参数(由Owner负责析构该部件)一般说来总是将Self作为Owner的传入参数。在OnCreate中,Self是指窗体。

5. 给Component的Parent属性赋值

设置Parent属性往往是构造部件后要做的第一件事时。Parent在形式上包

含部件,一般来说Parent是窗体或者GoupBox、Panel。通常给Parent赋与Self,即窗体。在设置部件的其它属性之前最好先给Parent赋值。

6. 按需要给部件的其它属性赋值

假设你想测试名为TNewComponent类型的新部件,库单元名为NewT est。窗体库单元应该是这样的;

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.

19.2.1.5 编写部件的面向对象技术

部件使用者在Delphi环境中开发,将遇到在包含数据和方法的对象。他们将在设计阶段和运行阶段操作对象,而编写部件将比他们需要更多的关于对象的知识,因此,你应当熟悉Delphi的面向对象的程序设计。

1. 建立部件

部件用户和部件编写者最基本的区别是用户处理对象的实例,而编写者创建新的对象类型。这个概念是面向对象程序设计的基础。例如,用户创建了一个包含两个按钮的窗体,一个标为OK,另一个标为Cancel,每个都是TButton的实例,通过给T ext、default和Cancel等属性赋不同的值,给OnClick事件赋予不同的处理过程,用户产生了两个不同的实例。

建立新部件一般有两个理由

●改变类型的缺省情况,避免反复

●为部件增加新的功能

目的都是为了建立可重用对象。如果从将来重用的角度预先计划和设计,能节省一大堆将来的工作。

在程序设计中,避免不必要的重复是很重要的。如果发现在代码中一遍又一遍重写相同的行,就应当考虑将代码放在子过程或函数中,或干脆建立一个函数库。

设计部件也是这个道理,如果总是改变相同的属性或相同的方法调用,那应创建新部件。

创建新部件的另一个原因是想给已有的部件增加新的功能。你可以从已有部件直接继承(如ListBox)或从抽象对象类型继承(如TComponent,TControl)。你虽然能为部件增加新功能,但不能将原有部件的属性移走,如果要这样做的话,就从该父对象的祖先对象继承。

2. 控制部件的访向

Object Pascal语言为对象的各部分提供了四个级别的访问控制。访问控制让你定义什么代码能访问对象的哪一部分。通过描述访问级别,定义了部件的接口。如果合理安排接口,将提高部件的可用性和重用性。

除非特地描述,否则加在对象里的域、方法和属性的控制级别是published,这意味着任何代码可以访问整个对象。

下表列出各保护级别:

表19.2 对象定义中的保护级别

━━━━━━━━━━━━━━━━━━━

保护级用处

───────────────────

private 隐藏实现细节

protected 定义开发者接口

public 定义运行时接口

published 定义设计时接口

━━━━━━━━━━━━━━━━━━━

所有的保护级都在单元级起作用。如果对象的某一部分在库单元中的一处可访向,则在该库单元任意处都可访向。

⑴隐藏实现细节

如果对象的某部分被声明为private,将使其它库单元的代码无法访问该部

分,但包含声明的库单元中的代码可以访问,就好象访问public一样,这是和

C++不同的。

对象类型的private部分对于隐藏详细实现是很重要的。既然对象的用户不能访问,private部分,你就能改变对象的实现而不影响用户代码。

下面是一个演示防止用户访问private域的例子:

unit HideInfo;

interface

uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms,

Dialogs;

type

TSecretForm = class(TForm) { 声明新的窗体窗口}

procedure FormCreate(Sender: TObject);

private { declare private part }

FSecretCode: Integer; { 声明private域}

end;

var

SecretForm: TSecretForm;

implementation

procedure TSecretForm.FormCreate(Sender: TObject);

begin

FSecretCode := 42;

end;

end.

unit TestHide; { 这是主窗体库单元}

interface

uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms,

Dialogs, HideInfo; { 使用带TSecretForm声明的库单元}

type

TTestForm = class(TForm)

procedure FormCreate(Sender: TObject);

end;

var

TestForm: TTestForm;

implementation

procedure TTestForm.FormCreate(Sender: TObject);

begin

SecretForm.FSecretCode := 13; {编译过程将以"Field identifier expected"错误停止}

end;

end.

⑵定义开发者接口

将对象某部分声明为protected,可使在包含该部件声明的库单元之外的代码无法访问,就象private部分。protected部分的不同之处是,某对象继承该对象,则包含新对象的库单元可以访问protected部分,你能使用protected声明定义开发者的接口。也就是说。对象的用户不能访向protected部分,但开发者通过继承就可能做到,这意味着你能通过protected部分的可访问性使部件编写者改变对象工作方式,而又不使用户见到这些细节。

⑶定义运行时接口

将对象的某一部分定义为public可使任何代码访问该部分。如果你没有对域方法或属性加以private、protected、public的访问控制描述。那么该部分就是published。

因为对象的public部分可在运行时为任何代码访问,因此对象的public部分被称为运行接口。运行时接口对那些在设计时没有意义的项目,如依靠运行时信息的和只读的属性,是很有用的。那些设计用来供用户调用的方法也应放在运行时接口中。

下例是一个显示两个定义在运行时接口的只读属性的例子:

type

TSampleComponent = class(TComponent)

private

FTempCelsius: Integer; { 具体实现是private }

function GetTempFahrenheit: Integer;

public

property TempCelsius: Integer read FTempCelsius; { 属性是public } property TempFahrenheit: Integer read GetTempFahrenheit;

end;

function GetTempFahrenheit: Integer;

begin

Result := FTempCelsius * 9 div 5 + 32;

既然用户在设计时不能改变public部分的属性的值,那么该类属性就不能出现在Object Inspector窗口中。

⑷定义设计时接口

将对象的某部分声明为published,该部分也即为public且产生运行时类型信息。但只有published部分定义的属性可显示在Object Inspector窗口中。对象的published部分定义了对象的设计时接口。设计时接口包含了用户想在设计时定制的一切特征。

下面是一个published属性的例子,因为它是published,因此可以出现在Object Inspector窗口:

TSampleComponent = class(TComponent)

private

FTemperature: Integer; { 具体实现是private }

published

property Temperature: Integer read FTemperature write FTemperature; { 可写的}

end;

3. 派送方法

派送(Dispatch)这个概念是用来描述当调用方法时,你的应用程序怎样决定执行什么样的代码,当你编写调用对象的代码时,看上去与任何其它过程或函数调用没什么不同,但对象有三种不同的派送方法的方式。

这三种派送方法的类型是:

●静态的

●虚拟的

●动态的

虚方法和动态方法的工作方式相同,但实现不同。两者都与静态方法相当不同。理解各种不同的派送方法对创建部件是很有用的。

⑴静态方法:

如果没有特殊声明,所有的对象方法都是静态的.。静态方法的工作方式正如一般的过程和函数调用。在编译时,编译器决定方法地址,并与方法联接。

静态方法的基本好处是派送相当快。因为由编译器决定方法的临时地址,并直接与方法相联。虚方法和动态方法则相反,用间接的方法在运行时查找方法的地址,这将花较长的时间。

静态方法的另一个不同之处是当被另一类型继承时不做任何改变,这就是说如果你声明了一个包含静态方法的对象,然后从该对象继承新的对象,则该后代对象享有与祖先对象相同的方法地址,因此,不管实际对象是谁,静态方法都完成相同的工作。

你不能覆盖静态方法,在后代对象中声明相同名称的静态方法都将取代祖先对象方法。

在下列代码中,第一个部件声明了两静态方法,第二个部件,声明了相同名

字的方法取代第一个部件的方法。

type

TFirstComponent = class(TComponent)

procedure Move;

procedure Flash;

end;

TSecondComponent = class(TFirstComponent)

procedure Move; { 尽管有相同的声明,但与继承的方法不同}

function Flash(HowOften: Integer): Integer; { 同Move方法一样}

end;

⑵虚方法

调用虚方法与调用任何其它方法一样,但派送机制有所不同。虚方法支持在后代对象中重定义方法,但调用方法完全相同,虚方法的地址不是在编译时决定,而是在运行时才查找方法的地址。

为声明一个新的方法,在方法声明后增加virtual指令。方法声明中的virtual 指令在对象虚拟方法表(VMT)中创建一个入口,该虚拟方法表保存对象类所有虚有拟方法的地址。

当你从已有对象获得新的对象,新对象得到自己的VMT,它包含所有的祖先对象的VMT入口,再增加在新对象中声明的虚拟方法。后代对象能覆盖任何继承的虚拟方法。

覆盖一个方法是扩展它,而不是取代它。后代对象可以重定义和重实现在祖先对象中声明的任何方法。但无法覆盖一个静态方法。覆盖一个方法,要在方法声明的结尾增加override指令,在下列情况,使用override将产生编译错误:

●祖先对象中不存在该方法

●祖先对象中相同方法是静态的

●声明与祖先对象的(如名字、参数)不匹配

下列代码演示两个简单的部件。第一个部件声明了三个方法,每一个使用不同的派送方式,第二个部件继承第一个部件,取代了静态方法,覆盖了虚拟方法和动态方法。

type

TFirstComponent = class(TCustomControl)

procedure Move; { 静态方法}

procedure Flash; virtual; { 虚方法}

procedure Beep; dynamic; { 动态虚拟方法}

end;

TSecondComponent = class(TFirstComponent)

procedure Move; { 声明了新的方法}

procedure Flash; override; { 覆盖继承的方法}

procedure Beep; override; { 覆盖继承的方法}

end;

⑶动态方法

动态方法是稍微不同于虚拟方法的派送机制。因为动态方法没有对象VMT 的入口,它们减少了对象消耗的内存数量。派送动态方法比派送一般的虚拟方法慢。因此,如果方法调用很频繁,你最好将其定义为虚方法。

定义动态方法时,在方法声明后面增加dynamic指令。

与对象虚拟方法创建入口不同的是dynamic给方法赋了一数字,并存储相应代码的地址,动态方法列表只包含新加的和覆盖的方法入口,继承的动态方法的派送是通过查找每一个祖先的动态方法列表(按与继承“反转的顺序”),因此动态方法用于处理消息(包括Windows消息)。实际上,消息处理过程的派送方式与动态方法相同,只是定义方法不同

⑷对象与指针

在Object Pascal中,对象实际上是指针。编译器自动地为程序创建对象指针,因此在大多数情况下,你不需要考虑对象是指针。但当你将对象作为参数传递时,这就很重要了。通常,传递对象是按值而非按引用,也就是说,将对象声明为过程的参数时,你不能用var参数,理由是对象已经是指针引用了。

第十九章Delphi自定义部件开发(二)

19.2.2 Delphi部件编程

19.2.2.1 创建属性

属性(Property)是部件中最特殊的部分,主要因为部件用户在设计时可以看见和操作它们,并且在交互过程中能立即得到返回结果。属性也很重要,因为如果将它们设计好后,将使用户更容易地使用,自己维护起来也很容易。

为了使你在部件中更好地使用属性,本部分将介绍下列内容:

● 为什么要创建属性

● 属性的种类

● 公布(publishing)继承的属性

● 定义部件属性

● 编写属性编辑器

1. 为什么要创建属性

属性提供非常重要的好处,最明显的好处是属性在设计时能出现在Object Inspector窗口中,这将简化编程工作,因为你只需读用户所赋的值,而不要处理构造对象的参数。

从部件使用者的观点看,属性象变量。用户可以给属性赋值或读值,就好象属性是对象的域。

从部件编写者的观点看属性比对象的域有更强的功能;

⑴ 用户可以在设计时设置属性

这是非常重要的,因为不象方法,只能在运行时访问。属性使用户在运行程序之前就能定制部件,通常你的部件不应包含很多的方法,它们的功能可以通过属性来实现。

⑵ 属性能隐藏详细的实现细节

⑶ 属性能引起简单地赋值之外的响应,如触发事件

⑷ 用于属性的实现方法可以是虚拟方法,这样看似简单的属性在不同的部件中,将实现不同的功能。

2. 属性的类型

属性可以是函数能返回的任何类型,因为属性的实现可以使用函数。所有的Pascal类型,兼容性规则都适用属性。为属性选择类型的最重要的方面是不同的类型出现在Object Inspector窗口中的方式不同。Object Inspector将按不同的类型决定其出现的方式。

你也能在注册部件时描述不同的属性编辑器。

下表列出属性出现在Object Inspector窗口中的方式

表19.3 属性出现在Object Inspector窗口中的方式

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

属性类型处理方式

───────────────────────────────────────

简单类型Numeric、Character和String属性出现在Object Inspector中,用户可

以直接编辑

枚举类型枚举类型的属性显示值的方式定义在代码中。选择时将出现下拉

式列表框,显示所有的可能取值。

集合类型集合类型出现在Object Inspector窗口中时正如一个集合,展开后,用

户通过将集合元素设为True或False来选择。

对象类型作为对象的属性本身有属性编辑器,如果对象有自己的published属性,用户在Object Inspector中通过展开对象属性列,可以独立编辑它们,

对象类型的属性必须从TPersistent继承。

数组类型数组属性必须有它们自己的属性编辑器,Object Inspector没有内嵌对数

组属性编辑的支持。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

3. 公布继承的属性

所有部件都从祖先类型继承属性。当你从已有部件继承时,新部件将继承祖先类型的所有属性。如果你继承的是抽象类,则继承的属性是protected或public,但不是published。如想使用户访问protected或public属性,可以将该属性重定义为published。如果你使用TWinControl继承,它继承了Ctl3D属性,但是protected的,因此用户在设计和运行时不能访问Ctl3D,通过在新部件中将Ctl3D重声明为published,就改变了Ctl3D的访问级别。下面的代码演示如何将Ctl3D声明为published,使之在设计时可被访问。

type

TSampleComponent=class(TWinControl)

published

property Ctl3D;

end;

4. 定义部件属性

⑴ 属性的声明

声明部件的属性,你要描述:

● 属性名

● 属性的类型

● 读和设置属性值的方法

至少,部件属性应当定义在部件对象声明的public部分,这样可以在运行时很方便地从外部访问;为了能在设计时编辑属性,应当将属性在published部分声明,这样属性能自动显示在Object Inspector窗口中。下面是典型的属性声明:

type

TYourComponent=class(TComponent)

private

FCount: Integer { 内部存储域}

function GetCount: Integer; { 读方法}

procedure SetCount(ACount: Integer); { 写方法}

pubilic

property Count: Integer read GetCount write SetCount;

end;

⑵ 内部数据存储

关于如何存储属性的数据值,Delphi没有特别的规定,通常Delphi部件遵循下列规定:

● 属性数据存储在对象的数据域处

● 属性对象域的标识符以F开头,例如定义在TControl中的属性FWidth

● 属性数据的对象域应声明在private部分

后代部件只应使用继承的属性自身,而不能直接访问内部的数据存储。

⑶ 直接访问

使属性数据可用的最简单的办法是直接访问。属性声明的read 和write部分描述了怎样不通过调用访问方法来给内部数据域赋值。但一般都用read进行直接访问,而用write进行方法访问,以改变部件的状态。

下面的部件声明演示了怎样在属性定义的read 和write部分都采用直接访问:

type

TYourComponent=class(TComponent)

private { 内部存储是私有}

FReadOnly: Boolean; { 声明保存属性值的域}

published { 使属性在设计时可用}

property ReadOnly: Boolean read FReadOnly write FReadOnly;

end;

⑷ 访问方法

属性的声明语法允许属性声明的read和write部分用访问方法取代对象私有数据域。不管属性是如何实现它的read 和write部分,方法实现应当是private,后代部件只能使用继承的属性访问。

① 读方法

属性的读方法是不带参数的函数,并且返回同属性相同类型的值。通常读函数的名字是“Get”后加属性名,例如,属性Count的读方法是GetCount。不带参数的唯一例外是数组属性。如果你不定义read方法,则属性是只写的。

② 写方法

属性的写方法总是只带一个参数的过程。参数可以是引用或值。通常过程名是"Set"加属性名。例如,属性Count的写方法名是SetCount。参数的值采用设置属性的新值,因此,写方法需要执行在内部存储数据中写的操作。

如果没有声明写方法,那么属性是只读的。

通常在设置新值前要检测新值是否与当前值不同。

下面是一个简单的整数属性Count的写方法:

procedure TMyComponent.SetCount( value: Integer);

begin

if value <>FCount then

begin

FCount := Value;

update;

end;

end;

⑸ 缺省属性值

当声明一个属性,能有选择地声明属性的缺省值。部件属性的缺省值是部件构造方法中的属性值集。例如,当从Component Palette选择某部件置于窗体中时,Delphi通过调用部件构造方法创建部件,并决定部件属性初始值。

Delphi使用声明缺省值决定是否将属性值存在DFM文件中。如果不描述缺省值,Delphi将总是保存该属性值。声明缺省值的方法是在属性声明后加default 指令,再跟缺省值。

当重声明一个属性时,能够描述没有缺省值的属性。如果继承的属性已有一个,则设立没有缺省值的属性的方法是在属性声明后加nodefault指令。如果是

第一次声明属性,则没有必要加nodefault指令,因为没有default指令即表示如此。

下例是名为IsTrue的布尔类型属性设置缺省值True的过程:

type

TSampleComponent=class(TComponent)

private

FIsaTrue: Boolean;

pubilic

constructor Create (AOwner: TComponent); Overvide;

published

property Istrue: Boolean read FIsTrue write FIsTrue default True; end;

constructor TSampleComponent.Create (AOwner: TComponent);

begin

inherited Create ( Aowner);

Fistvue := True; { 设置缺省值}

end;

5. 编写属性编辑器

Object Inspector提供所有类型属性的缺省编辑器,Delphi也支持通过编写和注册属性编辑器的方法为属性设计自己的编辑器。可以注册专门为自定义部件的属性设计的编辑器,也可设计用于所有某类型的属性。编写属性编辑器需要下列五个步骤:

● 继承一个属性编辑器对象

● 将属性作为文本编辑

● 将属性作为整体编辑

● 描述编辑器属性

● 注册属性编辑器

⑴ 继承属性编辑器对象

DsgnIntf库单元中定义了几种属性编辑器。它们都是从TPropertyEditor继承而来。当创建属性编辑器时,可以直接从TPropertyEditor中继承或从表中的任一属性编辑器中继承。

表19.4 属性编辑器的类型

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

类型编辑的属性

─────────────────────────────────────

TOrdinalProperty 所有有序的属性(整数、字符、枚举)

TIntegerProperty 所有整型,包括子界类型

TCharProperty 字符类型或字符子集

TEnumProperty 任何枚举类型

TFloatProperty 所有浮点数

TStringProperty 字符串,包括定长的字符串

TSetElementProperty 集合中的独立元素

TSetElementProperty 所有的集合,并不是直接编辑集合类型,而是展开成一列集合元素属性

TClassProperty 对象,显示对象名,并允许对象属性的展开TMethodPropevty 方法指针,主要指事件

TComponentProperty 相同窗体中的部件,用户不能编辑部件的属性,

但能指向兼容的部件

TColorProperty 部件颜色,显示颜色常量,否则显示十六进制数TFontNameProperty 字体名称

TFontProperty 字体,允许展开字体的属性或弹出字体对话框

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

下面是TFloatPropertyEditor的定义:

type

TFloatProperty=Class(TPropertyEditor)

public

function AllEqual: Boolean; override;

function GetValue: String; override;

procedure SetValue ( Const Value: string ); override;

end;

⑵ 象文本一样编辑属性

所有的属性都需要将它们的值在Object Inspector窗口中以文本的方式显示。属性编辑器对象提供了文本表现和实际值之间转换的虚方法。这些虚方法是GetValue和SetValue,你的属性编辑器也能继承了一系列的方法用于读和写不同类型的值。见下表:

表19.5 读写属性值的方法

━━━━━━━━━━━━━━━━━━━━━━━━━━

属性类型"Get"方法"Set"方法

──────────────────────────

浮点数GetFloatValue SetFloatVallue

方法指针GetMethodValue SetMehodValue

有序类型GetOrdValue SetOrdValue

字符串GetStrValue SetStrValue

━━━━━━━━━━━━━━━━━━━━━━━━━━

当覆盖GetValue方法时,调用一个"Get"方法;当覆盖SetValue方法时调用一个"Set"方法。

属性编辑器的GetValue方法返回一个字符串以表现当前属性值。缺省情况下GetValue返回"unknown"。

属性编辑器的SetValue接收Object Inspector窗口String类型的参数,并将其转换成合适的类型,并设置属性值。

下面是TIntegerProperty的GetValue和SetValue的例子:

function TIntegerProperty GetValue: string;

begin

Result := IntToStr (GetOrdValue);

end;

proceduve TIntegerPropertySetValue (Const Value: string);

var

L: Longint;

begin

L := StrToInt(Value); { 将字符串转换为数学}

with GetTypeData (GetPropType)^ do

if ( L < Minvalue ) or ( L > MaxValue ) then

Raise EPropertyError.Create (FmtloadStr(SOutOfRange,

[MinValue,MaxValue]));

SetOrdValue (L);

end;

⑶ 将属性作为一个整体来编辑

Delphi支持提供用户以对话框的方式可视化地编辑属性。这种情况常用于对对象类型属性的编辑。一个典型的例子是Font属性,用户可以找开Font对话框来选择字体的属性。

提供整体属性编辑对话框,要覆盖属性编辑对象的Edit方法。Edit方法也使用"Get"和"Set"方法。

在大多数部件中使用的Color属性将标准的Windows颜色对话框作为属性编辑器。下面是TColorProperty的Edit方法

procedure TColorProperty.Edit

var

ColorDialog: TColorDialog;

begin

ColorDialog := TColorDialog.Create(Application); { 创建编辑器}

try

ColorDialog.Color := GetOrdValue; { 使用已有的值}

if ColorDialog.Execute then

SetOrdValue (ColorDialog.Color);

finally

ColorDialog.Free;

end;

end;

⑷ 描述编辑器的属性

属性编辑必须告诉Object Inspector窗口如何采用合适的显示工具。例如Object Inspector窗口需要知道属性是否有子属性,或者是否能显示可能取值的列表。描述编辑器的属性通常覆盖属性编辑器的GetAttributes方法。GetAttributes返回TPropertyAttributes类型的集合。集合中包括表中任何或所有的值:

表19.6 属性编辑器特征标志

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

标志含义相关方法

──────────────────────────────paValuelist 编辑器能给予一组枚举值GetValues

paSubPropertie 属性有子属性GetPropertises

paDialog 编辑器能显示编辑对话框Edit

PaMultiSelect 当用户选择多于一个部件

时,属性应能显示N/A

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Color属性是灵活的,它允许在Object Inspector窗口中以多种方式选择他们。或者键入,或者从列表中选择定编辑器。因此TColorProperty的GetAttributes 方法在返回值中包含多种属性。

function TColorProperty.GetAttributes: TProrertyAttributes;

begin

Result := [PaMultiselect, paDialog, paValuelist];

end;

⑸ 注册属性编辑器

一旦创建属性编辑器,必须在Delphi中注册。注册属性编辑器时,要与某种属性相联。

调用RegisterPropertyEditor过程来注册属性编辑器。该过程接受四个参数:

● 要编辑的属性的类型信息的指针。这总是通过调用调用TypeInfo函数得到,如TypeInfo ( TMyComponent )

● 编辑器应用的部件类型,如果该参数为nil则编辑器应用于所给的类型的所有属性

● 属性名,该参数只有在前一参数描述了部件的情况下才可用

● 使用该属性编辑器的属性的类型

delphi制作多文档界面

最为一个巩固之前有关窗体和对象的有关知识,下面就建立一个简单的MDI示范程序,这个程序的功能是打开和保存图形文件(包括位图、图标等),为了完成这个任务,我们有一个大概的计划,计划内容如下: (1)建立主窗体(一个MDI父窗体),包括菜单。 (2)为【File | Open…】和【File | Save…】菜单选项编写代码。 (3)为Windows菜单上的Cascade、Tile和Arrange All选项编写代码。 (4)建立MDI子窗体。 (5)建立一个About对话框。 (6)然后再回忆和欣赏一下这段工作。 时间就是金钱,即刻就做吧。 一、创建主窗口窗体 首先创建一个主窗口窗体,一个MDI应用程序的主窗口的FormStyle属性必须设置为fsMDIForm。不但要为应用程序增加File Open和File Save 对话框,还要增加一个菜单。 1、启动Delphi,并从主菜单选择【File | New | Application】; 2、把主窗体的Name属性设置为MainForm; 3、把Caption属性设置为Picture Viewer; 4、把FormStyle属性设置为fsMDIForm; 好了,下面为此窗体增加一个菜单,利用Delphi特性,引进一个预定义菜单,具体如下:1、点击组件选项板的Standard标签,并点击MainMenu按钮;

2、把MainMenu组件点击放置到窗体上,具体放到哪个地方无所谓了,因为在运行阶段,代表菜单的图标只是占地方而不显示,这是非可视化组件。 3、把MainMenu组件Name属性改为MainMenu; 4、双击MainMenu组件,就会出现Menu Designer对话框; 5、在MainMenu上点击鼠标右键,选择“Insert From Template…”,将出现Insert Template对话框;

delphi制作登陆界面

///////////////////// (一)项目文件 test.dpr ////////////////////// program SerialGet; uses Forms, UMain in UMain.pas {frmMain}, ULogin in ULogin.pas {frmLogin}, UDataModule in UDataModule.pas {DataModule1: TDataModule}, {$R *.res} begin Application.Initialize; if CreateMutex then //创建句柄,判断此应用程序是否在运行 begin //调用全局函数,创建并显示登陆界面 if doLogin then //登陆成功 begin Application.CreateForm(TfrmMain, frmMain); //数据模块文件不须在这儿创建,因为 ULogin.pas 中已创建 //Application.CreateForm(TDataModule1, DataModule1); Application.Run; end else //登陆不成功 begin try DataModule1.free; Application.terminate; except end; end; end else begin DestroyMutex; //释放句柄 end; end. //////////////// (二)登陆窗体 ULogin.pas ULogin.dfm ////////////////// unit ULogin; interface uses ...... type ... ... ...

用delphi设计图书管理系统

《数据库技术与应用》 大作业 题目:数据库应用系统的设计和实现 适用专业: 指导老师: 班级: 姓名: 学号: 中南大学信息科学与工程学院 2010 年1月

图书是人类文明的见证,随着高科技的发展各式各样图书越来越多,图书馆和书店的管理也越来越复杂。如今图书管理系统是一 个书店或一个图书馆的必备系统。一个安全可靠并且对于用户比较实用的图书管理系统来说变得尤其重要。 本次设计设计了一个在DELPHI平台基于SQL Server 2000开发出的图书管理系统。在系统的设计上面实现了该系统的交互式界面。 从系统的需求分析、系统设计、系统实现入手,详细阐述了一个 C/S 结构的图书管理信息系统主要功能的实现过程。每一阶段均给 出了相应的理论依据和实现内容,并介绍了系统实现部分的主要算法。整个系统的设计与开发严格按照软件工程思想进行,从需求分析到系统设计和实现、从原型系统设计到迭代完善,本图书管理系统涵盖了六个主要的子系统:图书资料管理、读者资料管理、借书 操作、还书操作、删除、修改和查询处理,提高了工作的准确率和效率。 本图书管理信息系统是利用计算机管理信息处理的迅速、准确、可靠且具有强大存储能力的突出特点,全面提高图书馆的管理水平 和工作效率,并以及时、完整的业务经营资料,为图书馆的及时转换提供一定的支持。

关键词:数据库,SQL server2000,Delphi 7,图书管理系统 1.1 课题研究现状分析 在现金信息化发达的社会,图书的发行量与日俱增。因此需要对书籍资源、读者资源、借书信息、还书信息进行管理,及时了解各个环节中信息的变更,有利用管理效率的提高。传统的图书馆需要制作有署名与对应编号的书卡,由读者按分类查找再交由图书管理员来处理借书工作,还书也要人工翻阅大量的记录,这样使得工作量大并及其繁琐,效率变得低下。建立网上电子图书管理系统的目的是实现无纸化图书管理,减轻管理员的工作量,方便读者查阅所需的图书,还可以利用网络实现提醒读者还书的功能。管理员还可以对各种图书进行分析统计,对过时、损坏的图书进行删除。达到降低成本提高工作效率的目标。 1.1.1本领域内已开展的研究工作 1. 理论研究基础 (1)数据库设计方法的完整化、多样化,又有多学科的综合性。 (2)数据库设计步骤的规范化和细致化。 (3)数据库技术不断的更新,并不断增加新的技术,兼容性范围也逐渐扩大。2. 技术层面的支持 SQL Server的普遍应用,并得到的用户的支持,与Windows操作系统的完全兼容性也决定了它在今天仍然有着庞大的使用群体。SQL Server2000作为后台数据库与前台开发软件Visual Basic、C#、Visual C++、Delphi等都能够无缝连接。 1.1.2已经取得的研究成果 (1)开发出了一套系统的数据库理论,安全性、完整性、并发性、恢复性都有完整的概述。 (2)随着Internet的迅猛发展,数据库在各个领域作为后台存储得到了广泛的 支持。 (3)完善的数据库管理并与前台开发软件的结合使用开发了一系列优秀的图书管理系统,在商业、经济等方面得到了广泛的应用。

delphi可视化编程讲稿

第三章D e l p h i的窗体与组件 教学要求: 掌握窗体、编辑类组件、按钮类控件、列表类控件、分组类组件、时钟组件、菜单组件、工具栏组件和工具按钮、多选项卡的的属性、方法与事件,学会使用这些组件设计应用程序的界面。 掌握ShowMessage、ShowMessageFmt、MassageDlg、MassageDlgPos、InputBox、InputQuery对话框函数与对话框过程的特点,并能熟练应用。熟悉公共对话框控件组件的属性,方法、事件及应用。 掌握创建新窗体的两种不同的方法及其应用。 掌握windows的模式与非模式窗体的概念及应用方法。 掌握焦点的含义,与焦点相关的属性,应用焦点设计程序的方法。 了解CreateMessageDialog函数的定义与用法、speedbutton和文件有关的控件的属性、方法与事件。

从本章开始,将介绍Delphi 编程的一些基本方法。通过这一部分的学习,可以了解开发Windows 环境下应用程序的一些关键技术,并可以方便、快捷地开发一般的应用程序。 为了简化编程工作,Delphi 提供了许多功能强大的函数和类。其中很重要的一部分就是组件类。本章将重点介绍常见组件及其编程应用。 现在深入普及的Windows操作系统中,方便快捷的人机交互界面主要是通过窗体和对话框实现的。在Delphi中,这些窗体和对话框就是程序设计阶段的窗体,Delphi的可视化设计工作就是在窗体中进行的。 通常,窗体中会有文字输入、滚动条、复选框、单选框、按钮等一系列组件,通过这些直观易懂的组件,可以方便的实现多种多样的功能。在Delphi中,这些运行期间出现在窗体和对话框中的组件称为可视组件。在窗体中,还可以放置一些运行期间非可视的组件,对应其它的TComponent子类。这些不可视组件集中地实现了一些特殊的功能。比如,时钟控制等功能。 ●TComponent组件类,所有的组件都是由这个类派生来的。 ●TControl子类(可视组件)可分为两类:窗体组件和图 形组件。

delphi的精美界面设计

Delphi界面设计专辑 [前言:]界面的美观和用户亲和性是应用软件成功的首要条件,因此界面往往是程序员最费心的地方。在这个专辑中,将向读者全面介绍Delphi中界面设计的原则和技巧 窗体设计 制作固定大小的Form 固定的Form像一个对话框,何不试试下面的语句 巧用Delphi制作溅射屏幕 精心编写的WINDOWS程序显示启动注意事项,称之为溅射屏幕(splash screen)。利用一点儿小小的内容,即可给程序的显示添加不少色彩 LED数码管仿真显示程序 在电子设备上广泛地使用LED数码管显示数据,在许多应用软件中也经常模拟LED数码管显示数据,使程序画面看起来很有特色 菜单设计 DELPHI中自适应表单的实现 我们知道,屏幕分辨率的设置影响着表单布局,假设你的机器上屏幕分辨率是800*600,而最终要分发应用的机器分辨率为640*480,或1024*768,这样你原先设计的表单在新机器上势必会走样 作非常规程序菜单掌握delphi高级秘籍 大家可能见过诸如金山毒霸,瑞星杀毒,以及五笔输入法等等在系统托盘(即右下角有时间和输入法图标的地方)在的控制菜单,而在正常的任务栏(即屏幕最下方的“开始”按钮的右边的各式各样)中却不出现按钮的程序,即我们常说的在后台运行的程序 用Delphi制作动态菜单 所谓动态菜单是指菜单项随着程序的操作变化而变化。现在,我们用Delphi来实现这一功能,具体步骤如下 工具栏和状态条 为Windows窗口标题栏添加新按钮 对于我们熟悉的标准windows窗口来讲,标题栏上一般包含有3个按钮,即最大化按钮,最小化按钮和关闭按钮。你想不想在Windows的窗口标题栏上添加一个新的自定义按钮用Delphi4实现风Word97格的工具栏 用过Word97的人对它的工具栏印象很深刻,因为它的风格很“酷”,同样IE4.0的工具栏也有类似的风格,Win98的出现,使这种风格的工具栏得到了推广 如何隐藏和显示Windows的任务条 如果隐藏和显示Windows的任务条?仅仅调用以下的函数就可以. 其他技巧 Delphi利用Windows GDI实现文字倾斜 在Delphi开发环境中,文字的输出效果一般都是头上脚下的"正统"字符,如何输出带有一定倾斜角度的文字以达到特殊的显示效果呢 Delphi之三十六计之界面篇 设置状态栏面板对象的Style为OwnerDraw,并在状态栏对象的DrawPanel事件中书写以下代码 利用COM技术实现外壳扩展的属性页 当用户在资源管理器中调用右键菜单时,会显示一个"属性"菜单项,点击属性菜单项会显

Delphi用BusinessSkinForm 做界面皮肤的使用说明

Delphi用BusinessSkinForm 做界面皮肤的使用说明 注意:新版的Delphi 已经用bsCompressedStoredSkin 代替了bsStoredSkin 1、先放bsBusinessSkinForm、bsSkinData、bsStoredSkin(bsCompressedStoredSkin)各一个到窗体上 2、修改bsBusinessSkinForm的SkinData属性为bsSkinData1 3、修改bsSkinData1的StoredSkin属性为bsStoredSkin1 4、修改bsStoredSkin1的filename属性,指向一个皮肤文件,例如我的55套皮肤包是放在C:\Program Files\Borland\Delphi7\BSF-Skins\Skins文件夹里,我就修改 bsStoredSkin1的filename属性为C:\Program Files\Borland\Delphi7\BSF-Skins\Skins\Animate\skin.ini 5、在delphi设计窗口中按下F9 6、爽吧!!!!! 第一步-安装: 1、双击BSFD7.dpk文件,在delphi 7.0中打开 2、单击compile按钮,你会发现原来不可用的install按钮可以使用了 3、单击install按钮,会弹出来一个对话框提示你“安装成功!” 4、将所有源文件复制到C:\Program Files\Borland\Delphi7\Lib文件夹中(如delphi安装路径不同的话,请各位老兄自行更改) 第二步-最基本的使用方法: 当你安装成功后,你会在delphi的组件面板上发现三个控件组,它们是: businessskinform vcl和businessskinform db vcl和businessskinform vcl dialogs,顾名思义,第一个是常用组件,第二个是数据库组件,第三个是对话框组件。 按照下面的步骤,不用写一行代码,你可以马上做出一个有漂亮界面的程序来 1、先放bsBusinessSkinForm、bsSkinData、bsStoredSkin(在businessskinform vcl控件组中)各一个到窗体上 2、修改bsBusinessSkinForm的SkinData属性为bsSkinData1 3、修改bsSkinData1的StoredSkin属性为bsStoredSkin1

Delphi XE FireMonkey 自带Demo体验与效果图

Delphi XE FireMonkey Demo体验与效果图 版本:Delphi XE6 FireMonkey DEMO:delphi FireMonkey自带 DEMO路径,在DELPHI XE6安装目录下:E:\Documents and Settings\All Users\Documents\Embarcadero\Studio\14.0\Samples 1●TabSlideTransition(分页可滑动翻页) 功能:每页可填写,并支持可滑动翻页 路径:Samples\Object Pascal\Mobile Samples\User Interface\TabSlideTransition 开启界面:

2●TabletMasterDetailWithSearch(查找联系人,定位,并显示明细) 功能:可以查找列表联系人,并定位,和显示明细 路径:Samples\Object Pascal\Mobile Samples\User Interface\TabletMasterDetailWithSearch 开启界面:

3●Settings Project(系统设置) 功能:打开USB调试,WIFI等设置 路径:Samples\Object Pascal\Mobile Samples\User Interface\Settings Project 开启界面:

4●ScrollableForm(滚动编辑框) 功能:滚动编辑框 路径:Samples\Object Pascal\Mobile Samples\User Interface\ScrollableForm 开启界面:

相关主题
文本预览
相关文档 最新文档