知识大全 通过实例看VCL组件开发全过程(一)
Posted 知
篇首语:一箫一剑平生意,负尽狂名十五年。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 通过实例看VCL组件开发全过程(一)相关的知识,希望对你有一定的参考价值。
通过实例看VCL组件开发全过程(一) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
这篇文章算是对我前段时间学习的一个学习总结 以及对自己学习过程的一个回顾 本文通过一个简单的例子来尽可能的展示VCL组件开发的各个方面 本文针对即将学习组件开发的初学者 如果你已经熟悉组件开发或认为本文内容过于基础简单 那么本文对你毫无用处 阅读本文 假设你已经熟悉delphi的普通程序设计以及vcl的结构层次 还有一些重要的关键字 published property等 (注 本文内容建立在delphi 及以上版本)在这篇文章中我们将建立一个和时间有关的组件 这个组件通过设置它的不同状态有以下基本功能 显示系统的当前时间(包括设置闹钟) 跑表 倒计时 这是一个简单的例子 然而我们将在这个例子中尽可能多的用到delphi在组件开发中的多种特性 你可以通过以下列举出的本文涉及特性有选择的阅读
·组件和组件包
·组件的属性类别
·组件的属性编辑器
·组件编辑器
一 组件和组件包 以及一些你应该知道的文件类型
组件和组件包的关系就如同普通工程中unit和工程文件的关系一样 通常你所安装的组件都是以组件包的形式发布的 一个组件包中可以有很多个组件 在组件开发中 组件包就是项目的工程文件 为了开始开发我们的组件(我们把他叫做TClock)并将它包括在我们自己的组件包(ClockPackage)中 我们选择Fileànewàother在弹出的窗口中的New页选择Package新建一个组件包 得到一个组件包窗口 查看这个组件包的原文件( dpk) 得到以下代码
package ClockPackage;
$R * res
$ALIGN
$ASSERTIONS ON
……
……
$DESCRIPTION Our Clock Pack
$IMPLICITBUILD OFF
requires
rtl;
end
这个文件其实就是组件开发中的工程文件 requires关键字指示了组件包所需组件包的列表 随着向组件包中加入组件(类似于单元文件) 你还会看到contains关键字 指示了组件包所包含的组件 你可以通过组件包窗口中的add和remove按纽来添加新的组件和删除已有的组件 另外这个代码中所包含的大量的编译器开关大多都可以在组件包窗体上的Options中设置 这里需要补充说明的是组件包的 种重要属性(都在Options中) Designtime Only Runtime Only Designtime and runtime(这 个词的意思有英语基础的朋友应该都知道吧) 对于大多数的组件包我们只要选择最后一个就可以了 然而有些组件包设计为只运行时(这样你用这套组件开发的程序不能脱离组件而单独运行 组件包也不能被安装) 有些组件包被设计为只设计时(这将在后文有更详细的说明)
了解了组件和组件包 我们对组件开发中可能出现的一些你没有见过的文件做一些说明 dpk文件既组件包的原代码 bpl文件 组件包编译后的结果 在没有发布dpk的情况下可以通过bpl来安装组件包到delphi(ProjectàOptionsàPackagesàadd) pas在这里就是组件包中组件的原代码了 dcu为pas编译后的结果 在你选择将组件包含进组件包时(contains关键字) 你可以选择发布原代码或是不发布(dcu文件) dcp如果你将组件作为运行时组件 连接器将使用该文件
二 开始开发组件
了解了上面的知识后 我们就可以开始开发组件了!在组件窗体中单击add 选择NewComponent页 在第一个组合框中选择我们的组件将要继承自哪个类(通常新的组件是通过继承已有的组件来开发的) 由于这个组件的主要作用是要显示时间 跑表 倒计时种的文字信息 所以我们选择继承自TCustomLabel(由于我们并不需要Tlabel的全部功能 我们选择了能够隐藏Tlabel属性并有选择的发布它的属性的TcustomLabel类) 接下来为我们的新组件取一个名字Tclock 然后指定我们想把组件安装到哪一个页中 这里我们自己键入一个ClockAndTime页 这将出现在RegisterComponents过程中(后面会详细说明) 选择好文件保存的路径后(最好把它和组件dpk包放在同一目录)确认 这是组件包窗体中的contains下已经多了我们刚才建立的组件的文件 双击它开始编写代码
在代码中我们需要注意在interface部分的一个新的过程 procedure Register;(注意 delphi规定Register的R必须大写 这是一个保留字) 这个过程是作为每一个组件所必须有的 它完成组件的注册 包括组件本身以及如属性编辑器等多种组件特性的注册)
procedure Register;
begin
RegisterComponents( ClockAndTime [TClock]);
//这个过程注册组件本身 注意到前面定义的ClockAndTime页了吗?
//这里在后面还会出现一些新的过程 包括注册组件的属性类别等等
end;
组件的代码由于假设你已经熟悉delphi开发(它和一般开发没什么不同) 我们就直接贴出来并加上适当的注释
unit Clock;
interface
uses
SysUtils Classes Controls StdCtrls ExtCtrls;
type
TState=(StClock StRunClock StBackClock);//定义枚举类表示控件的 种状态 时钟 跑表 倒计时钟
TClock = class(TCustomLabel)
private
fState:TState;
fTimer:TTimer;//为什么使用这个组件作为我们组件的私有成员就不用说了吧
RCD:array[ ] of integer;//跑表中的各个数位
fBeginTime:string;//到计时时的开始时钟 之所以没用TTime类型是为了在后面演示属性编辑器
fWakeTime:string;//闹钟时间 出于和上面同样的理由
fAllowWake:boolean;//是否开启闹钟功能
fOnWakeUp:TNotifyEvent;//为了使组件更加完美 我们允许组件用户能够响应闹钟到来时的时件
fOnTimeUp:TNotifyEvent;//同上能够响应倒计时种完成时的事件 我们将发布这两个事件
function GetActive:boolean;//控制Timer是否工作以控制 种状态的钟是否工作
procedure SetActive(Value:boolean);
procedure SetState(Value:TState);
procedure SetBeginTime(Value:string);
procedure SetWakeTime(Value:string);
protected
procedure WalkClock(sender:TObject);//作为时钟时走种的事件
procedure RunClock(sender:TObject); //跑表
procedure BackClock(sender:TObject);//倒计时
public
constructor Create(AOwner:TComponent);override;//完成一些初始化工作
procedure ReSetRunClock; //跑表和倒计时都需要一个复位方法给组件使用者调用
procedure ReSetBackClock;
published
property State:TState read fState write SetState default StClock;//默认为时钟状态
property Active:boolean read GetActive write SetActive;//控制 种状态的钟是否工作
property BeginTime:string read fBeginTime write SetBeginTime;
property WakeTime:string read fWakeTime write SetWakeTime;
property AllowWake:boolean read fAllowWake write fAllowWake;
property OnWakeUp:TNotifyEvent read fOnWakeUp write fOnWakeUp;
property OnTimeUp:TNotifyEvent read fOnTimeUp write fOnTimeUp;
//最后我们再发布一些被TCustomLabel所隐藏而我们又需要的属性
property Align;
property Alignment;
property Color;
property Font;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Visible;
property Transparent;
property OnClick;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents( ClockAndTime [TClock]);
end;
TClock
constructor TClock Create(AOwner: TComponent);
begin
inherited Create(AOwner);
//设置默认值
fTimer:=TTimer Create(self);
//将它属于我们的组件 这样便不用编写析构函数 而可以自动在释放本组件时释放Timer
Active:=false;
AllowWake:=false;
State:=StClock;
BeginTime:= : : ;
WakeTime:= : : ;
end;
function TClock GetActive: boolean;
begin
result:=fTimer Enabled;
end;
procedure TClock SetActive(Value: boolean);
begin
fTimer Enabled:=Value;
end;
procedure TClock SetState(Value: TState);
var
i:integer;
begin
case Value of
StClock:
begin
Active:=false;
fTimer Interval:= ;
fTimer OnTimer:=WalkClock;
Active:=true;
end;
StRunClock://由于Time类型不好处理微秒操作 我们只有手工模仿这个操作 代码会稍微烦琐
begin
Active:=false;
for i:= to do RCD[i]:= ;
Caption:=IntToStr(RCD[ ])+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ])+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ]);
Caption:=Caption+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ])+IntToStr(RCD[ ]);
fTimer Interval:= ;
//经过测试 这个秒表的效果很好 然而这只是一个技术上的演示
//实际上这么频繁( / 秒)的不断执行RunClock会使CPU的占用一直达到 %
//这并不是一个好注意 事实上要想在跑表中显示微秒级别并做到合理的占用CPU
//这需要更加灵活和复杂的编程
fTimer OnTimer:=RunClock;
end;
StBackClock:
begin
Active:=false;
Caption:=BeginTime;
fTimer Interval:= ;
fTimer OnTimer:=BackClock;
end;
end;
fState:=Value;
end;
procedure TClock SetBeginTime(Value: string);
begin
try
StrToTime(Value);
fBeginTime:=Value;
if State=StBackClock then
begin
Active:=false;
Caption:=Value;
end;
except
on Exception do
begin
fBeginTime:= : : ;
if State=StBackClock then Caption:= : : ;
end;
end;
end;
procedure TClock SetWakeTime(Value: string);
begin
try
StrToTime(Value);
fWakeTime:=Value;
except
on Exception do
begin
fWakeTime:= : : ;
end;
end;
end;
procedure TClock WalkClock(sender: TObject);
begin
Caption:=TimeToStr(Time);
if AllowWake and (StrToTime(Caption)=StrToTime(WakeTime)) then
begin
Beep;//蜂鸣器
if Assigned(fOnWakeUp) then
fOnWakeUp(self);
end;
end;
procedure TClock RunClock(sender: TObject);
begin
RCD[ ]:=RCD[ ]+ ;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then begin RCD[ ]:=RCD[ ]+ ;RCD[ ]:= ; end;
if RCD[ ]= then RCD[ ]:= ; //我们的跑表最多可计 个小时;
Caption:=IntToStr(RCD[ ])+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ])+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ]);
Caption:=Caption+IntToStr(RCD[ ])+ : +IntToStr(RCD[ ])+IntToStr(RCD[ ]);
end;
procedure TClock BackClock(sender: TObject);//可以在一天之类的时间倒计时
begin
if StrToTime(Caption)<>StrToTime( : : ) then
Caption:=TimeToStr(StrToTime(Caption) )
else
begin
Active:=false;
Beep;
if Assigned(fOnTimeUp) then
fOnTimeUp(self);
end;
end;
procedure TClock ReSetBackClock;
var
i:integer;
begin
if State=StRunClock then
begin
Active:=false;
for i:= to do RCD[i]:= ;
Caption:= : : : ;
end;
end;
procedure TClock ReSetRunClock;
begin
if State=StBackClock then
begin
Active:=false;Caption:=BeginTime;
end;
end;
end 为了测试我们的组件 现在你就可以安装这个组件包并建立一个应用测试它了 点击组件包窗体中的install即可(注意 一但你安装了组件包 当你想对组件修改时 在修改了原代码以后只用点击组件窗体的pile就可以了更新组件了) 这时delphi的组件页的最后多出了我们定义的页 其中有了我们的组件!
cha138/Article/program/Delphi/201311/24840相关参考
通过实例看VCL组件开发全过程 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 在这篇文章中我们将
通过实例看VCL组件开发全过程(二) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &n
怎样在Java实例开发的过程中使用进度条 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 在读取大
基于Delphi的组件设计之简单实例 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!这是一个可以计数
Extjs单独定义各组件的实例代码 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 网上看到的一个
dotnet下开发COM+组件 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 一问题的提出 最
在你的struts配置文件strutsconfigxml中加入下面的配置 <plugin
新建类库MyTestDLL 右击项目“MyTestDLL”》属性》生成》勾选“为互操作注册” 打开 AssemblyInfocs&nb
在laszlo应用开发过程中大部分编码过程集中在对系统组件的熟练应用比如取值传值刷新组件状态等等但是很多情况下尤其是项目的初始编码阶段需要定义一些满足项目特定要求的界面组件这就需要自定义组件了&n
VB.NET中的组件开发 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!简介组件其实是一段可以重用的