2005. március 6., vasárnap

How to save components to a file or stream


Problem/Question/Abstract:

I have a component TZzz (descends from TComponent) and I want to implement some saving/ restoring capabilities for it. Here's my point. I want to place a TZzz component in a form and export this object to a file. Later, I want import that file to another TZzz object in another form (only for copying the properties from one object to another). Any ideas?

Answer:

Here is a component I wrote which I use often. Simply derive from TPersistentComponent and you can then stream it in and out either directly to a stream or to a file as well. You will have to implement the FindMethod method yourself.

unit Unit1;

interface

uses
  Classes, Sysutils;

const
  cFileDoesNotExist = 'File Does Not Exist %0s';
  cDefaultBufSize = 4096;

type
  TPersistComponent = class(TComponent)

  private
    FStreamLoad: Boolean;
  protected
    property StreamLoad: Boolean read FSTreamLoad;
    procedure FindMethod(Reader: TReader; const MethodName: string; var Address:
      Pointer;
      var Error: Boolean); virtual;
  public
    procedure LoadFromFile(const FileName: string; const Init: Boolean = False);
      virtual;
    procedure SaveToFile(const FileName: string); virtual;
    procedure LoadFromStream(Stream: TStream); virtual;
    procedure SaveToStream(Stream: TStream); virtual;
  end;

implementation

procedure TPersistComponent.FindMethod(Reader: TReader; const MethodName: string;
  var Address: Pointer; var Error: Boolean);
begin
  Error := False;
end;

procedure TPersistComponent.LoadFromFile(const FileName: string; const Init: Boolean =
  False);
var
  FS: TFileStream;
begin
  if FileExists(Filename) then
  begin
    FS := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
    try
      LoadFromStream(FS);
    finally
      FS.Free;
    end;
  end
  else
    raise Exception.CreateFmt(cFileDoesNotExist, [FileName]);
end;

procedure TPersistComponent.LoadFromStream(Stream: TStream);
var
  Reader: TReader;
begin
  Reader := TReader.Create(Stream, cDefaultBufSize);
  try
    {Reader.OnFindMethod := FindMethod;}
    FStreamLoad := True;
    Reader.OnFindMethod := FindMethod;
    Reader.BeginReferences;
    Reader.Root := Owner;
    Reader.ReadComponent(Self);
    Reader.EndReferences;
    Loaded;
  finally
    FStreamLoad := False;
    Reader.Free;
  end;
end;

procedure TPersistComponent.SaveToFile(const FileName: string);
var
  FS: TFileStream;
begin
  FS := TFileStream.Create(FileName, fmCreate);
  try
    SaveToStream(FS);
  finally
    FS.Free;
  end;
end;

procedure TPersistComponent.SaveToStream(Stream: TStream);
var
  Writer: TWriter;
begin
  Writer := TWriter.Create(Stream, cDefaultBufSize);
  try
    Writer.Root := Owner;
    Writer.WriteComponent(Self);
  finally
    Writer.Free;
  end;
end;

end.

Nincsenek megjegyzések:

Megjegyzés küldése