Ver Mensaje Individual
  #4  
Antiguo 06-10-2005
rounin rounin is offline
Miembro
 
Registrado: sep 2005
Posts: 43
Reputación: 0
rounin Va por buen camino
Procedures Stream.WriteComponent and ReadComponent are
purposed for deal mainly with Root components (Form, DataModule, ...).

Somewhen I was experimenting with components
and wrote procedures for read/write
non-root components from stream:

Código Delphi [-]
 
 
{*******************************************************************************
* *
* Reonid sources *
* Categoty: other *
* (c) reonid@yahoo.com *
* *
*******************************************************************************}
unit Comp2Stm;
interface
uses
Classes, Controls;
 
function LoadComponentFromStream(ARoot, AOwner: TComponent; AParent: TWinControl;
SrcTxtStream: TStream; AComp: TComponent = nil): TComponent;
 
procedure SaveComponentToStream(AComp, ARoot: TComponent; DestTxtStream: TStream);
 
implementation
 
type
TDummy = class
class procedure ReaderSetName(Reader: TReader; Component: TComponent; var Name: string);
end;
 
class procedure TDummy.ReaderSetName(Reader: TReader; Component: TComponent; var Name: string);
begin
if (Reader.Owner <> nil) and
(Reader.Owner.FindComponent(Name) <> nil) then Name := '';
// The simplest way to resolve the name conflicts
end;
 
function LoadComponentFromStream(ARoot, AOwner: TComponent; AParent: TWinControl;
SrcTxtStream: TStream; AComp: TComponent = nil): TComponent;
var
BinStream: TStream;
Reader: TReader;
Comp: TComponent;
begin
BinStream := TMemoryStream.Create;
try
Reader := TReader.Create(BinStream, 4096);
 
//SrcTxtStream.Position := 0;
ObjectTextToBinary(SrcTxtStream, BinStream);
try
Reader.Position := 0;
Reader.Owner := AOwner;
Reader.Parent := AParent;
Reader.Root := ARoot;
// Owner, Parent and Root for new Component
// Reader will search in RTTI-tables of the Root component 
// classes and event handlers etc.
 
Reader.OnSetName := TDummy.ReaderSetName;
// Äë˙ đŕçđĺřĺíč˙ ęîíôëčęňîâ čě¸í
// For the name conflicts resolution
 
//Reader.OnFindMethod := ;
//Reader.OnFindComponentClass := ;
 
Reader.BeginReferences;
try
Reader.ReadSignature;
Comp := Reader.ReadComponent(AComp);
Result := Comp;
Reader.FixupReferences;
// Initializes references on other components,
// that saved in DFM as names.
finally
Reader.EndReferences;
end;
finally
Reader.Free;
end;
finally
BinStream.Free;
end;
end;
 
procedure SaveComponentToStream(AComp, ARoot: TComponent; DestTxtStream: TStream);
var BinStream: TStream;
Writer: TWriter;
begin
BinStream := TMemoryStream.Create();
try
Writer := TWriter.Create(BinStream, 4096);
try
Writer.Root := ARoot;
Writer.WriteSignature;
Writer.WriteComponent(AComp);
Writer.WriteListEnd;
finally
Writer.Free;
end;
BinStream.Position := 0;
ObjectBinaryToText(BinStream, DestTxtStream);
finally
BinStream.Free;
end;
end;
 
end.

PS: When Reader reads a component from stream,
initially it reads the Class Name of the component.
Then (if the component has not been created before reading)
Reader tries to find the Class Reference by Class Name.

First, it searches the class in the RTTI-table of Root component.
If there is any component of the same class in the Root,
then success.

Second, the Reader searches the class in the
registered classes. If the class have been registered by
RegisterClass (RegisterClasses), then success.

Third, the Reader let user to resolve the Class Name
to the Class Reference by himself
(it calls OnFindComponentClass event handler).

If all this attempts have failed, the Reader raise EClassNotFound
"class <Class Name> not found".
Use RegisterClasses to solve it.

Última edición por rounin fecha: 06-10-2005 a las 14:23:22.
Responder Con Cita