欢迎来到图者知识网!

江苏省计算机二级讲义,计算机等级考试二级

教育考试 时间:2020-01-03

【www.tuzhexing.com--教育考试】

20.3.1.5 动态DFM文件应用揭秘

1. 动态DFM文件概述

动态DFM文件是相对于静态DFM文件而言。所谓静态DFM文件是指在Delphi开发环境中设计的窗体文件。窗体的设计过程就是程序的编制过程。因此,动态DFM文件就是指在程序运行过程生成或存取的DFM文件。

动态DFM文件的创建和使用分别如下两种情况:

● 在程序运行过程中,由Create方法动态生成窗体或部件,然后动态生成其它部件插入其中生成DFM文件

● 在Delphi开发环境中,设计生成DFM文件,然后用DFM 文件存取函数,或者用Stream对象和Filer对象的方法,将DFM文件读入内存,进行处理,最后又存入磁盘中

由Delphi的窗体设计的常规方法生成的DFM文件在程序运行一开始就规定了部件的结构。因为在窗体设计过程中,窗体中的每个部件都在程序的对象声明中定义了部件变量。这种固定的结构虽然能方便应用,但以牺牲灵活性为代价。

在Delphi应用程序中有时需要在运行过程中创建控制,然后将该控制插入另一个部件中。例如:

procedure TForm1.Button1Click(Sender: Tobject);

var

Ctrl: TControl

begin

Ctrl := TEdit.Create(Self);

Ctrl.Top := 100;

Ctrl.Left := 100;

Ctrl.Width := 150;

Ctrl.Height := 20;

InsertControl(Ctrl);

end;

动态插入控制的优点是可以在任何时刻、任意位置插入任意数量的任何类型的控制。因为应用程序需求在很多情况下是在程序运行中才知道的,所以动态插入控制就显得很重要。而且在很多情况下,需要保存这些界面元素,留待程序再次调用。例如应用程序界面的定制、系统状态的保存、对话框的保存等。这时生成动态DFM文件是最佳选择。

动态插入控制的不足之处是在插入控制前,无法直观地看到控制的大小、风格、位置等,也就是动态插入控制的过程是非可视化的。但可以借助于静态DFM文件的可视化设计。这就是生成和使用动态DFM文件的第二种方法。也就是在应用程序运行前,在Delphi开发环境中,使用可视化开发工具设计所需窗口或部件的样式,以DFM文件保存。然后在应用程序运行过程中,将DFM文件读入内存。Delphi的Stream对象和Filer对象在读取DFM文件时,会根据DFM文件的内容自动创建部件及其拥有的所有部件。

在使用动态DFM文件时有两点需要注意。

● 每一个动态插入的控制或部件必须在程序中调用RegisterClass进行注册

● 读入DFM文件自动创建部件后,如果调用了InsertControl方法, 则在关闭窗口时要调用RemoveControl方法移去该控制,否则会产生异常事件

2. 动态DFM文件应用之一:超媒体系统的卡片设计

Delphi多种类型的可视部件,如文本部件、编辑部件、图形图像部件、数据库部件、媒体媒放部件和OLE部件等,每一种部件在屏幕中占据一定的区域,具有相当丰富的表现能力,可以作为卡片中的一种媒体,因此可以利用这些可视部件进行超媒体系统的卡片设计。

超媒体卡片设计要求卡片中的媒体数目和媒体种类是不受限制的,而且必须能够修改和存取卡片,因此,采用动态DFM文件是比较合适的。而且如果利用Stream对象,将卡片存储在数据库BLOB字段中,就为把超文本与关系数据库技术结合起来创造了契机。

下面是超媒体卡片设计子系统中的部分源程序,它演示了如何创建对象、插入对象和存取动态DFM文件。

⑴ 在应用程序中注册对象

procedure TMainForm.FormCreate(Sender: TObject);

begin

RegisterClass(TLabel);

RegisterClass(TEdit);

RegisterClass(TMemo);

RegisterClass(TButton);

RegisterClass(TPanel);

RegisterClass(TPanelP);

RegisterClass(TBitBtn);

BR>
end;

