billionjk 0 Posted January 24 (edited) 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 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. 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. 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. Teach me the correct how to read and write all the elements present in the stream, please. Edited January 24 by billionjk Share this post Link to post
Uwe Raabe 2060 Posted January 24 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
billionjk 0 Posted January 27 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