Delphi的元件讀寫機制(二) (轉)

gugu99發表於2007-12-04
Delphi的元件讀寫機制(二) (轉)[@more@]

:namespace prefix = o ns = "urn:schemas--com::office" />

Ø  TFiler

  先來看一下TFiler類的定義:

  TFiler = class(T)

  private

  FStream: TStream;

  FBuffer: Pointer;

  FBufSize: Integer;

  FBufPos: Integer;

  FBufEnd: Integer;

  F: TComponent;

  FLookupRoot: TComponent;

  FAncestor: TPersistent;

  FIgnoreChildren: Boolean;

  protected

  procedure SetRoot(Value: TComponent); virtual;

  public

  constructor Create(Stream: TStream; BufSize: Integer);

  destructor Destroy; overr;

  procedure DefineProperty(const Name: string;

  ReadData: TReaderProc; WriteData: TWriterProc;

  HasData: Boolean); virtual; abstract;

  procedure DefineBinaryProperty(const Name: string;

  ReadData, WriteData: TStreamProc;

  HasData: Boolean); virtual; abstract;

  procedure FlushBuffer; virtual; abstract;

  property Root: TComponent read FRoot write SetRoot;

  property LookupRoot: TComponent read FLookupRoot;

  property Ancestor: TPersistent read FAncestor write FAncestor;

  property IgnoreChildren: Boolean read FIgnoreChildren write FIgnoreChildren;

  end;

  TFiler是TReader和TWriter的抽象類,定義了用於的基本屬性和方法。它定義了Root屬性,Root指明瞭所讀或寫的元件的根物件,它的Create方法將Stream物件作為傳入引數以建立與Stream物件的聯絡, Filer物件的具體讀寫操作都是由Stream物件完成。因此,只要是Stream物件所能訪問的媒介都能由Filer物件存取元件。

  TFiler 物件還提供了兩個定義屬性的public方法:DefineProperty和DefineBinaryProperty,這兩個方法使物件能讀寫不在元件published部分定義的屬性。下面重點介紹一下這兩個方法。

  Defineproperty ( )方法用於使標準資料型別持久化,諸如字串、整數、布林、字元、浮點和列舉。

  在Defineproperty方法中。Name引數用於指定應寫入DFM的屬性的名稱,該屬性不在類的published部分定義。

  ReadData和WriteData引數指定在存取物件時讀和寫所需資料的方法。ReadData引數和WriteData引數的型別分別是TReaderProc和TWriterProc。這兩個型別是這樣宣告的:

  TReaderProc = procedure(Reader: TReader) of object;

  TWriterProc = procedure(Writer: TWriter) of object;

  HasData引數在執行時決定了屬性是否有資料要儲存。

  DefineBinaryProperty方法和Defineproperty有很多的相同之處,它用來儲存二進位制資料,如和圖象等。

  下面來說明一下這兩個方法的用途。

  我們在窗體上放一個非視覺化元件如TTimer,重新開啟窗體時我們發現TTimer還是在原來的地方,但TTimer沒有Left和Top屬性啊,那麼它的位置資訊儲存在哪裡呢?

  開啟該窗體的DFM檔案,可以看到有類似如下的幾行內容:

  object Timer1: TTimer

  Left = 184

  Top = 149

  end

的流只能儲存published資料,但TTimer並沒有published的Left和Top屬性,那麼這些資料是怎麼被儲存下來的呢?

TTimer是TComponent的派生類,在TComponent類中我們發現有這樣的一個:

procedure TComponent.DefineProperties(Filer: TFiler);

var

  Ancestor: TComponent;

  Info: Longint;

begin

  Info := 0;

  Ancestor := TComponent(Filer.Ancestor);

  if Ancestor <> nil then Info := Ancestor.FDesignInfo;

  Filer.DefineProperty('Left', ReadLeft, WriteLeft,

  LongRec(FDesignInfo).Lo <> LongRec(Info).Lo);

  Filer.DefineProperty('Top', ReadTop, WriteTop,

  LongRec(FDesignInfo).Hi <> LongRec(Info).Hi);

end;

  TComponent的DefineProperties是覆蓋了它的祖先類TPersistent的方法,在TPersistent類中該方法為空的虛方法。

  在DefineProperties方法中,我們可以看出,有一個Filer物件作為它的引數,當定義屬性時,它引用了Ancestor屬性,如果該屬性非空,物件應當只讀寫與從Ancestor繼承的不同的屬性的值。它TFiler的DefineProperty方法,並定義了ReadLeft,WriteLeft,ReadTop,WriteTop方法來讀寫Left和Top屬性。

  因此,凡是從TComponent派生的元件,即使它沒有Left和Top屬性,在流化到DFM檔案中,都會存在這樣的兩個屬性。

  在查詢資料的過程中,發現很少有資料涉及到元件讀寫機制的。由於元件的寫過程是在設計階段由Delphi的IDE來完成的,因此無法跟蹤它的執行過程。所以筆者是透過在執行過程中跟蹤VCL原始碼來了解元件的讀機制的,又透過讀機制和TWriter來分析元件的寫機制。所以下文將按照這一思維過程來講述元件讀寫機制,先講TReader,而後是TWriter。

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-987775/,如需轉載,請註明出處,否則將追究法律責任。

相關文章