This solution requires parent_id of root to be 0, tested with
Select 1 as ID, 0 as Parent_ID, 'Root' as Name
union
Select 2, 1, ' Car'
union
Select 3 , 1, 'Plane'
union
Select 4, 2, 'BMW'
union
Select 5, 4, 'CLK'
should by optimized, have just a lack of time ...
Function GetMenu(pop:TPopupmenu;ID:Integer):TMenuItem;
var
i:Integer;
Function CheckItem(mi:TMenuItem):TMenuItem;
var
i:Integer;
begin
Result := nil;
if mi.Name = 'DYN_' + INtToStr(ID) then Result := mi
else for i := 0 to mi.Count-1 do
if not Assigned(Result) then Result := CheckItem(mi[i]);
end;
begin
Result := nil;
for i := 0 to pop.Items.Count-1 do
begin
if not Assigned(Result) then Result := CheckItem(pop.Items[i]);
if Assigned(Result) then Break;
end;
end;
Function InsertMenuItem(pop:TPopupMenu;mi:TMenuItem;ID:Integer;Const caption:String):TMenuItem;
begin
Result := TMenuItem.Create(pop);
Result.Caption := caption;
Result.Name := 'DYN_' + INtToStr(ID) ;
if not Assigned(mi) then pop.Items.Add(Result) else mi.Add(Result);
end;
Function AddMenuItem(pop:TPopupmenu;ID:Integer;Ads:TDataset):TMenuItem;
begin
Ads.Locate('ID',ID,[]);
Result := GetMenu(pop,id);
if (not Assigned(Result)) then
begin
if (Ads.FieldByName('parent_ID').AsInteger<>0) then
begin
result := AddMenuItem(pop,Ads.FieldByName('parent_ID').AsInteger,Ads);
Ads.Locate('ID',ID,[]);
end;
Result := InsertMenuItem(pop,Result,ID,Ads.FieldByName('Name').AsString);
end;
Ads.Locate('ID',ID,[]);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
while not ADS.Eof do
begin
AddMenuItem(Popupmenu1,ads.FieldByName('ID').AsInteger,Ads);
Ads.Next
end;
end;