⑵ 创建和插入对象

procedure TMDIChild.FormClick(Sender: TObject);

var

Ctrl : TControl;

Point: TPoint;

begin

GetCursorPos(Point);

Point := BackGround.ScreenToClient(Point);

case CurToolIndex of

1 : begin

Ctrl := TLabel.Create(self);

TLabel(Ctrl).AutoSize := False;

TLabel(ctrl).Caption := "Label"+S;

TLabel(ctrl).Name := "Label 1";

TLabel(ctrl).Top := Point.Y;

TLabel(ctrl).Left := Point.X;

TLabel(Ctrl).Height := Round(100*Res/1000/Ratio);

TLabel(Ctrl).Width := Round(600*Res/1000/Ratio);

TLabel(Ctrl).Color := clWhite;

TLabel(Ctrl).Font.Color := clBlack;

TLabel(Ctrl).Font.Name := "Roman";

TLabel(Ctrl).Font.Height := -TLabel(Ctrl).Height;

TLabel(Ctrl).Font.Pitch := fpFixed;

TLabel(Ctrl).Enabled := False;

TLabel(Ctrl).OnClick := LabelClick;

TLabel(Ctrl).OnMouseMove := ReportPos;

BackGround.InsertControl(Ctrl);

CurTool.Down := False;

CurTool := nil;



end;

2: begin

Ctrl := TEdit.Create(self);

TEdit(ctrl).AutoSize := True;

TEdit(ctrl).Top := Point.Y;

TEdit(ctrl).Left := Point.X;

TEdit(Ctrl).Height := 20;

BackGround.InsertControl(Ctrl);



end;

3:



end;

end;

⑵ 存取动态DFM文件

procedure TMainForm.FileOpen(Sender: TObject);

begin

if OpenDialog.Execute then

begin

DesignWin := TMDIChild.Create(Application);

ReadComponentResFile(OpenDialog.FileName, DesignWin);

DesignWin.Init;

FileName := OpenDialog.FileName;

DesignWin.Caption := FFileName;

end;

end;

DesignWin是在TMainForm中定义的TMDIChild类型的窗体部件,是卡片设计平台;FFileName是私有变量,用来保存当前编辑的卡片文件名。DesignWin的Init方法实现如下:

procedure TMDIChild.Init;

var

I: Integer;

Ctrl: TControl;

begin

BackGround.BringToFront;

with B ackGround do

for I:= 0 to ControlCount - 1 do

if Controls[I].Name <> ""then

ObjectIns.ObjectList.Items.AddObject(Controls[I].Name, Controls[I]);

end;

BackGround是TPanel类型的部件,所有的动态创建对象都插入到BackGround中,所以,后面调用BackGround.InsertControl(Ctrl);ObjectIns是个仿Delphi 的媒体属性编辑器。

动态DFM文件的存储过程是这样的:

procedure TMainForm.FileSave(Sender: TObject);

begin

if DesignWin.CurControl <> nil then

DesignWin.CurControl.Enabled := True;

WriteComponentResFile(FFilename, DesignWin);

DesignWin.Caption := FileName;

end;

end;

因为在DesignWin的Init方法中调用了InsertControl方法,所以在关闭DesignWin窗口时要相应地调用RemoveControl,否则在关闭DesignWin窗口时会产生内存错误。

procedure TMDIChild.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

var

I: Integer;

Ctrl: TControl;

Removed: Boolean;

begin

if Modified = True then

if MessageDlg("Close the form?", mtConfirmation,

[mbOk, mbCancel], 0) = mrCancel then

CanClose := False;

if CanClose = True then

begin

repeat

removed := False;

I := 0;

repeat

if BackGround.Controls[I].Name <> "" then

begin

BackGround.RemoveControl(BackGround.Controls[I]);

Removed := True;

end;

I := I + 1

until (I >= BackGround.ControlCount) or (Removed = True);

until (Removed = False);

SendMessage(ObjectIns.Handle, WM_MDICHILDCLOSED, 0, 0);

end;

end;

本文来源:http://www.tuzhexing.com/jiaoyu/998043/

推荐内容