📄 055.htm
字号:
<p>procedure ConvertObject;</p><p>begin</p><p></font><font face="宋体" lang="ZH-CN">…</p><p></font><font face="Arial">end;</p><p> </p><p>begin</p><p>NestingLevel := 0;</p><p>Reader := TReader.Create(Input, 4096);</p><p>SaveSeparator := DecimalSeparator;</p><p>DecimalSeparator := '.';</p><p>try</p><p>Writer := TWriter.Create(Output, 4096);</p><p>try</p><p>Reader.ReadSignature;</p><p>ConvertObject;</p><p>finally</p><p>Writer.Free;</p><p>end;</p><p>finally</p><p>DecimalSeparator := SaveSeparator; </p><p>Reader.Free;</p><p>end;</p><p>end;</p><p> </font><font face="宋体" lang="ZH-CN"></p><p> 过程中调用的</font><font face="Arial">ConvertObject</font><fontface="宋体" lang="ZH-CN">过程是个递归过程,用于将</font><font face="Arial">DFM</font><fontface="宋体" lang="ZH-CN">文件中的每一个部件转化为文本形式。因为由于部件的拥有关系,所以部件成嵌套结构,采用递归是最好的方式:</p><p> </p><p></font><font face="Arial">procedure ConvertObject;</p><p>begin</p><p>ConvertHeader;</p><p>Inc(NestingLevel);</p><p>while not Reader.EndOfList do ConvertProperty;</p><p>Reader.ReadListEnd;</p><p>while not Reader.EndOfList do ConvertObject;</p><p>Reader.ReadListEnd;</p><p>Dec(NestingLevel);</p><p>WriteIndent;</p><p>WriteStr('end'#13#10);</font><font face="宋体" lang="ZH-CN"></p><p></font><font face="Arial">end;</font><font face="宋体" lang="ZH-CN"></p><p> </p><p> </font><font face="Arial">NestStingLevel</font><font face="宋体" lang="ZH-CN">变量表示部件的嵌套层次。</font><fontface="Arial">WriteIndent</font><font face="宋体" lang="ZH-CN">是写入每一行起始字符前的空格,</font><fontface="Arial">ConvertHeader</font><font face="宋体" lang="ZH-CN">过程是处理部件的继承标志信息。转换成的头信息文本有两种形式。</font><fontface="Arial"></p><p></font><font face="宋体" lang="ZH-CN"> </font><font face="Arial">InheritedTestForm1: TTestForm[2]</font><font face="宋体" lang="ZH-CN"></p><p> 或者:</font><font face="Arial"></p><p>Object TestForm1: TTestForm</p><p> </p><p></font><font face="宋体" lang="ZH-CN">前者是</font><font face="Arial">ffInherited</font><fontface="宋体" lang="ZH-CN">和</font><font face="Arial">ffChildPos</font><fontface="宋体" lang="ZH-CN">置位,后面是都没置位。</p><p> </font><font face="Arial">ConvertProperty</font><font face="宋体" lang="ZH-CN">过程用于转化属性。</p><p> </p><p></font><font face="Arial">procedure ConvertProperty;</p><p>begin</p><p>WriteIndent;</p><p>WriteStr(Reader.ReadStr);</p><p>WriteStr(' = ');</p><p>ConvertValue;</p><p>WriteStr(#13#10);</p><p>end;</p><p> </font><font face="宋体" lang="ZH-CN"></p><p> </font><font face="Arial">WriteIndent</font><font face="宋体" lang="ZH-CN">语句写入属性名前的空格,</font><fontface="Arial">WriteStr(Reader.ReadStr)</font><font face="宋体" lang="ZH-CN">语句写入属性名</font><fontface="Arial">ConvertValue</font><font face="宋体" lang="ZH-CN">过程根据属性的类型将属性值转化为字符串,然后写入流中。</p><p> </font><font face="Arial">ObjectTextToBinary</font><font face="宋体"lang="ZH-CN">过程执行的功能与</font><font face="Arial">ObjectBinaryToText</font><fontface="宋体" lang="ZH-CN">相反,将</font><font face="Arial">TXT</font><fontface="宋体" lang="ZH-CN">文件转换为二进制流中的部件,而且只要</font><fontface="Arial">TXT</font><font face="宋体" lang="ZH-CN">文件内容的书写符合</font><fontface="Arial">DFM</font><font face="宋体" lang="ZH-CN">脚本语法,</font><fontface="Arial">ObjectTextToBinary</font><font face="宋体" lang="ZH-CN">可将任何程序生成的</font><fontface="Arial">TXT</font><font face="宋体" lang="ZH-CN">文件转换为部件,这一功能也为</font><fontface="Arial">DFM </font><font face="宋体" lang="ZH-CN">文件的动态生成和编辑奠定了基础。</font><fontface="Arial">ObjectTextToBinary</font><font face="宋体" lang="ZH-CN">过程的主程序如下:</p><p> </p><p></font><font face="Arial">procedure ObjectTextToBinary(Input, Output: TStream);</p><p>var</p><p>SaveSeparator: Char;</p><p>Parser: TParser;</p><p>Writer: TWriter;</p><p> </p><p></font><font face="宋体" lang="ZH-CN"> </font><font face="Arial"> </font><fontface="宋体" lang="ZH-CN">…</font><font face="Arial"></p><p></font><font face="宋体" lang="ZH-CN"> </p><p></font><font face="Arial">begin</p><p>Parser := TParser.Create(Input);</p><p>SaveSeparator := DecimalSeparator;</p><p>DecimalSeparator := '.';</p><p>try</p><p>Writer := TWriter.Create(Output, 4096);</p><p>try</p><p>Writer.WriteSignature;</p><p>ConvertObject;</p><p>finally</p><p>Writer.Free;</p><p>end;</p><p>finally</p><p>DecimalSeparator := SaveSeparator;</p><p>Parser.Free;</font><font face="宋体" lang="ZH-CN"></p><p></font><font face="Arial">end;</font><font face="宋体" lang="ZH-CN"></p><p></font><font face="Arial">end;</p><p> </font><font face="宋体" lang="ZH-CN"></p><p> 在程序流程和结构上与</font><font face="Arial">ObjectBinaryToText</font><fontface="宋体" lang="ZH-CN">差不多。</font><font face="Arial">ConvertObject</font><fontface="宋体" lang="ZH-CN">也是个递归过程:</p><p> </p><p></font><font face="Arial">procedure ConvertObject;</p><p>var</p><p>InheritedObject: Boolean;</p><p>begin</p><p>InheritedObject := False;</p><p>if Parser.TokenSymbolIs('INHERITED') then</p><p>InheritedObject := True </p><p>else</p><p>Parser.CheckTokenSymbol('OBJECT');</p><p>Parser.NextToken;</p><p>ConvertHeader(InheritedObject);</p><p>while not Parser.TokenSymbolIs('END') and</p><p>not Parser.TokenSymbolIs('OBJECT') and</p><p>not Parser.TokenSymbolIs('INHERITED') do ConvertProperty;</p><p>Writer.WriteListEnd;</p><p>while not Parser.TokenSymbolIs('END') do ConvertObject;</p><p>Writer.WriteListEnd;</p><p>Parser.NextToken;</p><p>end;</p><p> </font><font face="宋体" lang="ZH-CN"></p><p> </font><font face="Arial">DFM</font><font face="宋体" lang="ZH-CN">文件与</font><fontface="Arial">DFM</font><font face="宋体" lang="ZH-CN">脚本语言之间相互转换的任务由</font><fontface="Arial">ObjectResourceToText</font><font face="宋体" lang="ZH-CN">和</font><fontface="Arial">ObjextTextToResource</font><font face="宋体" lang="ZH-CN">两个过程完成。</p><p> </p><p></font><font face="Arial">procedure ObjectResourceToText(Input, Output: TStream);</p><p>begin</p><p>Input.ReadResHeader;</p><p>ObjectBinaryToText(Input, Output);</p><p>end;</p><p> </p><p>ObjectTextToResource</font><font face="宋体" lang="ZH-CN">过程就比较复杂,因为</font><fontface="Arial">DFM</font><font face="宋体" lang="ZH-CN">文件资源头中要包含继承标志信息,因此在调用</font><fontface="Arial">ObjectTextToBinary</font><font face="宋体" lang="ZH-CN">后,就读取标志信息,然后写入资源头。</p><p> </p><p></font><font face="Arial">procedure ObjectTextToResource(Input, Output: TStream);</p><p>var</p><p>Len: Byte;</p><p>Tmp: Longint;</p><p>MemoryStream: TMemoryStream;</p><p>MemorySize: Longint;</p><p>Header: array[0..79] of Char;</p><p>begin</p><p>MemoryStream := TMemoryStream.Create;</p><p>try</font><font face="宋体" lang="ZH-CN"></p><p></font><font face="Arial">ObjectTextToBinary(Input, MemoryStream);</font><fontface="宋体" lang="ZH-CN"></p><p></font><font face="Arial">MemorySize := MemoryStream.Size;</p><p>FillChar(Header, SizeOf(Header), 0);</p><p>MemoryStream.Position := SizeOf(Longint); { Skip header }</p><p>MemoryStream.Read(Len, 1);</p><p>if Len and $F0 = $F0 then</p><p>begin</p><p>if ffChildPos in TFilerFlags((Len and $F0)) then</p><p>begin</p><p>MemoryStream.Read(Len, 1);</p><p>case TValueType(Len) of</p><p>vaInt8: Len := 1;</p><p>vaInt16: Len := 2;</p><p>vaInt32: Len := 4;</p><p>end;</p><p>MemoryStream.Read(Tmp, Len);</p><p>end;</p><p>MemoryStream.Read(Len, 1);</p><p>end;</p><p>MemoryStream.Read(Header[3], Len);</p><p>StrUpper(@Header[3]);</p><p>Byte((@Header[0])^) := $FF;</p><p>Word((@Header[1])^) := 10;</p><p>Word((@Header[Len + 4])^) := $1030;</p><p>Longint((@Header[Len + 6])^) := MemorySize;</p><p>Output.Write(Header, Len + 10);</p><p>Output.Write(MemoryStream.Memory^, MemorySize);</p><p>finally</p><p>MemoryStream.Free;</p><p>end;</p><p>end;</p><p> </p><p>20.3.1.5 </font><font face="宋体" lang="ZH-CN">动态</font><font face="Arial">DFM</font><fontface="宋体" lang="ZH-CN">文件应用揭秘</p><p> </p><p> </font><font face="Arial">1. </font><font face="宋体" lang="ZH-CN">动态</font><fontface="Arial">DFM</font><font face="宋体" lang="ZH-CN">文件概述</font><fontface="Arial"></p><p></font><font face="宋体" lang="ZH-CN">动态</font><font face="Arial">DFM</font><fontface="宋体" lang="ZH-CN">文件是相对于静态</font><font face="Arial">DFM</font><fontface="宋体" lang="ZH-CN">文件而言。所谓静态</font><font face="Arial">DFM</font><fontface="宋体" lang="ZH-CN">文件是指在</font><font face="Arial">Delphi</font><fontface="宋体" lang="ZH-CN">开发环境中设计的窗体文件。窗体的设计过程就是程序的编制过程。因此,动态</font><fontface="Arial">DFM</font><font face="宋体" lang="ZH-CN">文件就是指在程序运行过程生成或存取的</font><fontface="Arial">DFM</font><font face="宋体" lang="ZH-CN">文件。</p><p> 动态</font><font face="Arial">DFM</font><font face="宋体" lang="ZH-CN">文件的创建和使用分别如下两种情况:</p><p> ●</font><font face="Arial"> </font><font face="宋体" lang="ZH-CN">在程序运行过程中,由</font><fontface="Arial">Create</font><font face="宋体" lang="ZH-CN">方法动态生成窗体或部件,然后动态生成其它部件插入其中生成</font><fontface="Arial">DFM</font><font face="宋体" lang="ZH-CN">文件</p><p> ●</font><font face="Arial"> </font><font face="宋体" lang="ZH-CN">在</font><fontface="Arial">Delphi</font><font face="宋体" lang="ZH-CN">开发环境中,设计生成</font><fontface="Arial">DFM</font><font face="宋体" lang="ZH-CN">文件,然后用</font><fontface="Arial">DFM </font><font face="宋体" lang="ZH-CN">文件存取函数,或者用</font><fontface="Arial">Stream</font><font face="宋体" lang="ZH-CN">对象和</font><fontface="Arial">Filer</font><font face="宋体" lang="ZH-CN">对象的方法,将</font><fontface="Arial">DFM</font><font face="宋体" lang="ZH-CN">文件读入内存,进行处理,最后又存入磁盘中</p><p> </p><p> 由</font><font face="Arial">Delphi</font><font face="宋体" lang="ZH-CN">的窗体设计的常规方法生成的</font><fontface="Arial">DFM</font><font face="宋体" lang="ZH-CN">文件在程序运行一开始就规定了部件的结构。因为在窗体设计过程中,窗体中的每个部件都在程序的对象声明中定义了部件变量。这种固定的结构虽然能方便应用,但以牺牲灵活性为代价。</p><p> 在</font><font face="Arial">Delphi</font><font face="宋体" lang="ZH-CN">应用程序中有时需要在运行过程中创建控制,然后将该控制插入另一个部件中。例如:</font><fontface="Arial"></p><p> </p><p>procedure TForm1.Button1Click(Sender: Tobject);</p><p>var</p><p>Ctrl: TControl</p><p>begin</p><p>Ctrl := TEdit.Create(Self);</p><p>Ctrl.Top := 100;</p><p>Ctrl.Left := 100;</p><p>Ctrl.Width := 150;</p><p>Ctrl.Height := 20; </p><p>InsertControl(Ctrl);</p><p>end;</p><p> </font><font face="宋体" lang="ZH-CN"></p><p> 动态插入控制的优点是可以在任何时刻、任意位置插入任意数量的任何类型的控制。因为应用程序需求在很多情况下是在程序运行中才知道的,所以动态插入控制就显得很重要。而且在很多情况下,需要保存这些界面元素,留待程序再次调用。例如应用程序界面的定制、系统状态的保存、对话框的保存等。这时生成动态</font><font
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -