在Delphi中巧改窗体文件实现控件数组

 delphi 开发的应用中,每一个窗体都有一个对应的窗体文件(.dfm),用来记录该窗体的属性以及窗体上所有控件的属性,以便在窗体关闭后能准确地重新生成窗体。几乎所有的DELPHI参考书都没有提到过该文件的具体情况,偶尔提到,也都泛泛而谈,因为窗体文件是二进制文件,只有在DELPHI提供的编辑环境中才能看到它的本来面目,对其进行操作可能会出现不可预知的错误;而且在大多数情况下,确实没有修改的必要。而本文谈到的和窗体文件密切相关。
  要利用窗体文件,首先必须了解该类型文件的结构。窗体文件的结构很简单,朋友们可以生成一个窗体,随便放上一些控件,存盘后打开Unit1.dfm文件,就可以看到窗体文件是由关键字"object"和"end"构成的代码段,基本结构如下:
object 控件名:类名
属性1 =属性值
属性2 =属性值
 … 
end
  并且支持嵌套。Delphi在记录控件属性时,只记录修改过的属性,举一个例子,比如对一个标签控件(label1)的缺省描述如下:
object Label1: TLabel
Left = 256 
Top = 80 
Width = 32 
Height = 13 
Caption = Label1 
End
  记录的五个属性都是随开发者拖放的位置和顺序不同而变化的,其它属性由于没有修改过,都是缺省值,所以不必记录。
  窗体文件是有序的,它的有序性表现如下:

object 窗体名:Tform 
窗体属性1=属性值 
窗体属性2=属性值
 。。。 。。。 

// 以下是TgraphControl类型的控件

object 控件名:类名 控件属性1=属性值 控件属性2=属性值 。。。 。。。 end 
object 控件名:类名 控件属性1=属性值 控件属性2=属性值 。。。 。。。 end 
。。。 。。。 

// 以下是TwinControl类型的控件

object控件名:类名
控件属性1=属性值
控件属性2=属性值
。。。。。。
end
object控件名:类名
控件属性1=属性值
控件属性2=属性值
。。。。。。
end

// 以下是其它类型的控件

object控件名:类名
控件属性1=属性值
控件属性2=属性值
。。。。。。
end

  在同一种类型的控件中,各控件排列的先后顺序和它被拖放到窗体上的先后顺序相同。这个顺序是可以人为修改的,我们正是通过修改这个顺序,来实现控件的数组化。下面将详细介绍。

  熟悉VB的朋友肯定知道在VB中可以通过控件拷贝实现控件的数组化。而DELPHI中则没有这种功能。Delphi中可以使用Components, Controls两个控件数组在一定程度上模拟控件的数组化,比如:

for I := 1 to ControlCount-1 do
  if (Controls[I] is Tlabel) then 
    (Controls[I] as Tlabel).Caption := Test;
  这段代码的功能是将窗体上所有Label的Caption属性设为Test;这是一种非常有用的方法,大家如果不太熟悉可以参考delphi帮助作进一步了解。这种方法有很多局限,最明显的是我们并不知道Controls[i]或Components[i]到底代表哪一个控件,只能用遍历的方法进行筛选,这不仅影响了程序执行的效率,也带来编程上的繁琐。
  其实,Controls和Components中控件的排列顺序和对应的窗体文件(.dfm)中控件描述代码段的排列顺序是相同的。前面我们谈到窗体文件是可以进行适当修改的,也就是说,我们可以根据需要调整窗体文件中控件描述代码段的排列顺序,让Controls和Components这两个控件数组全在掌握之中,这样我们就能清楚知道Controls[I]或Components[I]具体代表的是哪一个控件。下面举例说明。
  比如,我们想让窗体Form1上的所有Tbutton灰化,最简单的方法是一句一句的编写代码:
Button1.Enabled := False; Button2.Enabled := False; … …
  如果Tbutton数量很多,代码就变得很冗长。于是我们采用一个循环来实现:
for I := 0 to ControlCount -1 do if Controls[I] is Tbutton Then   (Controls[I] as Tbutton).Enabled := False;
  现在我们有了更有效的方法,首先打开窗体文件(Form1.dfm),调整Tbutton的排列顺序,让所有Tbutton的代码段(Object…end)都排在一起,然后数一下前面其它控件代码段的个数,设为n,n-1就是第一个Button在Controls(Components)数组中的位置,这样程序就很简单:
for I:= n-1 to n-1+ButtonNum do
  (Controls[I] as Tbutton).Enabled := False;
  代码的效率和简洁比以前有了很大提高。其中ButtonNum是Button的个数。
  下一个例子更能体现利用这一规律的优越性。在编写Socket通信程序的时候,我们通常需要将用户输入的信息按照一定的顺序形成字符串,然后发送给服务器,服务器再根据事先约定的顺序解包,提取出内容,进行入库或其它操作。在形成字符串时,一般都是直接写代码,比如:

