VCL源码理解

1.TWriter对象

WriteBuffer是TWriter对象定义的私有方法,它的作用是将Writer 对象内部缓冲区中的有效数据写入流中,并将FBufPos置为0。FlushBuffer对象就是用WriteBuffer方法刷新缓冲区。
procedure TWriter.WriteBuffer;
begin
  FStream.WriteBuffer(FBuffer^, FBufPos);
  FBufPos := 0;
end;

 

在SetPosition方法中,如果Value值超出了边界(FStream.Position,FStream.Position + FBufPos),就将缓冲区中的内容写入流,重新设置缓冲区在流中的相对位置;否则,就只是移动FBufPos指针。

procedure TWriter.SetPosition(Value: Longint);
var
StreamPosition: Longint;
begin
StreamPosition := FStream.Position;
{ 只清除越界的缓冲区 }
if (Value < StreamPosition) or (Value > StreamPosition + FBufPos) then
begin
WriteBuffer;
FStream.Position := Value;
end
else FBufPos := Value - StreamPosition;
end; 

 

WriteListBegin和WriteListEnd的实现,WriteListBegin写入VaList标志,WriteListEnd写入VaNull标志。 两个方法都调用TWriter对象的WriteValue方法,该方法主要用于写入TValueType类型的值。

procedure TWriter.WriteValue(Value: TValueType);
begin
Write(Value, SizeOf(Value)); 
end;

procedure TWriter.WriteListBegin;
begin
WriteValue(vaList);
end;

procedure TWriter.WriteListEnd;
begin
WriteValue(vaNull);
end;

简单数据类型的写入
简单数据类型指的是整型、字符型、字符串型、浮点型、布尔型等。TWriter对象都定义了相应的写入方法。
WriteInteger方法将整型数据分为8位、16位和32位三种,并分别用vaInt8、vaInt16和VaInt32。

procedure TWriter.WriteInteger(Value: Longint);
begin
  if (Value >= -128) and (Value <= 127) then
  begin
     WriteValue(vaInt8);
     Write(Value, SizeOf(Shortint));
  end else
  if (Value >= -32768) and (Value <= 32767) then
  begin
  WriteValue(vaInt16);
  Write(Value, SizeOf(Smallint));
  end else
   begin
     WriteValue(vaInt32);
     Write(Value, SizeOf(Longint));
     end;
end;

 

与其它数据类型不同的是布尔型数据只使用了标志位是存储布尔值,在标志位后没有数据。字符串“True”、“False”和“nil”作为标识符传入是由于Delphi的特殊需要。如果是“True”、“False”和“nil”则写入VaTrue、VaFalse和VaNil,否则写入VaIdent标志,接着以字符串形式写入标识符。procedure TWriter.WriteFloat(Value: Extended);
begin
WriteValue(vaExtended);
Write(Value, SizeOf(Extended));
end;

 

 
WriteString方法用于写入字符串 .Delphi的字符串类型有两种。一种长度小于256个字节,另一种长度小于65536 个字节。WriteString方法区分这两类情况存储字符串,一种设置VaStirng标志,另一种设置VaLString。然后存储字符串的长度值,最后存储字符串数据。

procedure TWriter.WriteString(const Value: string);
var
L: Integer;
begin
L := Length(Value);
if L <= 255 then
begin
WriteValue(vaString);
Write(L, SizeOf(Byte));
end else
begin
WriteValue(vaLString);
Write(L, SizeOf(Integer));
end;
Write(Pointer(Value)^, L);
end;
 
部件的写入:

TWriter对象中与写入部件有关的方法有WriteSignature、WritePrefix、WriteComponent、WriteDescendant和WriteRootComponent。 
procedure TWriter.WriteSignature; //WriteSignature方法用于往流中写入Filer对象标签。FilerStgnature是字符串常量,其值为“TPF0”,代表对象标签。
begin
Write(FilerSignature, SizeOf(FilerSignature));
end;

WritePrefix方法用于在写入部件前写入ffInherited和ffChildPos标志,这些标志表示部件的继承特征和创建序值特征。 
procedure TWriter.WritePrefix(Flags: TFilerFlags; AChildPos: Integer);
var
Prefix: Byte;
begin
  if Flags <> [] then
  begin
      Prefix := $F0 or Byte(Flags);
      Write(Prefix, SizeOf(Prefix));
     if ffChildPos in Flags then WriteInteger(AChildPos); //如果ffChildPos置位,则存入部件在Owner中的创建序值

 end;
end;


WriteComponent方法往流中写入部件。

procedure TWriter.WriteComponent(Component: TComponent);

  function FindAncestor(const Name: string): TComponent;
  begin

  end;

var
  OldAncestor: TPersistent;
  OldRootAncestor: TComponent;
  AncestorComponent: TComponent;
  I: Integer;
begin
  OldAncestor := Ancestor;
  OldRootAncestor := RootAncestor;
  try
    Include(Component.FComponentState, csWriting); //将控件的FComponentState置为csWriting
    for I := 0 to Component.ComponentCount - 1 do //将其所拥有的控件的FComponentState置为csWriting
      if csSubComponent in Component.Components[I].ComponentStyle then
        Include(Component.Components[I].FComponentState, csWriting);
       
    if Assigned(FAncestorList) then
      Ancestor := FindAncestor(Component.Name);
    if Assigned(FOnFindAncestor) and ((Ancestor = nil) or
    (Ancestor is TComponent)) then
    begin
      AncestorComponent := TComponent(Ancestor);
      FOnFindAncestor(Self, Component, Component.Name, AncestorComponent,
        FRootAncestor);
      Ancestor := AncestorComponent;
    end;
    Component.WriteState(Self); //写入属性
   
    Exclude(Component.FComponentState, csWriting);//写入完后再将csWriting复位
    for I := 0 to Component.ComponentCount - 1 do
      if csSubComponent in Component.Components[I].ComponentStyle then
        Exclude(Component.Components[I].FComponentState, csWriting);
  finally
    Ancestor := OldAncestor;
    FRootAncestor := OldRootAncestor;
  end;
end;

 

procedure TWriter.WriteRootComponent(Root: TComponent);//将Ancestor参数以nil值传入,调用WriteDescendant方法写入部件
begin
  WriteDescendent(Root, nil);
end;

 

 

//先调用WriteSignature方法写入Filer对象标签。然后调用WriteComponent将部件Root写入流
procedure TWriter.WriteDescendent(Root: TComponent; AAncestor: TComponentbegin);
  FRootAncestor := AAncestor;
  FAncestor := AAncestor;
  FRoot := Root;
  FLookupRoot := Root;
  WriteSignature;
  WriteComponent(Root);
end;

procedure TStream.WriteDescendent(Instance, Ancestor: TComponent); //创建了TWriter对象,然后利用TWriter的WriteDescendant方法将Instance写入流。
var
  Writer: TWriter;
begin
  Writer := TWriter.Create(Self, 4096);
  try
    Writer.WriteDescendent(Instance, Ancestor);
  finally
    Writer.Free;
  end;
end;

 

流TStream

procedure TStream.WriteDescendent(Instance, Ancestor: TComponent); //创建了TWriter对象,然后利用TWriter的WriteDescendant方法将Instance写入流。
var
  Writer: TWriter;
begin
  Writer := TWriter.Create(Self, 4096);
  try
    Writer.WriteDescendent(Instance, Ancestor);
  finally
    Writer.Free;
  end;
end;

procedure TStream.WriteComponent(Instance: TComponent); //WriteComponent方法只是简单地调用WriteDescendant方法将Instance写入流
begin
  WriteDescendent(Instance, nil);
end;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值