📄 054.htm
字号:
<p>SetString(Result, PChar(nil), L);</p>
<p>Read(Pointer(Result)^, L);</p>
<p>end;</p>
<p></font> <font face="Arial"></p>
<p></font><font face="宋体" lang="ZH-CN">如果</font><font face="Arial">VaString</font><font
face="宋体" lang="ZH-CN">类型紧接着一个字节存有字符串的长度;如果是</font><font
face="Arial">VaLString</font><font face="宋体" lang="ZH-CN">类,则紧接着两个字节存放字符串长度,然后根据字符串长度用</font><font
face="Arial">SetString</font><font face="宋体" lang="ZH-CN">过程给分配空间,用</font><font
face="Arial">Read</font><font face="宋体" lang="ZH-CN">方法读出数据。</p>
<p> </font><font face="Arial">ReadFloat</font><font face="宋体" lang="ZH-CN">方法允许将整型值转换为浮点型。</p>
<p> </p>
<p></font><font face="Arial">function TReader.ReadFloat: Extended;</p>
<p>begin</p>
<p>if ReadValue = vaExtended then Read(Result, SizeOf(Result)) else</p>
<p>begin</p>
<p>Dec(FBufPos);</font><font face="宋体" lang="ZH-CN"></p>
<p></font><font face="Arial">Result := ReadInteger;</font><font face="宋体" lang="ZH-CN"></p>
<p></font><font face="Arial">end;</p>
<p>end;</p>
<p></font> <font face="Arial"></p>
<p></font><font face="宋体" lang="ZH-CN">字符类型数据设有直接的标志,它是根据</font><font
face="Arial">VaString</font><font face="宋体" lang="ZH-CN">后面放一个序值为</font><font
face="Arial">1</font><font face="宋体" lang="ZH-CN">的字节来判断的。</p>
<p> </p>
<p></font><font face="Arial">function TReader.ReadChar: Char;</p>
<p>begin</p>
<p>CheckValue(vaString);</p>
<p>Read(Result, 1);</p>
<p>if Ord(Result) <> 1 then</p>
<p>begin</p>
<p>Dec(FBufPos);</p>
<p>ReadStr;</p>
<p>PropValueError;</p>
<p>end;</p>
<p>Read(Result, 1);</p>
<p>end;</p>
<p></font> <font face="Arial"></p>
<p></font><font face="宋体" lang="ZH-CN">出于读取</font><font face="Arial">DFM</font><font
face="宋体" lang="ZH-CN">文件需要,</font><font face="Arial">Filer</font><font
face="宋体" lang="ZH-CN">对象支持读取标识符。</p>
<p> </p>
<p></font><font face="Arial">function TReader.ReadIdent: string;</p>
<p>var</p>
<p>L: Byte;</p>
<p>begin</p>
<p>case ReadValue of</p>
<p>vaIdent:</p>
<p>begin</p>
<p>Read(L, SizeOf(Byte));</p>
<p>SetString(Result, PChar(nil), L);</p>
<p>Read(Result[1], L);</p>
<p>end;</p>
<p>vaFalse:</p>
<p>Result := 'False';</p>
<p>vaTrue:</p>
<p>Result := 'True';</p>
<p>vaNil:</p>
<p>Result := 'nil';</p>
<p>else</p>
<p>PropValueError;</p>
<p>end;</p>
<p>end;</p>
<p></font> <font face="Arial"></p>
<p></font><font face="宋体" lang="ZH-CN">一般说来,各种复杂的数据结构都是由这些简单数据组成</font><font
face="Arial">;</font><font face="宋体" lang="ZH-CN">定义了这些方法等于给读各种类型的数据提供了元操作,使用很方便。例如,读取字符串类型的数据时,如果采用传流方法还要判断字符串的长度,使用</font><font
face="Arial">ReadString</font><font face="宋体" lang="ZH-CN">方法就不同了。但应该特别注意的是这些类型数据的存储格式是由</font><font
face="Arial">Delphi</font><font face="宋体" lang="ZH-CN">设计的与简单数据类型有明显的不同。因此,存入数据时应当使用</font><font
face="Arial">Writer</font><font face="宋体" lang="ZH-CN">对象相应的方法,而且在读数据前要用</font><font
face="Arial">NextValue</font><font face="宋体" lang="ZH-CN">方法进行判断,否则会触发异常事件。</p>
<p> </font><font face="Arial">6. </font><font face="宋体" lang="ZH-CN">读取部件的方法的实现</p>
<p> </font><font face="Arial">Reader</font><font face="宋体" lang="ZH-CN">对象中用于读取部件的方法有</font><font
face="Arial">ReadSignature</font><font face="宋体" lang="ZH-CN">、</font><font
face="Arial">ReadPrefix</font><font face="宋体" lang="ZH-CN">、</font><font
face="Arial">ReadComponent</font><font face="宋体" lang="ZH-CN">、</font><font
face="Arial">ReadRootComponent</font><font face="宋体" lang="ZH-CN">和</font><font
face="Arial">ReadComponents</font><font face="宋体" lang="ZH-CN">。</font><font
face="Arial"></p>
<p>ReadSignature</font><font face="宋体" lang="ZH-CN">方法主要用于读取</font><font
face="Arial">Delphi Filer</font><font face="宋体" lang="ZH-CN">对象标签一般在读取部件前,都要用调用</font><font
face="Arial">ReadSignature</font><font face="宋体" lang="ZH-CN">方法以指导部件读写过程。</p>
<p> </p>
<p></font><font face="Arial">procedure TReader.ReadSignature;</p>
<p>var</p>
<p>Signature: Longint;</p>
<p>begin</p>
<p>Read(Signature, SizeOf(Signature));</p>
<p>if Signature <> Longint(FilerSignature) then ReadError(SInvalidImage);</p>
<p>end;</p>
<p></font> <font face="Arial"></p>
<p>FilerSignature</font><font face="宋体" lang="ZH-CN">就是</font><font face="Arial">Filer</font><font
face="宋体" lang="ZH-CN">对象标签其值为“</font><font face="Arial">TPF0</font><font
face="宋体" lang="ZH-CN">”</font><font face="Arial"> </font><font face="宋体"
lang="ZH-CN">,如果读的不是“</font><font face="Arial">TPF0</font><font
face="宋体" lang="ZH-CN">”</font><font face="Arial"> </font><font face="宋体"
lang="ZH-CN">,则会触发</font><font face="Arial">SInValidImage</font><font
face="宋体" lang="ZH-CN">异常事件。</p>
<p> </font><font face="Arial">ReadPrefix</font><font face="宋体" lang="ZH-CN">方法是用于读取流中部件前的标志位,该标志表示该部件是否处于从祖先窗体中继承的窗体中和它在窗体中的位置是否很重要。</p>
<p> </p>
<p></font><font face="Arial">procedure TReader.ReadPrefix(var Flags: TFilerFlags; var
AChildPos: Integer);</p>
<p>var</p>
<p>Prefix: Byte;</p>
<p>begin</p>
<p>Flags := [];</p>
<p>if Byte(NextValue) and $F0 = $F0 then</p>
<p>begin</p>
<p>Prefix := Byte(ReadValue);</p>
<p>Byte(Flags) := Prefix and $0F;</p>
<p>if ffChildPos in Flags then AChildPos := ReadInteger;</p>
<p>end;</p>
<p>end;</p>
<p></font> <font face="宋体" lang="ZH-CN"></p>
<p> </font><font face="Arial">TFilerFlags</font><font face="宋体" lang="ZH-CN">的定义是这样的:</p>
<p> </p>
<p> </font><font face="Arial">TFilerFlag = (ffInherited, ffChildPos); </p>
<p>TFilerFlags = Set of TFilerFlag; </p>
<p></font> <font face="Arial"></p>
<p></font><font face="宋体" lang="ZH-CN">充当标志的字节的高四位是</font><font
face="Arial">$F</font><font face="宋体" lang="ZH-CN">,低四位是集合的值,也是标志位的真正含义。如果</font><font
face="Arial">ffChildPos</font><font face="宋体" lang="ZH-CN">置位,则紧接着的整型数字中放着部件在窗体中的位置序值。</p>
<p> </font><font face="Arial">ReadComponent</font><font face="宋体" lang="ZH-CN">方法用于从</font><font
face="Arial">Reader</font><font face="宋体" lang="ZH-CN">对象的流中读取部件。</font><font
face="Arial">Component </font><font face="宋体" lang="ZH-CN">参数指定了要从流中读取的对象。函数返回所读的部件。</p>
<p> </p>
<p></font><font face="Arial">function TReader.ReadComponent(Component: TComponent):
TComponent;</p>
<p>var</p>
<p>CompClass, CompName: string;</p>
<p>Flags: TFilerFlags;</p>
<p>Position: Integer;</p>
<p></font><font face="宋体" lang="ZH-CN">…</p>
<p> </p>
<p></font><font face="Arial">begin</p>
<p>ReadPrefix(Flags, Position);</p>
<p>CompClass := ReadStr;</font><font face="宋体" lang="ZH-CN"></p>
<p></font><font face="Arial">CompName := ReadStr;</font><font face="宋体" lang="ZH-CN"></p>
<p></font><font face="Arial">Result := Component;</p>
<p>if Result = nil then</p>
<p>if ffInherited in Flags then</p>
<p>FindExistingComponent else</p>
<p>CreateComponent;</p>
<p>if Result <> nil then</p>
<p>try</p>
<p>Include(Result.FComponentState, csLoading);</p>
<p>if not (ffInherited in Flags) then SetCompName;</p>
<p>if Result = nil then Exit;</p>
<p>Include(Result.FComponentState, csReading);</p>
<p>Result.ReadState(Self);</p>
<p>Exclude(Result.FComponentState, csReading);</p>
<p>if ffChildPos in Flags then Parent.SetChildOrder(Result, Position);</p>
<p>FLoaded.Add(Result);</p>
<p>except</p>
<p>if ComponentCreated then Result.Free;</p>
<p>raise;</p>
<p>end;</p>
<p>end;</p>
<p></font> <font face="Arial"></p>
<p>ReadCompontent</font><font face="宋体" lang="ZH-CN">方法首先调用</font><font
face="Arial">ReadPrefix</font><font face="宋体" lang="ZH-CN">方法,读出部件标志位和它的创建次序值</font><font
face="Arial">(Create Order)</font><font face="宋体" lang="ZH-CN">。然后用</font><font
face="Arial">ReadStr</font><font face="宋体" lang="ZH-CN">方法分别读出部件类名和部件名。如果</font><font
face="Arial">Component</font><font face="宋体" lang="ZH-CN">参数为</font><font
face="Arial">nil</font><font face="宋体" lang="ZH-CN">,则执行两个任务:</font><font
face="Arial"></p>
<p></font><font face="宋体" lang="ZH-CN">●</font><font face="Arial"> </font><font
face="宋体" lang="ZH-CN">如果</font><font face="Arial">ffInberited </font><font
face="宋体" lang="ZH-CN">置位则从</font><font face="Arial">Root </font><font
face="宋体" lang="ZH-CN">找已有部件,否则,就从系统的</font><font
face="Arial">Class</font><font face="宋体" lang="ZH-CN">表中找到该部件类型的定义并创建</font><font
face="Arial"></p>
<p></font><font face="宋体" lang="ZH-CN">●</font><font face="Arial"> </font><font
face="宋体" lang="ZH-CN">如果结果不为空,将用部件的</font><font
face="Arial">ReadState</font><font face="宋体" lang="ZH-CN">方法读入各种属性值,并设置部件的</font><font
face="Arial">Parent </font><font face="宋体" lang="ZH-CN">属性,并恢复它在</font><font
face="Arial">Parent</font><font face="宋体" lang="ZH-CN">部件的创建次序。</p>
<p> </p>
<p> </font><font face="Arial">ReadComponent</font><font face="宋体" lang="ZH-CN">方法主要是调用</font><font
face="Arial">ReadComponent</font><font face="宋体" lang="ZH-CN">方法从</font><font
face="Arial">Reader</font><font face="宋体" lang="ZH-CN">对象的流中读取一连串相关联的部件,并分解相互引用关系。</p>
<p> </p>
<p></font><font face="Arial">procedure TReader.ReadComponents(AOwner, AParent: TComponent;</p>
<p>Proc: TReadComponentsProc);</p>
<p>var</p>
<p>Component: TComponent;</p>
<p>begin</p>
<p>Root := AOwner;</p>
<p>Owner := AOwner;</p>
<p>Parent := AParent;</p>
<p>BeginReferences;</p>
<p>try</p>
<p>while not EndOfList do</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -