程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 第二十章-開發Delphi對象式數據管理功能(五)(3)

第二十章-開發Delphi對象式數據管理功能(五)(3)

編輯:Delphi

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);

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 BackGround 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;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved