As you already know, you need to use the TListView.OnDeletion event to dispose of the TListItem.Data memory that you are allocating. If you read the documentation for StrAlloc(), the correct way to free that memory is with StrDispose(), not FreeMem():
procedure TMainFrm.LV_DataDeletion(Sender: TObject; Item: TListItem);
begin
if Item.Data <> nil then
begin
StrDispose(PChar(Item.Data));
Item.Data := nil;
end;
end;
Alternatively, a slightly easier way is to use a normal String and let the compiler manage it. A String is implemented as a pointer, and you can store that pointer in the TListItem.Data. You would just have to ensure its reference count is incremented while stored in TListItem.Data, and decremented when you are done using it:
var
i : Integer;
ListItem : TListItem;
PObject : Pointer;
begin
for i := 0 to 3 do
begin
ListItem := AList.Items.Add;
...
PObject := nil;
String(PObject) := '...';
ListItem.Data := PObject;
end;
procedure TMainFrm.LV_DataDeletion(Sender: TObject; Item: TListItem);
var
PObject: Pointer:
begin
if Item.Data <> nil then
begin
PObject := Item.Data;
Item.Data := nil;
String(PObject) := '';
end;
end;
var
sPath : string;
begin
if (LV_Data.Items.Count > 0) AND (LV_Data.ItemIndex <> -1) then
begin
sPath := String(LV_Data.Items[LV_Data.ItemIndex].Data);
end;
That being said, a much safer and cleaner solution is to not use the TListItem.Data property at all. Instead, derive a new class from TListItem and add a String member to it, then use the TListView.OnCreateItemClass event to let TListView create instances of your derived class:
type
TMyListItem = class(TListItem)
public
Path: string;
end;
procedure TMainFrm.LV_DataCreateItemClass(Sender: TCustomListView;
var ItemClass: TListItemClass);
begin
ItemClass := TMyListItem;
end;
var
i : Integer;
ListItem : TListItem;
begin
for i := 0 to 3 do
begin
ListItem := AList.Items.Add;
...
TMyListItem(ListItem).Path := '...';
end;
var
sPath : string;
begin
if (LV_Data.Items.Count > 0) AND (LV_Data.ItemIndex <> -1) then
begin
sPath := TMyListItem(LV_Data.Items[LV_Data.ItemIndex]).Path;
end;
No mess, no fuss. The memory is managed for you, and will be cleaned up automatically, no OnDeletion handler needed.