




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領
文檔簡介
1、保存 評價 游戲規(guī)則 免費注冊 資料下載 關于本站問題分類 編程問題 非技術(shù)題 富翁列表 我的信息 提出問題 在線富翁 富翁日歷 筆記列表 我的筆記 寫作筆記 全文檢索 專家門診 (component至表單,完成表單的界面和事件設計。Delphi 將這些界面的設計期信息保存在表單相應的 DFM 文件中,方便程序員隨時讀取和修改。DFM 文件根據(jù)元件在表單上的嵌套層次存放元件屬性,以下是一個 DFM 文件的示例:object Form1: TForm1.Left = 192Top = 107Width = 544Caption = 'Form1'object Button1: T
2、ButtonLeft = 24Top = 16Caption = 'Button1'OnClick = Button1Clickend.end應用程序編譯之后,DFM 文件的信息被二進制化了,這些二進制信息存儲在應用程序的資源(resource段中。每個表單(也就是 class 及表單上的元件在資源段中存儲為與表單同名的資源,可以使用 FindResource API 獲得。應用程序在運行期創(chuàng)建表單實例的時候,會從資源段中讀取表單的屬性,還原設計期的設置。這種將類型信息保存在文件中,并且可以在運行期恢復類型的操作,在本文中被稱之為持續(xù)(persistent機制。持續(xù)機制是 De
3、lphi 成為 RAD 工具的原因之一。持續(xù)機制和 RTTI 是緊密結(jié)合的,但本文不討論 RTTI(關于 RTTI 可參考我前幾天寫的兩篇筆記 ,只討論實現(xiàn)持續(xù)機制的總體框架及相關類(class。這些類包括 TStream 、TFiler 、TReader 、TWriter 、TParser 、TPersisetent 、TComponent 、TCustomForm 等。= ReadComponentResFile / WriteComponentResFile 函數(shù)=讓我們從一個比較直觀的例子開始。Classes.pas 中定義了兩個函數(shù) ReadComponentResFile 和 Wr
4、iteComponentResFile ,它們的功能是“把元件的屬性信息保存到文件”和“從文件中恢復元件屬性信息”。先做個試驗。新建一個項目,在 Form1 上放置兩個 Button 和一個 Memo 。Button 的 Click 事件代碼如下。按 F9 運行該項目,先在 Memo1 中輸入一些字符,然后按下 Button1,再按下 Button2,你會看一個新建的 Form 。它的屬性幾乎和 Form1 一樣,甚至連 Memo1 中的字符都保存下來了,唯一的不同只是它的 Name 屬性變成了“Form1_1”。你可以查看 FORM1.RES 文件的內(nèi)容看看 Delphi 是如何存儲元件信息
5、的。procedure TForm1.Button1Click(Sender: TObject;beginWriteComponentResFile('C:FORM1.RES', Form1;end;procedure TForm1.Button2Click(Sender: TObject;varNewForm: TForm1;beginNewForm := TForm1.CreateNew(Application;ReadComponentResFile('C:FORM1.RES', NewForm;NewForm.Left := NewForm.Left +
6、 100;end;WriteComponentResFile 函數(shù)的代碼如下,它只是調(diào)用 Stream 對象的 WriteComponentRes 方法將對象屬性保存到資源文件中的:procedure WriteComponentResFile(const FileName: string; Instance: TComponent;beginStream := TFileStream.Create(FileName, fmCreate;Stream.WriteComponentRes(Instance.ClassName, Instance;Stream.Free;end;ReadCompo
7、nentResFile 函數(shù)也是調(diào)用 Stream 的方法實現(xiàn)從文件中讀取對屬信息:function ReadComponentResFile(const FileName: string; Instance: TComponent:TComponent;beginStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite;Result := Stream.ReadComponentRes(Instance;Stream.Free;end;ReadComponentResFile 函數(shù)可以通過 Instance 參
8、數(shù)傳入對象句柄,也可以通過返回值獲得對象句柄。Instance 參數(shù)只能是已實例化的對象或 nil 。如果是 nil ,那么 ReadComponentResFile 會自動根據(jù)文件信息創(chuàng)建對象實例,但必須使用 RegisterClass 函數(shù)注冊將要被載入的類,否則會觸發(fā)異常。有個類似的函數(shù) ReadComponentRes ,它從應用程序的資源段中恢復對象的屬性信息。它的ResName 參數(shù)就是表單類的名稱:function ReadComponentRes(const ResName: string; Instance: TComponent:TComponent;= Delphi 持續(xù)
9、機制框架簡述=持續(xù)機制的實現(xiàn)必須由 IDE 、編譯器、表單類、元件類和輔助類合作完成。這里的表單類不是指一般所指的 TForm class,在 Delphi 的幫助文件中,稱之為“root class”。root class 是指能在設計期被 Form Designer 作為最上層編輯表單的類(如 TCustomForm 、TFrame 、TDataModule 等 。Delphi 在設計期將元件的 published 屬性的值保存在 .DFM 文件中,也只有 published 的屬性才能被 Object Insepector 設置賦值。Form Designer 設計的 root clas
10、s 對象在編譯時,Delphi 將對象的屬性以及其所包含的元件的屬性保存在應用程序的資源段(RT_RCDATA中。輔助類包括 TStream 、TReader 、TWriter 、TParser 等。這些類起著中間層的作用,用于存儲和讀取對象屬性的信息。雖然我稱它們?yōu)檩o助類,但是保存和恢復對象信息的實際操作是由它們完成的。= 一個 TForm 對象的創(chuàng)建過程=下面是一個典型的表單 Form1 的創(chuàng)建過程,縮進代表調(diào)用關系(Form1.ReadState 例外,防止縮進太多 ,帶“?”的函數(shù)表示我尚未仔細考察的部分,帶“*”表示元件編寫者需要注意的函數(shù)。Application.CreateFor
11、m(TForm1, Form1;|-Form1.NewInstance;|-Form1.Create(Application;|-Form1.CreateNew(Application;|-InitInheritedComponent(Form1, TForm;|-InternalReadComponentRes(Form1.ClassName, Form1ResHInst, Form1;|-TResourceStream.Create(Form1ResHInst, Form1.ClassName, RT_RCDATA;|-TResourceStream.ReadComponent(Form1
12、;|-TReader.Create(ResourceStream, 4096;|-TReader.ReadRootComponent(Form1;|-TReader.ReadSignature;*|-TReader.ReadPrefix(Flags, ChildPos;|-IF Form1 = nil THEN Form1 := FindClass(ReadStr.Create;|-Include(Form1.FComponentState, csLoading;|-Include(Form1.FComponentState, csReading;|-Form1.Name := FindUni
13、queName(ReadStr;?|-FFinder := TClassFinder.Create;*|-Form1.ReadState(Reader;|-TCustomForm.ReadState(Reader; DisableAlign; |-TWinControl.ReadState(Reader; DisableAlign; *|-TControl.ReadState(Reader; Include(FControlState, csReadingState; Parent := TWinControl(Reader.Parent; *|-TComponent.ReadState(Re
14、ader;|-Reader.ReadData(Form1;|-Reader.ReadDataInner(Form1;|-WHILE NOT EndOfList DO Reader.ReadProperty(Form1;|-IF PropInfo <> nil THEN ReadPropValue(Form1, PropInfo;*|-ELSE Form1.DefineProperties(Reader;|-WHILE NOT EndOfList DO ReadComponent(nil;|-ReadPrefix(Flags, Position;|-IF ffInherited TH
15、EN FindExistingComponent|-ELSE CreateComponent;*|-SubComponent.ReadState(Reader; (Like Form1.ReadState?|-DoFixupReferences;過程簡述:TCustomForm.Create 函數(shù)中先調(diào)用 CreateNew 設置缺省的表單屬性,然后調(diào)用Classes.InitInheritedComponent 函數(shù)。InitInheritedComponent 用于初始化一個 root class 對象。該函數(shù)的功能就是從應用程序的資源中恢復設計期的表單信息。InitInheritedCo
16、mponent 的聲明如下: Classes.pas function InitInheritedComponent(Instance: TComponent;RootAncestor: TClass: Boolean;InitInheritedComponent 傳入兩個參數(shù):Instance 參數(shù)代表將要從資源段中恢復信息的對象,RootAncestor 表示該對象的祖先類。如果從資源中恢復信息成功,則返回 True ,否則返回 False 。InitInheritedComponent 通常只在 root class 的構(gòu)造函數(shù)中調(diào)用。constructor TCustomForm.Cr
17、eate(AOwner: TComponent;begin.CreateNew(AOwner; / 初始化缺省的 Form 屬性Include(FFormState, fsCreating; / 標記為 Creating 狀態(tài)if not InitInheritedComponent(Self, TForm then / 從資源中恢復 Form 信息raise EResNotFound.CreateFmt(SResNotFound, ClassName;.Exclude(FFormState, fsCreating; / 取消 Creating 狀態(tài)end;InitInheritedCompo
18、nent 調(diào)用自身內(nèi)置的函數(shù):InitComponent(Instance.ClassType。InitComponent 先判斷 Instance.ClassType 是否是 TComponent 或 RootAncestor ,如果是則返回 False 并退出,否則調(diào)用 InternalReadComponentRes 。* InitComponent 遞歸調(diào)用自己檢查類信息。沒看懂為什么要這樣設計,如果有誰看懂了請告訴我。function InitComponent(ClassType: TClass: Boolean;beginResult := False;if (ClassType
19、 = TComponent or (ClassType = RootAncestor then Exit;Result := InitComponent(ClassType.ClassParent;Result := InternalReadComponentRes(ClassType.ClassName,FindResourceHInstance(FindClassHInstance(ClassType, Instance or Result;end;InternalReadComponentRes 使用 Instance.ClassName 作為 ResourceName ,調(diào)用FindR
20、esourceHInstance 找到 class 資源所在模塊的 HInst 句柄(因為 class 可能是在動態(tài)鏈接庫中 ,并通過引用方式傳遞 Instance 對象(* 好像沒有必要使用引用方式,InitInheritedComponent 也沒有使用引用方式 : Classes.pas function InternalReadComponentRes(const ResName: string; HInst: THandle;var Instance: TComponent: Boolean;InternalReadComponentRes 先檢查 class 資源是否存在,如果存在
21、則創(chuàng)建一個TResourceStream 對象(TResourceStream 的 Create 構(gòu)造函數(shù)把 class 信息的資源內(nèi)存地址和大小記錄在成員字段中 ,然后使用 TResourceStream.ReadComponent 方法從資源中讀取 Instance 的信息。TResourceStream 并沒有定義 ReadComponent 方法,而是使用祖先類 TStream 的方法。TStream.ReadComponent 創(chuàng)建一個 TReader 對象,然后使用自己的對象地址(Self作為參數(shù),調(diào)用 TReader.ReadRootComponent 讀取 Instance 對
22、象的內(nèi)容。 TReader function ReadRootComponent(Root: TComponent: TComponent;ReadRootComponent 先調(diào)用 TReader.ReadSignature 。ReadSignature 從 stream 中讀取 4 字節(jié)的內(nèi)容,如果讀出來的內(nèi)容不是 'TPF0' ,則觸發(fā)異常(SInvalidImage,表示該 stream 的內(nèi)容是錯誤的。然后 ReadRootComponent 調(diào)用 ReadPrefix 讀取元件的狀態(tài)信息。如果 Root 參數(shù)是 nil ,也就是說 Root 對象還沒被創(chuàng)建,則直接從
23、流中讀取 Root 的類名,再使用 FindClass 函數(shù)找到該類在內(nèi)存中的地址,并調(diào)用該類的構(gòu)造函數(shù)創(chuàng)建 Root 的實例。接下來 ReadRootComponent 調(diào)用 Root 的 ReadState 虛函數(shù)從流中讀取 Root 對象的屬性。TComponent.ReadState 只有一行代碼:Reader.ReadData(Self;。ReadData 調(diào)用 ReadDataInner 讀取 root 元件及 root 的子元件的屬性信息。ReadDataInner 先循環(huán)調(diào)用 ReadProperty 從流中讀取 root 元件的屬性,直到遇到 EndOfList標志(vaNu
24、ll。ReadProperty 使用 RTTI 函數(shù),將從流中讀出的數(shù)據(jù)設置為對象的屬性。ReadProperty 中還調(diào)用了 Instance.DefineProperties ,用于實現(xiàn)自定義的屬性存儲。ReadDataInner 然后循環(huán)調(diào)用 ReadComponent(nil 讀取子元件的信息。ReadComponent 的執(zhí)行過程與 ReadRootComponent 的過程很相似,它根據(jù)流中的信息使用 FindComponentClass 找到元件類在內(nèi)存中的地址,然后調(diào)用該元件類的構(gòu)造函數(shù)創(chuàng)建對象,接下來調(diào)用新建對象的 ReadState -> TReader.ReadDa
25、ta -> ReadDataInner ->TReader.ReadProperty ,重復 ReadRootComponent 的過程。TReader.ReadComponent 和 TComponent.ReadState 形成遞歸調(diào)用過程,把表單上嵌套的元件創(chuàng)建出來。最后 InitInheritedComponent 函數(shù)返回,一個 root class 對象從資源中實例化的過程完成。= TStream Class 和 TStream.ReadComponent 方法=TStream 在對象持續(xù)機制扮演的角色是提供一種存儲媒介,由 TFiler 對象使用。TStream 是一
26、個虛類,它定義了數(shù)據(jù)的“流式”讀寫方法。它的繼承類 TFileStream 、TMemoryStream 、TResourceStream 等實現(xiàn)對不同媒體的讀寫。對象的 persistent 信息可以存儲在任何 TStream 類中,也可以從任何 TStream 中獲得。由于 Delphi 缺省的對象信息存儲在應用程序的資源段中,因此,可以從程序的資源段中讀取數(shù)據(jù)的 TResourceStream 類就顯得更加重要。TStream 定義兩個讀寫緩沖的方法:ReadBuffer 和 WriteBuffer 。這兩個方法封裝了 TStream.Read 和 TStream.Write 純虛方法(
27、必須被后繼類重載 。 TStream procedure ReadBuffer(var Buffer; Count: Longint;procedure WriteBuffer(const Buffer; Count: Longint;可以看到這兩個方法的 Buffer 參數(shù)都是無類型的,也就是使用引用的方式傳入的,所以不管是使用單個字符或自定義的結(jié)構(gòu)都是正確的(當然,不能使用常量 。Count 指示要讀或?qū)懭氲?Buffer 的大小(Bytes。TStream 還定義了兩個元件信息的讀寫方法:ReadComponent 和 WriteComponent 。由于 WriteComponent
28、通常是由 Delphi 的 IDE/編譯器調(diào)用的,很難跟蹤它的執(zhí)行過程,所以我們以后主要考察 ReadComponent 方法。我們可以很容易想像這兩個方法互為逆過程,理解了其中一個也就能知道另一個所做的工作。 TStream function ReadComponent(Instance: TComponent: TComponent;procedure WriteComponent(Instance: TComponent;TStream.ReadComponent 創(chuàng)建了一個 TReader 對象,將自己的對象地址作為參數(shù)傳遞給 Reader ,并調(diào)用 Reader.ReadRootCo
29、mponent 創(chuàng)建對象實例。function TStream.ReadComponent(Instance: TComponent: TComponent;varReader: TReader;beginReader := TReader.Create(Self, 4096; / 4096 是緩沖區(qū)大小Result := Reader.ReadRootComponent(Instance;Reader.Free;end;TStream 把自己的對象句柄交給 TReader 之后,就成了 TReader 讀取對象屬性資料的來源。此后 TStream 對象只由 TReader 來掌控,自己不再主
30、動進行其它工作。= TReader Class 和 TReader.ReadRootComponent 方法=TReader 和 TWriter 都是從 TFiler 繼承下來的類。TFiler 是個純虛類,它的構(gòu)造函數(shù)被 TReader 和 TWrite 共享。TFiler.Create 先把 Stream 參數(shù)保存在 FStream 字段中,然后生成一個自己的緩沖區(qū):constructor TFiler.Create(Stream: TStream; BufSize: Integer;beginFStream := Stream; / 保存 stream 對象GetMem(FBuffer,
31、 BufSize; / 創(chuàng)建自己的緩沖區(qū),加速數(shù)據(jù)訪問FBufSize := BufSize; / 設置緩沖區(qū)大小end;上面說到 TStream.ReadComponent 在創(chuàng)建 TReader 對象之后,立即調(diào)用TReader.ReadRootComponent 方法。TReader.ReadRootComponent 方法的功能是從 stream 中讀取 root class 對象的屬性。并返回該對象的指針。 TReader function ReadRootComponent(Root: TComponent: TComponent;ReadRootComponent 先調(diào)用 TRe
32、ader.ReadSignature 。TReader.ReadSignature 方法從 stream 中讀取 4 字節(jié)的內(nèi)容,如果讀出來的內(nèi)容不是 'TPF0' ,則觸發(fā)異常(SInvalidImage,表示該 stream 的內(nèi)容是錯誤的。'TPF0' 就是 root class 對象的標記。然后 ReadRootComponent 調(diào)用 ReadPrefix 讀取元件的繼承信息。如果 Root 參數(shù)是 nil ,也就是說 Root 對象還沒被創(chuàng)建,則直接從流中讀取 Root 的類名,再使用 FindClass 函數(shù)找到該類在內(nèi)存中的地址,并調(diào)用該類的構(gòu)造
33、函數(shù)創(chuàng)建 Root 的實例。如果 Root 實例已存在,則調(diào)用內(nèi)嵌的 FindUniquName 函數(shù)檢查 Root.Name 是否與已有的實例重復,如有重復則在 Root.Name 后加上序號使其唯一。接下來 ReadRootComponent 調(diào)用 Root 的 ReadState 虛方法從流中讀取 Root 對象的屬性。= TReader.ReadPrefix 方法=ReadPrefix 方法用于讀取元件的狀態(tài)信息,這些信息是由 Writer 在寫入元件屬性之前寫入的。 TReader procedure ReadPrefix(var Flags: TFilerFlags; var AC
34、hildPos: Integer; virtual;Flags 參數(shù)是以引用方式傳遞的,用于設置元件的在表單中的狀態(tài),元件的狀態(tài)在這里包含三種情況:ffInherited :表示元件存在于表單的父類之中ffChildPos :表示元件在表單中的創(chuàng)建次序(creation order是重要的ffInline :表示元件是最上級(top-level的元件,比如表單或數(shù)據(jù)模塊如果元件的狀態(tài)中包含 ffChildPos ,ReadPrefix 還會讀取元件的創(chuàng)建次序值,存放在 AChildPos 參數(shù)中。= TComponent.ReadState 虛方法=設置 ReadState 方法的主要目的是在
35、讀取屬性信息的前后可以讓元件進行一些處理工作。ReadState 是 Component Writer 需要注意的方法。 TComponent procedure ReadState(Reader: TReader; virtual;由于 ReadState 是虛函數(shù),在 TControl 、TWinControl 、TCustomForm 等后續(xù)類中都被重載,進行自己需要的操作(比如 DisableAlign 、UpdateControlState 。TComponent.ReadState 只有一行代碼:Reader.ReadData(Self;注意:自己重載 ReadState 方法必須
36、調(diào)用 inherited 。= TReader.ReadData 方法=上面說到 TComponent.ReadState 又回頭調(diào)用 TReader.ReadData 方法。它的主要代碼如下: TReader procedure TReader.ReadData(Instance: TComponent;begin.ReadDataInner(Instance;DoFixupReferences;.end;TReader.ReadData 基本上是個包裝函數(shù),它調(diào)用 TReader.ReadDataInner 讀取 root 對象及 root 所包含的元件的屬性信息。= TReader.Re
37、adDataInner 方法=ReadDataInner 負責讀取元件的屬性和子元件的屬性,它的主要代碼如下:procedure TReader.ReadDataInner(Instance: TComponent;begin.while not EndOfList do ReadProperty(Instance;.while not EndOfList do ReadComponent(nil;.end;ReadDataInner 先循環(huán)調(diào)用 ReadProperty 從流中讀取對象的屬性,直到遇到 EndOfList 標志(vaNull。再循環(huán)調(diào)用 ReadComponent(nil 讀
38、取子元件的信息。這兩個方法都是 TReader 的重要方法,后面分兩節(jié)討論。ReadDataInner 在ReadProperty 調(diào)用之后還設置了元件的 Parent 和 Owner 關系。= TReader.ReadProperty 方法=ReadProperty 使用 RTTI 函數(shù)將從流中讀出的數(shù)據(jù)設置為對象的屬性。它先解析從流中讀出的屬性名稱,然后判斷該屬性是否有 RTTI 信息,如果有則調(diào)用 TReader.ReadPropValue 方法從流中讀取屬性值;如果該屬性沒有 RTTI 信息,說明該屬性不屬于 published 段,而是由元件自己寫入的,因此調(diào)用 TPersisten
39、t.DefineProperties 讀取自定義的元件信息。ReadProperty 的關鍵代碼:procedure TReader.ReadProperty(AInstance: TPersistent;begin.PropInfo := GetPropInfo(Instance.ClassInfo, FPropName;if PropInfo <> nil then / 檢查屬性 RTTI 信息ReadPropValue(Instance, PropInfo / 從流中讀取屬性else beginInstance.DefineProperties(Self; / 調(diào)用自定義存儲
40、過程if FPropName <> '' then PropertyError(FPropName; / 注意這里end;.end;ReadPropValue 方法基本上是使用 SetOrdProp 、SetFloatProp 、SetStrProp 、GetEnumValue 等 RTTI 函數(shù)設置元件的屬性值,它的代碼冗長而簡單,不再單獨列出。下面介紹比較重要的DefineProperties 函數(shù)。= TPersistent.DefineProperties 虛方法=DefineProperties 虛方法用于元件設計者自定義非 published 屬性的存儲
41、和讀取方法。 TPersistent 定義的該方法是個空方法,到 TComponent 之后被重載。procedure TPersistent.DefineProperties(Filer: TFiler; virtual;下面以 TComponent 為例說明該方法的用法:procedure TComponent.DefineProperties(Filer: TFiler;varAncestor: TComponent;Info: Longint;beginInfo := 0;Ancestor := TComponent(Filer.Ancestor;if Ancestor <>
42、; 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;DefineProperties 調(diào)用 Filer.DefineProperty 或 Define
43、BinaryProperty 方法讀寫流中屬性值。TReader.DefineProperty 方法檢查傳入的屬性名稱是否與當前流中讀到的屬性名稱相同,如果相同,則調(diào)用傳入的 ReadData 方法讀取數(shù)據(jù),并設置 FPropName 為空,用以通知 ReadProperty 已經(jīng)完成讀屬性值的工作,否則將會觸發(fā)異常。procedure TReader.DefineProperty(const Name: string;ReadData: TReaderProc; WriteData: TWriterProc; HasData: Boolean;beginif SameText(Name, F
44、PropName and Assigned(ReadData thenbeginReadData(Self;FPropName := ''end;end;TWriter.DefineProperty 根據(jù) HasData 參數(shù)決定是否需要寫屬性值。procedure TWriter.DefineProperty(const Name: string;ReadData: TReaderProc; WriteData: TWriterProc; HasData: Boolean;beginif HasData and Assigned(WriteData thenbeginWrit
45、ePropName(Name;WriteData(Self;end;end;如果 Filer.Ancestor 不是 nil ,表示當前正在讀取的元件繼承自表單父類中的元件,元件設計者可以根據(jù) Ancestor 判斷是否需要寫屬性至流中。例如:當前元件的屬性值與原表單類中的元件屬性值相同的時候,可以不寫入(通常是這樣設計 。ReadData 、WriteData 參數(shù)是從 Filer 對象中讀寫數(shù)據(jù)的方法地址,它們的類型是:TReaderProc = procedure(Reader: TReader of object;TWriterProc = procedure(Writer: TWri
46、ter of object;比如:procedure TComponent.ReadLeft(Reader: TReader;beginLongRec(FDesignInfo.Lo := Reader.ReadInteger;end;procedure TComponent.WriteLeft(Writer: TWriter;beginWriter.WriteInteger(LongRec(FDesignInfo.Lo;end;對于二進制格式的屬性值,可以使用 TFiler.DefineBinaryProperty 方法讀寫:procedure DefineBinaryProperty(con
47、st Name: string;ReadData, WriteData: TStreamProc; HasData: Boolean; override;TStreamProc = procedure(Stream: TStream of object;Stream 參數(shù)是從流中讀出的二進制數(shù)據(jù)或要寫入二進制數(shù)據(jù)的流對象句柄。注意:自己定義屬性的讀寫方法時要記得調(diào)用 inherited DefineProperties(Filer,否則祖先類的自定義屬性讀寫操作不會進行。TControl 是個例外,因為它已經(jīng)定義了 published Left 和 Top 屬性。= TReader.ReadC
48、omponent 方法=ReadComponent 的執(zhí)行過程與 ReadRootComponent 的過程很相似,它根據(jù)流中的信息使用 FindComponentClass 方法找到元件類在內(nèi)存中的地址,然后調(diào)用該元件類的構(gòu)造函數(shù)創(chuàng)建對象,接下來調(diào)用新建對象的 ReadState -> TReader.ReadData -> ReadDataInner ->TReader.ReadProperty ,重復 ReadRootComponent 的過程。 TReader function ReadComponent(Component: TComponent: TCompone
49、nt;TReader.ReadComponent 和 TComponent.ReadState 形成遞歸調(diào)用過程,把表單上嵌套的元件創(chuàng)建出來。= TReader.ReadValue / TReader.NextValue 系列方法=ReadValue 方法從流中讀出一個 TValueType 類型的數(shù)據(jù),它主要由其它的方法調(diào)用。TValueType 中只有 vaList 比較特殊,它表示后面的數(shù)據(jù)是一個屬性值系列,以 vaNull 結(jié)束。其余的枚舉值的都是指屬性的數(shù)據(jù)類型或值。TValueType = (vaNull, vaList, vaInt8, vaInt16, vaInt32, vaE
50、xtended,vaString, vaIdent, vaFalse, vaTrue, vaBinary, vaSet, vaLString,vaNil, vaCollection, vaSingle, vaCurrency, vaDate, vaWString,vaInt64, vaUTF8String;function TReader.ReadValue: TValueType;beginRead(Result, SizeOf(Result;end;NextValue 方法調(diào)用 ReadValue 返回流中下一個數(shù)據(jù)的類型,然后將流指針回退至讀數(shù)據(jù)之前。通常用于檢測流中下一個數(shù)據(jù)的類型。function TReader.NextValue: TValueType;beginResult :=
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- GB/T 20840.10-2025互感器第10部分:低功率無源電流互感器的補充技術(shù)要求
- 度配件采購與供應合同
- 團購住宅合同轉(zhuǎn)讓權(quán)名額協(xié)議樣本
- 股權(quán)轉(zhuǎn)讓合同(四):不動產(chǎn)相關
- 婚姻終止財產(chǎn)分配合同
- 4 繁星教學設計-2024-2025學年四年級上冊語文統(tǒng)編版
- 詳盡版住宅租賃合同
- 藥店收購合同范本
- 3宿建德江教學設計-2024-2025學年六年級上冊語文統(tǒng)編版
- 藥品供應鏈合作合同
- 江蘇省2023年普通高校專轉(zhuǎn)本選拔考試計算機專業(yè)大類專業(yè)技能試卷及答案解析
- 2024年度(完整版)《各種各樣的天氣》課件
- 企業(yè)安全培訓課件-網(wǎng)絡與信息安全
- 設備采購 投標方案(技術(shù)方案)
- 越野車改裝方案
- 修辭手法在計算機語言學中的應用
- 消防工程維保方案三篇
- 高考一輪復習《文學類文本閱讀(小說)》教案
- 空間向量求線面角
- 閱讀與思考圓錐曲線的光學性質(zhì)及其應用課件
- 試產(chǎn)到量產(chǎn)項目轉(zhuǎn)移清單
評論
0/150
提交評論