1.Is correct the way I am adding and removing (freeing) the TStream object inside the StringList?
Yes, because the TStrings.Objects[]
property returns a TObject
pointer and TStream
derives from TObject
, so you can call Free()
on the object pointers.
Maybe I need to first free the Stream and then the Object??
You need to free the TStream
objects before freeing the TStringList
object. Just as you are already doing.
2.Is correct the way I am freeing all objects on FormDestroy event?
Yes. Though technically, you do not need to check the TStringList.Count
property for > 0
before entering the loop, as the loop will handle that condition for you. And you do not need to nil
the pointers before freeing the TStringList
:
procedure TForm1.FormDestroy(Sender: TObject);
var
I: Integer;
begin
for I := 0 to Pred(List.Count) do
List.Objects[I].Free;
List.Free;
end;
One thing you are doing that is overkill, though, is Assign()
ing the entire TStringList
to the TListBox
whenever you add/delete a single item from the TStringList
. You should instead simply add/delete the associated item from the ListBox and preserve the remaining items as-is.
And add some extra error checking to btnAddClick()
as well to avoid any memory leaks if something goes wrong.
Try this:
procedure TForm1.btnAddClick(Sender: TObject);
var
Strm: TStream;
Idx: Integer;
begin
Strm := TMemoryStream.Create;
try
Memo.Lines.SaveToStream(Strm);
Strm.Position := 0;
Idx := List.AddObject(IntToStr(List.Count), Strm);
except
Strm.Free;
raise;
end;
try
ListBox.Items.Add(List.Strings[Idx]);
except
List.Objects[Idx].Free;
List.Delete(Idx);
raise;
end;
Memo.Clear;
end;
procedure TForm1.btnDelFirstClick(Sender: TObject);
begin
if List.Count > 0 then
begin
List.Objects[0].Free;
List.Delete(0);
ListBox.Items.Delete(0);
end;
end;
3.When I try to load the stream back to Memo (Memo.Lines.LoadFromStream(TStream(List.Objects[Idx]))), it doesn't load, despite Stream.Size is higher than zero. What I am doing wrong?
You are not seeking the stream back to Position
0 before loading it into the Memo. SaveToStream()
always leaves the stream positioned at the end of the stream, and LoadFromStream()
leave the stream positioned wherever the load stopped reading from (if not at the end, in case of failure).
Now, with all of this said, I personally would not use TListBox
in this manner. I would instead set its Style
property to lbVirtual
and then use its OnData
event to display the strings from the TStringList
. No need to copy them into the TListBox
directly, or try to keep the two lists in sync at all times. It would be safer, and use less memory, to let the TListBox
ask you for what it needs, and then you can provide it from the TStringList
(which I would then change to a TList
since you are not really storing meaningful names that can't be produced dynamically in the OnData
event handler):
var
List: TList;
procedure TForm1.FormCreate(Sender: TObject);
begin
List := TList.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
I: Integer;
begin
ListBox.Count := 0;
for I := 0 to Pred(List.Count) do
TStream(List[I]).Free;
List.Free;
end;
procedure TForm1.btnAddClick(Sender: TObject);
var
Strm: TStream;
Idx: Integer;
begin
Strm := TMemoryStream.Create;
try
Memo.Lines.SaveToStream(Strm);
Strm.Position := 0;
Idx := List.Add(Strm);
except
Strm.Free;
raise;
end;
try
ListBox.Count := List.Count;
except
TStream(List[Idx]).Free;
List.Delete(Idx);
raise;
end;
Memo.Clear;
end;
procedure TForm1.btnDelFirstClick(Sender: TObject);
begin
if List.Count > 0 then
begin
TStream(List[0]).Free;
List.Delete(0);
ListBox.Count := List.Count;
end;
end;
procedure TForm1.ListBoxDblClick(Sender: TObject);
var
Strm: TStream;
Idx: Integer;
begin
Memo.Clear;
Idx := ListBox.ItemIndex;
if Idx >= 0 then
begin
Strm := TStream(List[Idx]);
if Strm.Size > 0 then
begin
Strm.Position := 0;
Memo.Lines.LoadFromStream(Strm);
end;
end;
end;
procedure TForm1.ListBoxData(Control: TWinControl; Index: Integer; var Data: string);
begin
Data := IntToStr(Index);
end;
Strm
toTObject
in theList.AddObject(IntToStr(List.Count), TObject(Strm));
lineStrm
IS a TObject – Gerry Coll