盒子论坛有人问如何把一个 TImage 的序列化后的字符串变成一个 TImage.
那么,首先我们来看看这个字符串是怎么来的,那就是:
如何把一个对象比如 Image1: TImage 序列化为字符串
看代码:
//序列化
function ComponentToString(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;
假设 Form1 上面我有一个 Image12,并且加载了图片,然后,
调用上述代码:
procedure TForm5.Button4Click(Sender: TObject);
var
S: string;
begin
S := ComponentToString(Image12);
Memo1.Lines.Text := S;
end;
获得的结果显示到 Memo1 里面了,如下:
object Image12: TImage
Left = 488
Top = 40
Width = 105
Height = 105
Picture.Data = {
0A544A504547496D6167654E1E0000FFD8FFE000104A46494600010101004800
480000FFE100C04578696600004D4D002A000000080006011A00050000000100
000056011B0005000000010000005E0128000300000001000200000131000200
0000110000006601320002000000140000007887690004000000010000008C00
000000000000480000000100000048000000017061696E742E6E657420352E30
2E31330000323030393A30323A31392031313A30353A3432000003A001000300
00000100010000A00200040000000100000270A003000400000001000001A900
0000000000FFE107E9687474703A2F2F6E732E61646F62652E636F6D2F786170
2F312E302F003C3F787061636B657420626567696E3D22EFBBBF222069643D22
57354D304D7043656869487A7265537A4E54637A6B633964223F3E0D0A3C783A
786D706D65746120786D6C6E733A783D2261646F62653A6E733A6D6574612F22
20783A786D70746B3D2241646F626520584D5020436F726520342E312D633033
362034362E3237363732302C204D6F6E2046656220313920323030372032323A
34303A30382020202020202020223E0D0A20203C7264663A52444620786D6C6E
733A7264663D22687474703A2F2F7777772E77332E6F72672F313939392F3032
2F32322D7264662D73796E7461782D6E7323223E0D0A202020203C7264663A44
65736372697074696F6E207264663A61626F75743D222220786D6C6E733A6463
3D22687474703A2F2F7075726C2E6F72672F64632F656C656D656E74732F312E
312F2220786D6C6E733A7861703D22687474703A2F2F6E732E61646F62652E63
6F6D2F7861702F312E302F2220786D6C6E733A7861704D4D3D22687474703A2F
2F6E732E61646F62652E636F6D2F7861702F312E302F6D6D2F2220786D6C6E73
3A73745265663D22687474703A2F2F6E732E61646F62652E636F6D2F7861702F
E41EBD4E4D15D1868C6F7B0E2DCB591F3D4B79AB3F882DE1D43529AE99409373
392C016C753D4FE028AF739525748F3A3567CAF534F47D2AF75FB51ACEB3A9C9
F62572A96D6D88CB727EF10063F0A2B96B4DC748E87651F7BE2361F53B3B4454
D2F4E8ACE123EE040C4907BB1058FE268AE75152D65A972935A23FFFD9}
end
说明:以上序列化出来的字符串,我把图片二进制数据部分删除了很多,只保留了一部分,仅仅为了说明里面的字符串实际上是 HEX 数据。如果都保留,篇幅太大了。
如何把字符串反序列化为对象
上面序列化出来的字符串,如何使用代码,在运行期,加载字符串,变成一个 TImage 对象,并且呈现在界面上?
反序列化的代码:
//测试 TComponent 反序列化
function StringToComponent(Value: string): TComponent;
var
StrStream:TStringStream;
BinStream: TMemoryStream;
begin
RegisterClass(TImage); //没有这个,会提示:Class TImage not found
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;
调用上述函数,把 Image 从字符串反序列化回来,显示到一个 Panel1 上面:
procedure TForm5.Button3Click(Sender: TObject);
var
AComponent: TComponent;
S: string;
begin
S := Memo1.Lines.Text;
AComponent := StringToComponent(S);
if (AComponent is TImage) then
begin
TImage(AComponent).Parent := Panel1;
TImage(AComponent).Align := alClient;
end;
end;
上述代码,在 Delphi 11 CE 版本上测试通过。
一个说明:
上述代码中,函数:StringToComponent 负责把字符串变成一个 TComponent 的对象,其中实际完成这个动作的代码是:BinStream.ReadComponent(nil);
但是,执行这一行,会有异常提示:Class TImage not found.
解决这个异常的办法就是,在执行这行代码之前,先注册 TImage:
RegisterClass(TImage);
当然,要在程序里面使用 TImage 还必须引用:Vcl.ExtCtrls
但是,仅仅是引用 Vcl.ExtCtrls 并不会使得 Class TImage not found 这个异常消失。
本文结束。
觉得本文有用的,点个赞吧!