首頁 考試吧論壇 Exam8視線 考試商城 網絡課程 模擬考試 考友錄 實用文檔 求職招聘 論文下載 | ||
![]() |
2011中考 | 2011高考 | 2012考研 | 考研培訓 | 在職研 | 自學考試 | 成人高考 | 法律碩士 | MBA考試 MPA考試 | 中科院 |
|
![]() |
四六級 | 職稱英語 | 商務英語 | 公共英語 | 托福 | 雅思 | 專四專八 | 口譯筆譯 | 博思 | GRE GMAT 新概念英語 | 成人英語三級 | 申碩英語 | 攻碩英語 | 職稱日語 | 日語學習 | 法語 | 德語 | 韓語 |
|
![]() |
計算機等級考試 | 軟件水平考試 | 職稱計算機 | 微軟認證 | 思科認證 | Oracle認證 | Linux認證 華為認證 | Java認證 |
|
![]() |
公務員 | 報關員 | 銀行從業資格 | 證券從業資格 | 期貨從業資格 | 司法考試 | 法律顧問 | 導游資格 報檢員 | 教師資格 | 社會工作者 | 外銷員 | 國際商務師 | 跟單員 | 單證員 | 物流師 | 價格鑒證師 人力資源 | 管理咨詢師考試 | 秘書資格 | 心理咨詢師考試 | 出版專業資格 | 廣告師職業水平 駕駛員 | 網絡編輯 |
|
![]() |
衛生資格 | 執業醫師 | 執業藥師 | 執業護士 | |
![]() |
會計從業資格考試(會計證) | 經濟師 | 會計職稱 | 注冊會計師 | 審計師 | 注冊稅務師 注冊資產評估師 | 高級會計師 | ACCA | 統計師 | 精算師 | 理財規劃師 | 國際內審師 |
|
![]() |
一級建造師 | 二級建造師 | 造價工程師 | 造價員 | 咨詢工程師 | 監理工程師 | 安全工程師 質量工程師 | 物業管理師 | 招標師 | 結構工程師 | 建筑師 | 房地產估價師 | 土地估價師 | 巖土師 設備監理師 | 房地產經紀人 | 投資項目管理師 | 土地登記代理人 | 環境影響評價師 | 環保工程師 城市規劃師 | 公路監理師 | 公路造價師 | 安全評價師 | 電氣工程師 | 注冊測繪師 | 注冊計量師 |
|
![]() |
繽紛校園 | 實用文檔 | 英語學習 | 作文大全 | 求職招聘 | 論文下載 | 訪談 | 游戲 |
或者:
Object TestForm1: TTestForm
前者是ffInherited和ffChildPos置位,后面是都沒置位。
ConvertProperty過程用于轉化屬性。
procedure ConvertProperty;
begin
WriteIndent;
WriteStr(Reader.ReadStr);
WriteStr(' = ');
ConvertValue;
WriteStr(#13#10);
end;
WriteIndent語句寫入屬性名前的空格,WriteStr(Reader.ReadStr)語句寫入屬性名ConvertValue過程根據屬性的類型將屬性值轉化為字符串,然后寫入流中。
ObjectTextToBinary過程執行的功能與ObjectBinaryToText相反,將TXT文件轉換為二進制流中的部件,而且只要TXT文件內容的書寫符合DFM腳本語法,ObjectTextToBinary可將任何程序生成的TXT文件轉換為部件,這一功能也為DFM 文件的動態生成和編輯奠定了基礎。ObjectTextToBinary過程的主程序如下:
procedure ObjectTextToBinary(Input, Output: TStream);
var
SaveSeparator: Char;
Parser: TParser;
Writer: TWriter;
…
begin
Parser := TParser.Create(Input);
SaveSeparator := DecimalSeparator;
DecimalSeparator := '.';
try
Writer := TWriter.Create(Output, 4096);
try
Writer.WriteSignature;
ConvertObject;
finally
Writer.Free;
end;
finally
DecimalSeparator := SaveSeparator;
Parser.Free;
end;
end;
在程序流程和結構上與ObjectBinaryToText差不多。ConvertObject也是個遞歸過程:
procedure ConvertObject;
var
InheritedObject: Boolean;
begin
InheritedObject := False;
if Parser.TokenSymbolIs('INHERITED') then
InheritedObject := True
else
Parser.CheckTokenSymbol('OBJECT');
Parser.NextToken;
ConvertHeader(InheritedObject);
while not Parser.TokenSymbolIs('END') and
not Parser.TokenSymbolIs('OBJECT') and
not Parser.TokenSymbolIs('INHERITED') do ConvertProperty;
Writer.WriteListEnd;
while not Parser.TokenSymbolIs('END') do ConvertObject;
Writer.WriteListEnd;
Parser.NextToken;
end;
DFM文件與DFM腳本語言之間相互轉換的任務由ObjectResourceToText和ObjextTextToResource兩個過程完成。
procedure ObjectResourceToText(Input, Output: TStream);
begin
Input.ReadResHeader;
ObjectBinaryToText(Input, Output);
end;
ObjectTextToResource過程就比較復雜,因為DFM文件資源頭中要包含繼承標志信息,因此在調用ObjectTextToBinary后,就讀取標志信息,然后寫入資源頭。
procedure ObjectTextToResource(Input, Output: TStream);
var
Len: Byte;
Tmp: Longint;
MemoryStream: TMemoryStream;
MemorySize: Longint;
Header: array[0..79] of Char;
begin
MemoryStream := TMemoryStream.Create;
try
ObjectTextToBinary(Input, MemoryStream);
MemorySize := MemoryStream.Size;
FillChar(Header, SizeOf(Header), 0);
MemoryStream.Position := SizeOf(Longint); { Skip header }
MemoryStream.Read(Len, 1);
if Len and $F0 = $F0 then
begin
if ffChildPos in TFilerFlags((Len and $F0)) then
begin
MemoryStream.Read(Len, 1);
case TValueType(Len) of
vaInt8: Len := 1;
vaInt16: Len := 2;
vaInt32: Len := 4;
end;
MemoryStream.Read(Tmp, Len);
end;
MemoryStream.Read(Len, 1);
end;
MemoryStream.Read(Header[3], Len);
StrUpper(@Header[3]);
Byte((@Header[0])^) := $FF;
Word((@Header[1])^) := 10;
Word((@Header[Len + 4])^) := $1030;
Longint((@Header[Len + 6])^) := MemorySize;
Output.Write(Header, Len + 10);
Output.Write(MemoryStream.Memory^, MemorySize);
finally
MemoryStream.Free;
end;
end;
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;
3. 動態DFM文件應用之二:超媒體系統腳本語言設計
超媒體腳本語言設計是超媒體系統設計的重要內容。腳本語言必須能夠表達卡片中的多種媒體對象,必須是可編程,可理解的,必須是可執行的,應該可以由腳本語言生成超媒體系統中的卡片和鏈。
DFM文件可以看作是超媒體系統的卡片,DFM腳本能夠表達DFM文件中的多種控制,也就是說能夠表達卡片中的多種媒體對象,再加上DFM腳本的對象式表達,可編輯性,可轉換為DFM文件,因此用作超媒體系統腳本語言較好的形式。
ObjectBinaryToText和ObjectTextToBinary過程提供了在部件和DFM腳本之間相互轉化的功能,ObjectResourceToText和ObjectTextToResoure過程提供了DFM文件和DFM腳本之間相互轉化的功能。這樣就可以在應用程序中自如實現超媒體卡片和超媒體腳本語言相互轉化。
下面是卡片和腳本語言相互轉化的程序:
procedure TMDIChild.CardToScript;
var
In, Out: TStream;
begin
In := TMemoryStream.Create;
Out := TMemoryStream.Create;
try
In.WriteComponentRes(Self.ClassName, Self);
ObjectResourceToText(In, out);
ScriptForm.ScriptEdit.Lines.LoadFromStream(Out);
finally
In.Free;
Out.Free;
end;
end;
ScriptEdit是個文本編輯器,它的Lines屬性是TStrings類型的對象。
procedure TScriptForm.ScriptToCard;
var
In, Out: TStream;
begin
In := TMemoryStream.Create;
Out := TMemoryStream.Create;
try
ScriptForm.ScriptEdit.Lines.SaveToFromStream(In);
ObjectTextToResource(In, out);
In.ReadComponentRes(DesignWin);
finally
In.Free;
Out.Free;
end;
end;
這兩段程序是對整個卡片,即窗體級,進行轉換的。ObjectBinaryToText和ObjectTextToBinary過程可以細化到部件級的轉換。因此超媒體腳本語言的編輯可以細化到媒體對象級。
4. 超媒體編輯和表現系統與動態DFM文件的擴展
超媒體系統的媒體編輯與卡片管理有其特殊的需求,比如鏈接需求。這時采用已有的窗體部件和媒體部件并按常規的DFM文件處理就顯得力不從心了。解決這個矛盾有兩套方案:
● 利用Delphi部件開發技術,繼承和開發新的部件增加新的超媒體特有的屬性和處理方法
● 擴展DFM文件結構,使之能按自己的需要任意地存取和轉換部件和DFM文件
前者是充分利用Delphi的面向對象部件開發技術,在存取和轉換等處理上仍舊與常規DFM文件相同。而后者需要DFM的存取和轉換上作比較大的改動。下文介紹擴展DFM文件的思路。
擴展動態DFM文件的總體思路是降低處理操作的數據的顆粒度,即從原先窗體級降低到部件級。
相關推薦:2010年9月計算機等級考試試題及答案解析專題北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內蒙古 |