Delphi流面板到文件 [英] Delphi stream panel to file

查看:69
本文介绍了Delphi流面板到文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天,我对将表单的一部分流式传输到文件存在疑问。
在此示例中,我使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