您的位置:首页 > 编程语言 > Delphi

编写界面可扩充的Delphi程序

2006-10-12 21:38 288 查看

编写界面可扩充的Delphi程序

(深圳职业技术学院计算机系  李俊平,广东 深圳 518055)

摘要:本文阐述Delphi程序界面编程的一般性方法。利用Delphi组件的继承关系,使得界面上具有相似功能的同一种组件增加时,不需要改变功能代码,力图做到用户界面与代码的分离,使代码达到最大限度的重用。

关键词:组件 继承 类 TComponent TControl

1 引言

  Delphi中的类都是从TObject这个根类继承而来的,其中所有的组件都是从TComponent继承(所谓组件,就是Delphi IDE中组件板上的那些类),而组件又分为可视的和非可视的两种。所有的可视化组件都是从TControl类继承下来的,所以可视化的组件也称为控件。窗体上所有的组件构成一个组件数组,所有的控件也构成一个控件数组。窗体可以很方便地统计它们的数目,也可以通过循环遍历每一个组件或控件。本文将利用Delphi的这个特性,探讨几种常用组件的可扩充的编程方法。

2 复选框问题的一般方法

  复选框的选中与否一般是逐个判断窗体上的每一个复选框的Checked属性,需要使用一连串的判断语句,在复选框较多时非常繁琐,而且每增加一个复选框都必须在代码中增加一个判断,界面和代码是高度耦合的。利用TControl类的一些特性可以解决这个问题,下面是一个例子。

  图1中的窗体上有若干代表个人爱好选择的复选框,有一个按钮其Click事件代码将选中的爱好排列在列表框中。利用TCheckBox祖先类TControl的某些特性,可以做到界面与代码的分离,即在窗体上增加复选框的数量,按钮的事件代码无须任何修改。

procedure TForm1.Button1Click(Sender: TObject);

var

i:integer;

begin

ListBox1.Items.Clear;

for i:=1 to ControlCount-1 do

begin

if Controls[i] is TCheckBox then

begin

if TCheckBox(Controls[i]).Checked then

ListBox1.Items.Add(TCheckBox(Controls[i]).Caption);

end;

end;

end;

 

            图1 复选框问题

  从以上的例子可以看出,Delphi所基于的Object Pascal语言在面向对象的编程方面所表现出来的类型特征是非常灵活而强大的。

3 文本框事件的一般方法

  我们经常在使用软件的过程中发现有些软件的输入窗体上的文本框有这样一个特性,就是当鼠标移到输入文本框时该输入框得到焦点且选定文本框原有文本,使得用户可以立即输入数据。通常的做法是对每个输入文本框的MouseMove事件编程,例如:

  procedure TForm1.Edit1MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);

begin

Edit1.SetFocus;

Edit1.SelectAll;

end;

如果窗体上有10个这样的输入框,就得编写10个类似的事件代码。而且以后每次增加新的输入框就需要增加新的事件代码。

这里探讨的方法也是基于界面和功能代码分离的原则,我们利用所有组件的祖先类TComponent的特性。首先编写通用的过程代码,功能是使输入框得到焦点并选定文本:

procedure TForm1.EditMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);

begin

EditEnter(Sender);

end;

procedure TForm1.EditEnter(Sender:TObject);

begin

(Sender as TEdit).SetFocus;

(Sender as TEdit).SelectAll;

end;

然后在窗体的FormCreate事件中将每个输入框的MouseMove事件指向通用的过程代码,注意通用过程的参数必须和事件过程一致:

procedure TForm1.FormCreate(Sender: TObject);

var

i:integer;

begin

for i:=0 to ComponentCount-1 do

begin

if Components[i] is TEdit then

(Components[i] as TEdit).OnMouseMove:=EditMouseMove;

end;

end;

这样每次增加新的输入框时就不必修改任何代码,而且新增加的输入框也具备所需的功能特征。

4 文本框输入焦点问题的一般方法

  一个经常讨论的问题是,窗体上有很多的输入框,如何能在一个输入框输入完毕后按回车键使得下一个输入框得到焦点。通常为每一个输入框的KeyPress事件编写代码,例如:

  procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);

begin

if key=#13 then

Edit2.SetFocus;

end;

和上一个问题一样,我们需要编写若干个相似的代码,而且扩充时还需要为新增的输入框添加获得焦点的代码。

本文的做法和上一个问题类似,首先编写通用的过程代码,然后在FormCreate事件中将每一个输入框的KeyPress事件指向通用过程:

procedure TForm1.FormCreate(Sender: TObject);

var

i:integer;

begin

for i:=0 to ComponentCount-1 do

if Components[i] is TEdit then

(Components[i] as TEdit).OnKeyPress:=EditKeyPress;

end;

procedure TForm1.EditKeyPress(Sender: TObject; var Key: Char);

var

Index:integer;

begin

if key=#13 then

begin

if ActiveControl.ComponentIndex < ComponentCount-1 then

Index:=ActiveControl.ComponentIndex+1

else

Index:=ComponentCount-1;

while (not (Components[Index] is TEdit)) and (Index < ComponentCount) do

begin

Index:=Index+1;

end;

(Components[Index] as TEdit).SetFocus;

(Components[Index] as TEdit).SelectAll;

end;

end;

这里我们利用了窗体的ActiveControl属性,它代表当前获得焦点的输入文本框;ComponentIndex属性代表了窗体控件放置的次序,也作为本方法中输入框获得焦点的顺序的参考。这个例子所使用方法的难点在于窗体上可以获得焦点的控件也许不止文本框,还有按钮、列表框、复选框等等,如何区分它们需要用到Delphi的运行时信息(RTTI)。另外,该方法有一个局限就是获得焦点的顺序和设计时控件放置的顺序相关。

结语

  以上几种方法的原则都是尽力做到界面的扩充和代码无关,使得界面和功能的偶合程度降低,这样程序的可扩充性和可维护性都得到极大地提高。我们从上述的代码中可以看出运行时信息(RTTI)在面向对象的程序设计中的重要作用,正确运用这种技术可以让我们的软件高效、可扩充和易维护。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: