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

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

編輯:Delphi

6. 讀取部件的方法的實現

Reader對象中用於讀取部件的方法有ReadSignature、ReadPrefix、ReadComponent、ReadRootComponent和ReadComponents。

ReadSignature方法主要用於讀取Delphi Filer對象標簽一般在讀取部件前,都要用調用ReadSignature方法以指導部件讀寫過程。

procedure TReader.ReadSignature;

var

Signature: Longint;

begin

Read(Signature, SizeOf(Signature));

if Signature <> Longint(FilerSignature) then ReadError(SInvalidImage);

end;

FilerSignature就是Filer對象標簽其值為“TPF0” ,如果讀的不是“TPF0” ,則會觸發SInValidImage異常事件。

ReadPrefix方法是用於讀取流中部件前的標志位,該標志表示該部件是否處於從祖先窗體中繼承的窗體中和它在窗體中的位置是否很重要。

procedure TReader.ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);

var

Prefix: Byte;

begin

Flags := [];

if Byte(NextValue) and $F0 = $F0 then

begin

Prefix := Byte(ReadValue);

Byte(Flags) := Prefix and $0F;

if ffChildPos in Flags then AChildPos := ReadInteger;

end;

end;

TFilerFlags的定義是這樣的:

TFilerFlag = (ffInherited, ffChildPos);

TFilerFlags = Set of TFilerFlag;

充當標志的字節的高四位是$F,低四位是集合的值,也是標志位的真正含義。如果ffChildPos置位,則緊接著的整型數字中放著部件在窗體中的位置序值。

ReadComponent方法用於從Reader對象的流中讀取部件。Component 參數指定了要從流中讀取的對象。函數返回所讀的部件。

function TReader.ReadComponent(Component: TComponent): TComponent;

var

CompClass, CompName: string;

Flags: TFilerFlags;

Position: Integer;

begin

ReadPrefix(Flags, Position);

CompClass := ReadStr;

CompName := ReadStr;

Result := Component;

if Result = nil then

if ffInherited in Flags then

FindExistingComponent else

CreateComponent;

if Result <> nil then

try

Include(Result.FComponentState, csLoading);

if not (ffInherited in Flags) then SetCompName;

if Result = nil then Exit;

Include(Result.FComponentState, csReading);

Result.ReadState(Self);

Exclude(Result.FComponentState, csReading);

if ffChildPos in Flags then Parent.SetChildOrder(Result, Position);

FLoaded.Add(Result);

except

if ComponentCreated then Result.Free;

raise;

end;

end;

ReadCompontent方法首先調用ReadPrefix方法,讀出部件標志位和它的創建次序值(Create Order)。然後用ReadStr方法分別讀出部件類名和部件名。如果Component參數為nil,則執行兩個任務:

● 如果ffInberited 置位則從Root 找已有部件,否則,就從系統的Class表中找到該部件類型的定義並創建

● 如果結果不為空,將用部件的ReadState方法讀入各種屬性值,並設置部件的Parent 屬性,並恢復它在Parent部件的創建次序。

ReadComponent方法主要是調用ReadComponent方法從Reader對象的流中讀取一連串相關聯的部件,並分解相互引用關系。

procedure TReader.ReadComponents(AOwner, AParent: TComponent;

Proc: TReadComponentsProc);

var

Component: TComponent;

begin

Root := AOwner;

Owner := AOwner;

Parent := AParent;

BeginReferences;

try

while not EndOfList do

begin

ReadSignature;

Component := ReadComponent(nil);

Proc(Component);

end;

FixupReferences;

finally

EndReferences;

end;

end;

ReadComponents首先用AOwner和AParent參數給Root,Owner和Parent賦值,用於重建各部件的相互引用。然後用一個While循環讀取部件並用由Proc傳入的方法進行處理。在重建引用關系時,用了BeginReferences、FixUpReferences和EndReferences嵌套模式。

ReadRootComponent方法從Reader對象的流中將部件及其擁有的部件全部讀出。如果Component參數為nil,則創建一個相同類型的部件,最後返回該部件:

function TReader.ReadRootComponent(Root: TComponent): TComponent;

function FindUniqueName(const Name: string): string;

begin

end;

var

I: Integer;

Flags: TFilerFlags;

begin

ReadSignature;

Result := nil;

try

ReadPrefix(Flags, I);

if Root = nil then

begin

Result := TComponentClass(FindClass(ReadStr)).Create(nil);

Result.Name := ReadStr;

end else

begin

Result := Root;

ReadStr; { Ignore class name }

if csDesigning in Result.ComponentState then

ReadStr else

Result.Name := FindUniqueName(ReadStr);

end;

FRoot := Result;

if GlobalLoaded <> nil then

FLoaded := GlobalLoaded else

FLoaded := TList.Create;

try

FLoaded.Add(FRoot);

FOwner := FRoot;

Include(FRoot.FComponentState, csLoading);

Include(FRoot.FComponentState, csReading);

FRoot.ReadState(Self);

Exclude(FRoot.FComponentState, csReading);

if GlobalLoaded = nil then

for I := 0 to FLoaded.Count - 1 do TComponent(FLoaded[I]).Loaded;

finally

if GlobalLoaded = nil then FLoaded.Free;

FLoaded := nil;

end;

GlobalFixupReferences;

except

RemoveFixupReferences(Root, '');

if Root = nil then Result.Free;

raise;

end;

end;

ReadRootComponent首先調用ReadSignature讀取Filer對象標簽。然後在try…except循環中執行讀取任務。如果Root參數為nil,則用ReadStr讀出的類名創建新部件,並以流中讀出部件的Name屬性;否則,忽略類名,並判斷Name屬性的唯一性。最後用Root的ReadState方法讀取屬性和其擁有的擁有並處理引用關系。

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