InfoS := ;//用于存放字符串。
if Edit1.Text $#@60; $#@62; then
  InfoS := InfoS + Edit1.Text;
else 
  begin
    Application.Message(请填写必要信息); 
    Exit;
  end;
if Edit2.Text $#@60; $#@62; then
  InfoS := InfoS + Edit2.Text;
else 
  begin 
    Application.Message(请填写必要信息);
 Exit;
end; 

  如果录入的项目多,这种方法会使代码冗长不堪。现在我们可以先调整窗体文件中Edit框描述代码段的顺序,让它们排列在一起,并确定第一个Edit框在Controls控件数组中的位置(方法入前),设为n-1(其中n表示排在Edit框前面的控件的描述代码段个数),编写如下代码实现:

for I := n-1 to n-1+EditNum do 
  if ((Controls[I] as TEdit).Text $#@60; $#@62; ) then
    InfoS := InfoS + (Controls[I] as Tedit).Text;
  else
  begin       
    Application.Message(请填写必要信息);
    Exit;
  end; 
//其中EditNum表示Edit框的个数。

  还有其它很多方面的应用,在这里就不一一赘述了。这实际上就是彻底实现了控件的数组化,而且这个数组还可以包含不同类型的控件。
  这里有两个问题需要注意:一是在调整控件描述代码段顺序时,一定要遵照文中提到的窗体文件的有序性规则,比如试图将一个TButton控件的描述代码放在一个TLabel控件的描述代码前面是不可能的;另外请大家注意Controls和Components的区别,窗体文件中,控件间的父子关系可以通过缩进的格式很明显的看出来,在计算控件在数组中的位置时,一定要考虑控件间的层次关系,如果使用Controls,就应该只对同级控件进行计数,如果是Components,则应包括所有的控件。

  当然,这种方法也有它的弊端,首先需要调整窗体文件顺序,其次程序的可读性会受到影响,所以大家在使用这种方法时应多写帮助。


unit Unit1;


interface


uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;


type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button2: TButton;
    Button1: TButton;
    Scrollbox1: TScrollBox;
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


var
  Form1: TForm1;


implementation


{$R *.dfm}


procedure TForm1.Button2Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to Panel1.ControlCount - 1 do
  begin


  end;
end;


procedure TForm1.FormCreate(Sender: TObject);
var
I:integer;
temp:TEdit;
begin
for I:=0 to 2 do
begin
temp:=TEdit.Create(ScrollBox1);
temp.Parent:=ScrollBox1;
temp.Top:=temp.Height*i*2+50;
temp.Text:='can be clear?'
end;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
I:integer;
begin
for I:= 0 to ScrollBox1.ControlCount-1 do
begin
if ScrollBox1.Controls[i] is TEdit then
TEdit(ScrollBox1.Controls[i]).Clear;
end;
end;


end.

for i:=0 to Controlcount-1 do
begin
  if Controls[i].ClassName='TEdit' then
    (Controls[i] as TEdit).Text:=inttostr(i);
end;

News 26.03.2015 Knowledge base file for Delphi XE3 freely available. 23.03.2015 Knowledge base file for Delphi XE and Delphi XE2 freely available. 16.03.2015 Latest version is available for download. What is IDR? IDR (Interactive Delphi Reconstructor) – a decompiler of executable files (EXE) and dynamic libraries (DLL), written in Delphi and executed in Windows32 environment. The program firstly is intended for the companies, engaged by development of anti-virus software. It can also help programmers to recover lost source code of programs appreciably. The current version of the program can process files (GUI and console applications), compiled by Delphi compilers of versions Delphi2 – Delphi XE3. Final project goal is development of the program capable to restore the most part of initial Delphi source codes from the compiled file but IDR, as well as others Delphi decompilers, cannot do it yet. Nevertheless, IDR is in a status considerably to facilitate such process. In comparison with other well known Delphi decompilers the result of IDR analysis has the greatest completeness and reliability. Moreover interactivity does work with the program comfortable and (we shall not be afraid of this word) pleasant. IDR make static analysis (analyzed file is not loaded to memory and executed) that allows to safely investigate viruses, trojans and other malware applications, those which executing is dangerous or is not desirable. The program does not require any installation activity and does not do any records in Windows registry. Below screenshot of IDR main window is shown. You can find examples of IDR working results on separate page. For detailed acquaintance with opportunities IDR there is a help file in format CHM which can be downloaded on page of download or directly from this link.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值