Delphi流面板到文件 [英] Delphi stream panel to file
问题描述
今天,我对将表单的一部分流式传输到文件存在疑问。
在此示例中,我使用Tmemo而不是文件来查看流。
today I've a question about streaming a part of a form to a file. In this example i use a Tmemo instead of file in order to see the stream.
这是我的表单:
表单右上方的面板具有一些控件,例如标签,编辑等等。
和保存面板按钮,但是我将面板保存在TStream上:
The panel on the right top of the form has some controls, like label, edit and so on. with the "Save panel" butto I save the panel on a TStream:
这里的代码:
procedure TfrmMain.btnSaveClick(Sender: TObject);
var
idx: Integer;
MemStr: TStream;
begin
MemStr := TMemoryStream.Create;
PanelStr := TMemoryStream.Create;
try
for idx := 0 to pnlSource.ControlCount - 1 do begin
MemStr.Position := 0;
MemStr.WriteComponent(pnlSource.Controls[idx]);
StreamConvert(MemStr);
end;
PanelStr.Position := 0;
mmoStream.Lines.LoadFromStream(PanelStr);
finally
MemStr.Free;
end;
end;
,这里是StreamConvert:
and here the StreamConvert:
{ Conversione stream in formato testo }
procedure TfrmMain.StreamConvert(aStream: TStream);
var
ConvStream: TStream;
begin
aStream.Position := 0;
ConvStream := TMemoryStream.Create;
try
ObjectBinaryToText(aStream, ConvStream);
ConvStream.Position := 0;
PanelStr.CopyFrom(ConvStream, ConvStream.Size);
lblStreamSize.Caption := IntToStr(ConvStream.Size);
finally
ConvStream.Free;
end;
end;
PanelStr是在表单的私有部分中声明的TStream对象,并在表单创建期间创建。
这部分效果很好,并且如您在图像的右侧部分中所示,表单上存在的元素已正确注册。
PanelStr is a TStream object declared in private section of the form and create during form create. This part works good and, as you can see in right part of the image the elements present on the form are register correctly.
现在我的问题是将此元素还原到窗体左下方的面板中。
我已经尝试过以下例程:
Now my problem is to restore this element into the panel on the left bottom of the form. I've tryed this routine:
{ Carica i controlli presenti nel pannello pnlSource in uno stream }
procedure TfrmMain.btnLoadClick(Sender: TObject);
var
idx: Integer;
MemStr: TStream;
begin
pnlSource.Free;
MemStr := TMemoryStream.Create;
try
PanelStr.Position := 0;
ObjectTextToBinary(PanelStr, MemStr);
MemStr.Position := 0;
MemStr.ReadComponent(pnlTarget);
finally
MemStr.Free;
end;
end;
但是它不起作用,在下面的图片中您可以看到结果:
but it doesn't work and in the following picture you can see the result:
我的例程出了什么问题,我该怎么读流中存在的所有元素,而不仅仅是第一个元素?
What is wrong in my routine, and How can I read all the element present in the stream and not only the first?
有人可以帮我解决这个麻烦吗?
Can someone help me in this headache?
推荐答案
您当前正在运行的代码可以有效地将源面板转换为标签。这是因为第一个流对象是标签,并且代码仅读取一个组件。 IOW,当读者到达第一个端
时,由于流中没有 sub 控件,因此读取完成。
The code you are currently running effectively transforms the source panel to a label. That's because the first object streamed is a label and the code is reading only one component. IOW, when the reader reaches the first end
, reading is complete since there are no sub controls in the stream.
因此,首先,您必须编写面板-只有面板。该面板是应该播放其子元素的面板。为此,它必须拥有它的控件。
So, first of all, you have to write the panel - and only the panel. The panel is the one that is supposed to stream it's children. To have it to do so, it must own it's controls.
var
idx: Integer;
MemStr: TStream;
begin
MemStr := TMemoryStream.Create;
PanelStr := TMemoryStream.Create;
try
// transfer ownership of controls to the panel
for idx := 0 to pnlSource.ControlCount - 1 do
pnlSource.InsertComponent(pnlSource.Controls[idx]);
// write the panel
MemStr.WriteComponent(pnlSource);
StreamConvert(MemStr);
PanelStr.Position := 0;
mmoStream.Lines.LoadFromStream(PanelStr);
finally
MemStr.Free;
end;
这将为备忘录生成如下输出:
This produces an output to the memo like this:
object pnlSource: TPanel
Left = 8
Top = 8
Width = 201
Height = 265
Caption = 'pnlSource'
TabOrder = 0
object Label1: TLabel
Left = 48
Top = 208
Width = 31
Height = 13
Caption = 'Label1'
end
object Label2: TLabel
...
请注意标签定义的缩进和所属面板的缺失末端(在末尾)。
Note the indentation of the label definition and the missing 'end' of the owning panel (it's at the end).
您需要注册课程以便流媒体在加载时能够找到它们:
You will need to register classes for the streamer to be able to find them when loading:
var
idx: Integer;
MemStr: TStream;
begin
pnlSource.Free;
RegisterClasses([TLabel, TEdit, TCheckBox, TRadioButton]);
MemStr := TMemoryStream.Create;
try
PanelStr.Position := 0;
ObjectTextToBinary(PanelStr, MemStr);
MemStr.Position := 0;
MemStr.ReadComponent(pnlTarget);
finally
MemStr.Free;
end;
注册当然可以移到其他地方,例如表单创建或单元初始化。
Registration can be of course moved to elsewhere, like form creation or unit initialization.
如果需要,您也可以将控件的所有权转移回表单,例如保存代码中那样。
You can also transfer ownership of the controls back to the form if it's required, like in the saving code.
这篇关于Delphi流面板到文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!