Difference between revisions of "Streaming components"

From Free Pascal wiki
Jump to navigationJump to search
Line 12: Line 12:
  
 
'''TComponent''' extends TPersistent by the ability to have child components. This is important for streaming, where one component is the '''root component''' also called '''lookup root''' with a list of child components.
 
'''TComponent''' extends TPersistent by the ability to have child components. This is important for streaming, where one component is the '''root component''' also called '''lookup root''' with a list of child components.
 +
 +
== Writing your own component - Part 1 ==
 +
 +
A custom component can be as simple as:
 +
type
 +
  TMyComponent = class(TComponent)
 +
  private
 +
    FID: integer;
 +
  published
 +
    property ID: integer read FID write FID;
 +
  end;
 +
 +
== Using the Lazarus IDE to create a custom component ==
 +
 +
  
 
== Writing a component to a stream ==
 
== Writing a component to a stream ==

Revision as of 17:02, 23 February 2006

Introduction

Normally, when you want to store data on disk or to network streams, you must write code for loading and saving each property. This tutorial describes how to write classes, that can be loaded from and saved to streams without writing extra load/save code by using the RTTI.

There is an example in the lazarus sources, demonstrating how to save a TGroupBox with a TCheckBox child to a stream and read the stream back to create a copy of both components.

 See <lazaruspath>/examples/componentstreaming/

TComponent / TPersistent

The class TPersistent is defined in the unit Classes and is uses the {$M+} compiler switch. This switch tells the compiler to create Run Time Type Information (RTTI). This means it and all its descendants get a new class section published. 'Published' properties are visible as 'public', but additonally their structure is accessible at run time. That means all published properties can be read and written at run time. The IDE for instance uses this to work with components it never heard of.

TComponent extends TPersistent by the ability to have child components. This is important for streaming, where one component is the root component also called lookup root with a list of child components.

Writing your own component - Part 1

A custom component can be as simple as: type

 TMyComponent = class(TComponent)
 private
   FID: integer;
 published
   property ID: integer read FID write FID;
 end;

Using the Lazarus IDE to create a custom component

Writing a component to a stream

The unit LResources has a function for that:

 procedure WriteComponentAsBinaryToStream(AStream: TStream; AComponent: TComponent);

It writes a component in binary format to the stream. For example:

procedure TForm1.Button1Click(Sender: TObject);
var
  AStream: TMemoryStream;
begin
  AStream:=TMemoryStream.Create;
  try
    WriteComponentAsBinaryToStream(AStream,AGroupBox);
    ... save stream somewhere ...
  finally
    AStream.Free;
  end;
end;

Reading a component from a stream

The unit LResources has a function for that:

 procedure ReadComponentFromBinaryStream(AStream: TStream;
   var RootComponent: TComponent; OnFindComponentClass: TFindComponentClassEvent; TheOwner: TComponent = nil);
  • AStream is the stream containing a component in binary format.
  • RootComponent is either an existing component, which data will be overwritten, or it is nil and a new component will be created.
  • OnFindComponentClass is a function, that is used by TReader to get the class from the classnames in the stream. For example:
procedure TCompStreamDemoForm.OnFindClass(Reader: TReader;
  const AClassName: string; var ComponentClass: TComponentClass);
begin
  if CompareText(AClassName,'TGroupBox')=0 then
    ComponentClass:=TGroupBox
  else if CompareText(AClassName,'TCheckBox')=0 then
    ComponentClass:=TCheckBox;
end;
  • TheOwner is the component owner, when creating a new component.

Streamable properties

There are some limitations, what types TReader/TWriter can stream:

  • Base types can be streamed: string, integer, char, single, double, extended, byte, word, cardinal, shortint, etc. .
  • TPersistent and descendants can be streamed

Streaming custom Data - DefineProperties