Jump to content

Recommended Posts

I'm learning how to convert panels with child components to stream from this article https://stackoverflow.com/questions/41021756/delphi-stream-panel-to-file . I'm designing a new form like this

 

2024-01-24_125836.thumb.png.0250f30e99496d84104d921116235b57.png

 

When clicking the btnSave will call the procedure StreamConvert to convert the panel to stream and show the text object in the memo.

 

procedure TForm1.StreamConvert(aStream: TStream);
var
  ConvStream: TStream;
begin
  aStream.Position := 0;
  ConvStream := TMemoryStream.Create;
  try
    ObjectBinaryToText(aStream, ConvStream);
    ConvStream.Position := 0;
    PanelStream.CopyFrom(ConvStream, ConvStream.Size);
    lblStreamSize.Caption := IntToStr(ConvStream.Size);
    lblLineCount.Caption := mmoObjectText.Lines.Count.ToString;
  finally
    ConvStream.Free;
  end;
end;

 

procedure TForm1.btnSaveClick(Sender: TObject);
var
  idx: Integer;
  MemStr: TStream;
begin
  MemStr := TMemoryStream.Create;
  try
    for idx := 0 to pnlSource.ControlCount - 1 do begin
      MemStr.Position := 0;
      MemStr.WriteComponent(pnlSource.Controls[idx]);
      StreamConvert(MemStr);
    end;
    PanelStream.Position := 0;
    mmoObjectText.Lines.Clear;
    mmoObjectText.Lines.LoadFromStream(PanelStream);
  finally
    MemStr.Free;
  end;
end;

PanelStream is a TStream declared in the public section and created in the onCreate form. The result of the running screen is as follows.

 

2024-01-24_130710.thumb.png.75f18152d687d5c61ffd78a785da4726.png

 

When clicking btnLoad will load the PanelStream back to pnlSource but the problem is when I change some text in TEdit and save it again. When click loading to load the PanelStream back to pnlSource the first line of the memo shows "object = pnlSource: TPanel" and I don't want to save the TPanel as the parent of all objects.

 

2024-01-24_132332.thumb.png.0792d57c3063cdaca5294aa89c1a0819.png

 

procedure TForm1.btnLoadClick(Sender: TObject);
var
  iTemp, iTemp2 : TStringList;
  MemStr: TStream;
  i: Integer;
begin
  // Clear all control in the panel source
  //btnClear.Click;

  // first read the destination panel an put it into a string list
  iTemp := TStringList.Create;
  iTemp2 := TStringList.Create;
  iTemp.Duplicates := TDuplicates.dupAccept;
  iTemp2.Duplicates := TDuplicates.dupAccept;
  MemStr := TMemoryStream.Create;
  try
    PanelStream.Position := 0;
    iTemp2.LoadFromStream(PanelStream); // our original source
    panelStream.Size := 0;
    MemStr.Position := 0;
    MemStr.WriteComponent(pnlSource); // write component to panel source
    StreamConvert(MemStr);

    // PanelStr now has our destination poanel.
    PanelStream.Position := 0;
    iTemp.LoadFromStream(PanelStream);
    for i := 0 to iTemp2.Count - 1 do
    begin
      iTemp.Insert(ITemp.Count - 1, iTemp2[i]);
    end;

    PanelStream.Size := 0;
    iTemp.SaveToStream(PanelStream);
    PanelStream.Position := 0;
    mmoObjectText.Lines.Clear;
    mmoObjectText.Lines.LoadFromStream(PanelStream);

    MemStr.Size := 0;
    PanelStream.Position := 0;
    ObjectTextToBinary(PanelStream, MemStr);
    MemStr.Position := 0;

    RegisterClass( TLabel );
    RegisterClass( TPanel );
    RegisterClass( TEdit );
    RegisterClass( TCheckBox );
    RegisterClass( TRadioButton );
    MemStr.ReadComponent(pnlSource);

  finally
    iTemp.Free;
    iTemp2.Free;
    MemStr.Free;
  end;
end;

I want to save the changes of EditText, Checkbox, and RadioButton values to stream and load it back to show the saved value. I think the problem is that btnLoad created the wrong object to stream and when the stream loaded then it showed the error of a duplicated object.

 

2024-01-24_132447.thumb.png.65712c0abc982a0fed1c4fd498f57029.png

 

Teach me the correct how to read and write all the elements present in the stream, please.

 

Edited by billionjk

Share this post


Link to post

If you don't want to have the panel stored to the stream as the parent of its controls, you shouldn't do so:

    MemStr.WriteComponent(pnlSource); // write component to panel source

Compare that to the code writing only the controls:

    for idx := 0 to pnlSource.ControlCount - 1 do begin
      MemStr.Position := 0;
      MemStr.WriteComponent(pnlSource.Controls[idx]);
      StreamConvert(MemStr);
    end;

 

Share this post


Link to post
On 1/24/2024 at 4:43 PM, Uwe Raabe said:

If you don't want to have the panel stored to the stream as the parent of its controls, you shouldn't do so:


    MemStr.WriteComponent(pnlSource); // write component to panel source

Compare that to the code writing only the controls:


    for idx := 0 to pnlSource.ControlCount - 1 do begin
      MemStr.Position := 0;
      MemStr.WriteComponent(pnlSource.Controls[idx]);
      StreamConvert(MemStr);
    end;

 

Thank you so much. Another problem was solved by setting the PanelStream size to 0 before saving.

 

procedure TForm1.btnSaveClick(Sender: TObject);
var
  idx: Integer;
  MemStr: TStream;
begin
  MemStr := TMemoryStream.Create;
  PanelStream.Size := 0;
  try
    for idx := 0 to pnlSource.ControlCount - 1 do begin
      MemStr.Position := 0;
      MemStr.WriteComponent(pnlSource.Controls[idx]);
      StreamConvert(MemStr);
    end;
    PanelStream.Position := 0;
    mmoObjectText.Lines.Clear;
    mmoObjectText.Lines.LoadFromStream(PanelStream);
  finally
    MemStr.Free;
  end;
end;

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×