熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Delphi編程 >> 正文

DELPHI基礎教程:開發Delphi對象式數據管理功能(五)[1]

2013-11-23 17:47:34  來源: Delphi編程 

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

  

  寫DFM文件的過程WriteComponentResFie

  該過程帶有兩個參數FileName和InstanceFileName參數指定要寫入的DFM文件名Instance參數是TComponent類型的它指定要寫入的部件名一般是TForm對象的子類該過程將Instance部件和其擁有的所有部件寫入DFM文件

  這個過程的意義在於可以在程序運行過程中產生Delphi的窗體部件和在窗體中插入部件並由該函數將窗體寫入DFM文件支持了動態DFM文件的重用性

  該過程的程序是這樣的

  procedure WriteComponentResFile(const FileName: string; Instance: TComponent)

  var

  Stream: TStream;

  begin

  Stream := TFileStreamCreate(FileName fmCreate)

  try

  StreamWriteComponentRes(InstanceClassName Instance)

  finally

  StreamFree;

  end;

  end;

  函數中用FileStream創建文件用Stream對象的WriteComponetRes方法將Instance寫入流中

   讀DFM文件的函數ReadComponentResFile

  ReadComponentResFile函數帶有兩個參數FileName和InstanceFileName參數指定要讀DFM文件名Instance參數指定從DFM文件中要讀的部件該函數從DFM文件中將Instance和它擁有的所有部件並返回該部件

  這個函數的意義在於配合WriteComponentResFile過程的使用支持DFM文件的重用性

  該函數的程序是這樣的

  function ReadComponentResFile(const FileName: string; Instance: TComponent)

  TComponent;

  var

  Stream: TStream;

  begin

  Stream := TFileStreamCreate(FileName fmOpenRead)

  try

  Result := StreamReadComponentRes(Instance)

  finally

  StreamFree;

  end;

  end;

  程序中使用FileStream對象打開由FileName指定的DFM文件然後用Stream對象的ReadComponentRes方法讀出Instance並將讀的結果作為函數的返回值

   讀取Delphi應用程序資源中的部件

  函數InternalReadComponentRes可以讀取Delphi應用程序資源中的部件Delphi 的DFM文件在程序經過編譯鏈接後被嵌入應用程序的資源中而且格式發生了改變即少了資源文件頭

  在第一節中曾經介紹過TResourceStream對象該對象是操作資源媒介上的數據的函數InternalReadComponentRes用了TResourceStream程序是這樣的

  function InternalReadComponentRes(const ResName: string;

  var Instance: TComponent) Boolean;

  var

  HRsrc: THandle;

  begin { 避免EResNotFound異常事件的出現 }

  HRsrc := FindResource(HInstance PChar(ResName) RT_RCDATA)

  Result := HRsrc <> ;

  if not Result then Exit;

  FreeResource(HRsrc)

  with TResourceStreamCreate(HInstance ResName RT_RCDATA) do

  try

  Instance := ReadComponent(Instance)

  finally

  Free;

  end;

  Result := True;

  end;

  HInstance是一個Delphi VCL定義的全局變量代表當前應用程序的句柄函數用了資源訪問API函數FindResource來測定是否存在ResName所描述資源因為在TResourceStream的創建過程還有FindResource等操作所以函數中調用了FreeResource最後函數調用了Stream對象的ReadComponent方法讀出部件因為函數的Instance是var類型的參數所以可以訪問Instance得到讀出的部件

   DFM文件與標准文本文件(TXT文件)的相互轉換

  在Delphi可視化設計環境中允許程序員在代碼編輯器中以文本的方式浏覽和修改DFM文件內容當用File/Open命令直接打開DFM文件或者選擇窗體設計窗口的彈出式菜單上的View as Text命令時就會在編輯器中出現文本形式的信息我們姑且將這種文本形式稱之為窗體設計腳本Delphi提供的這種腳本編輯功能是對Delphi可視化設計的一大補充當然這個腳本編輯能力是有限制的比方說不能在腳本任意地添加和刪除部件因為代碼和DFM腳本是緊密相連的任意添加和修改會導致不一致性然而在動態生成的DFM文件中就不存在這一限制後面會介紹DFM動態生成技術的應用

  實際上DFM文件內容是二進制數據它的腳本是經過Delphi開發環境自動轉化的而且Delphi VCL中的Classes庫單元中提供了在二進制流中的文件DFM和它的腳本之相互轉化的過程它們是ObjectBinaryToText和ObjectTextBinaryObjectResourceToText和ObjectTextToResource

  ObjectBinaryToText過程將二進制流中存儲的部件轉化為基於文本的表現形式這樣就可以用文本處理函數進行處理還可以用文本編輯器進行查找和替代操作最後可以將文本再轉化成二進制流中的部件

  ObjectBinaryToText過程的主程序是這樣的

  procedure ObjectBinaryToText(Input Output: TStream)

  var

  NestingLevel: Integer;

  SaveSeparator: Char;

  Reader: TReader;

  Writer: TWriter;

  procedure WriteIndent;

  const

  Blanks: array[] of Char = ;

  var

  I: Integer;

  begin

  for I := to NestingLevel do WriterWrite(Blanks SizeOf(Blanks))

  end;

  procedure WriteStr(const S: string)

  begin

  WriterWrite(S[] Length(S))

  end;

  procedure NewLine;

  begin

  WriteStr(##

  WriteIndent;

  end;

  procedure ConvertHeader;

  begin

  …

  end;

  procedure ConvertBinary;

  begin

  …

  end;

  procedure ConvertValue;

  begin

  …

  end;

  procedure ConvertProperty;

  begin

  …

  end;

  procedure ConvertObject;

  begin

  …

  end;

  begin

  NestingLevel := ;

  Reader := TReaderCreate(Input

  SaveSeparator := DecimalSeparator;

  DecimalSeparator := ;

  try

  Writer := TWriterCreate(Output

  try

  ReaderReadSignature;

  ConvertObject;

  finally

  WriterFree;

  end;

  finally

  DecimalSeparator := SaveSeparator;

  ReaderFree;

  end;

  end;

  過程中調用的ConvertObject過程是個遞歸過程用於將DFM文件中的每一個部件轉化為文本形式因為由於部件的擁有關系所以部件成嵌套結構采用遞歸是最好的方式

  procedure ConvertObject;

  begin

  ConvertHeader;

  Inc(NestingLevel)

  while not ReaderEndOfList do ConvertProperty;

  ReaderReadListEnd;

  while not ReaderEndOfList do ConvertObject;

  ReaderReadListEnd;

  Dec(NestingLevel)

  WriteIndent;

  WriteStr(end##

  end;

  NestStingLevel變量表示部件的嵌套層次WriteIndent是寫入每一行起始字符前的空格ConvertHeader過程是處理部件的繼承標志信息轉換成的頭信息文本有兩種形式

  Inherited TestForm: TTestForm[]

  或者

  Object TestForm: TTestForm

  前者是ffInherited和ffChildPos置位後面是都沒置位

  ConvertProperty過程用於轉化屬性

  procedure ConvertProperty;

  begin

  WriteIndent;

  WriteStr(ReaderReadStr)

  WriteStr( =

  ConvertValue;

  WriteStr(##

  end;

  WriteIndent語句寫入屬性名前的空格WriteStr(ReaderReadStr)語句寫入屬性名ConvertValue過程根據屬性的類型將屬性值轉化為字符串然後寫入流中

[]  []  []  []  


From:http://tw.wingwit.com/Article/program/Delphi/201311/25088.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.