I made program according to these instructions. Works great, but I do not know why.
http://docwiki.embarcadero.com/CodeExamples/XE3/en/ComponentToString_(Delphi).
My code is:
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ExtCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Image1: TImage;
Image2: TImage;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
function ComponentToStringProc(Component: TComponent): string;
var
BinStream:TMemoryStream;
StrStream: TStringStream;
s: string;
begin
BinStream := TMemoryStream.Create;
try
StrStream := TStringStream.Create(s);
try
BinStream.WriteComponent(Component);
BinStream.Seek(0, soFromBeginning);
ObjectBinaryToText(BinStream, StrStream);
StrStream.Seek(0, soFromBeginning);
Result:= StrStream.DataString;
finally
StrStream.Free;
end;
finally
BinStream.Free
end;
end;
function StringToComponentProc(Value: string): TComponent;
var
StrStream:TStringStream;
BinStream: TMemoryStream;
begin
StrStream := TStringStream.Create(Value);
try
BinStream := TMemoryStream.Create;
try
ObjectTextToBinary(StrStream, BinStream);
BinStream.Seek(0, soFromBeginning);
Result:= BinStream.ReadComponent(nil);
finally
BinStream.Free;
end;
finally
StrStream.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Text:= ComponentToStringProc(Image1);
end;
procedure TForm1.Button2Click(Sender: TObject);
var img:TImage;
begin
img:= (StringToComponentProc(Memo1.Text) as TImage);
img.Left:=200;
img.Top:=96;
img.Parent:=form1;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Image1.Picture.Bitmap.Height:=Image1.Height;
Image1.Picture.Bitmap.Width:=Image1.Width;
Image1.Picture.Bitmap.Canvas.Rectangle(0,0,Image1.Width,Image1.Height);
end;
initialization
RegisterClass(TImage);
end.
My question is: Why do I have
initialization
RegisterClass (TImage);
When Image2 is a visual component placed on form1?
If there's two lines are missing, it says error 219 Invalid typecast
The streaming framework needs to be able to convert a component class name into a class. Once it has done so it is able to instantiate an object of the right class.
The key line of code is:
Result := BinStream.ReadComponent(nil);
Although Result
has type TComponent
, the actual runtime type can be a subclass of TComponent
. In your case, TImage
.
So, in order to be able to convert the string 'TImage'
into the meta class TImage
, there needs to be a registry (i.e. a map) of classes and their names. And that registry is populated by calls to RegisterClass
. Without that call, the streaming framework cannot find the metaclass TImage
that is named 'TImage'
. And so it cannot stream in the component.
Although you are working with FPC, the Delphi documentation for RegisterClass
will be helpful to you.