Remove parent TMenuItem in a TPopupMenu or recursively add items from PopupMenu1 into PopupMenu2 without the parent TMenuItem

skynergy
skynergy used Ask the Experts™
on
Question A:
I have a TPopupMenu that have the following TMenuItems in each tier:
Tier1     Tier2    Tier3
-----      -----      -----
parent  child_1  sub_item_a
                            sub_item_b
            child_2  sub_item_c
                            sub_item_d
            child_3   sub_item_e
                            sub_item_f
                 
How do I remove the 1st TMenuItem (called 'parent' in this example) from the TPopupMenu, so it that the TMenuItems that remain will show as follows:
Tier1     Tier2    
-----       -----
child_1  sub_item_a
               sub_item_b
child_2  sub_item_c
               sub_item_d
child_3  sub_item_e
               sub_item_f                
         
Question B:        
If one cannot remove the first tier's TMenuItem, how do I recursuvely go through TPopupMenu1 and add all the TMenuItems from TPopupMenu1, except for the parent TMenuItem, to TPopupMenu2?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Commented:
Ok here is how I did it:

function TForm1.AddMI(MI: TMenuItem; MIP: TPopupMenu; MICaption: String): TMenuItem;
var
  i: Integer;
  tmi: TMenuItem;
begin
  tmi := TMenuItem.Create(MIP);
  tmi.Caption := MICaption;
  MI.Add(tmi);
  Result := tmi;
end;

procedure TForm1.LoopMI(MIS, MIT: TMenuItem; PMT: TPopupMenu);
var
  i: Integer;
  mi: TMenuItem;
begin
  for i := 0 to MIS.Count - 1 do begin
    mi := AddMI(MIT, PMT, MIS[i].Caption);
    LoopMi(MIS.Items[i], mi, PMT);
  end;
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
 { I start with Items[0] to skip the parent item }
  LoopMI(PopupMenu2.Items[0], PopupMenu3.Items, PopupMenu3);

{ Normally you will start like this, no [0]
  LoopMI(PopupMenu2.Items, PopupMenu3.Items, PopupMenu3);
}

  PopupMenu3.Popup(Left, Top);
end;
developmentguruPresident

Commented:
If this is a simple switch of menus (as opposed to a more dynamic restructuring)... I.E. there will only ever be the two possibilities, then you can simply use two popup menus and switch which one the form is using by setting the form's popup menu property to popupmenu1 or popupmenu2.
Ephraim WangoyaSoftware Engineer

Commented:
If we are just removing the first tier, a simple nested loop should be sufficient

procedure RemoveFirstTier(APopupMenu: TPopupMenu);
var
  Item, ParentItem: TMenuItem;
  I: Integer;
  List: TList;
begin
  List := TList.Create;  //just maintain a list of the parent items
  try
    for I := 0 to APopupMenu.Items.Count -1 do
    begin
      ParentItem := APopupMenu.Items[I];
      while ParentItem.Count > 0 do
      begin
        Item := ParentItem.Items[0];
        ParentItem.Remove(Item);
        APopupMenu.Items.Add(Item);
      end;
      List.Add(ParentItem);
    end;

    for I := List.Count -1 downto 0 do
      APopupMenu.Items.Remove(TMenuItem(List[I]));
  finally
    FreeAndNil(List)
  end;
end;
Ephraim WangoyaSoftware Engineer

Commented:
My previous solution will remove all the first level menu items, You can change it to

procedure TForm1RemoveFirstTier(APopupMenu: TPopupMenu);
var
  Item, ParentItem: TMenuItem;
  I: Integer;
  List: TList;
begin
  List := TList.Create;  //just maintain a list of the parent items
  try
    for I := 0 to APopupMenu.Items.Count -1 do
    begin
      ParentItem := APopupMenu.Items[I];
      if ParentItem.Count > 0 then
      begin
        while ParentItem.Count > 0 do
        begin
          Item := ParentItem.Items[0];
          ParentItem.Remove(Item);
          APopupMenu.Items.Add(Item);
        end;
        List.Add(ParentItem);
     end;
    end;

    for I := List.Count -1 downto 0 do
    begin
      Item := TMenuItem(List[I])
      APopupMenu.Items.Remove(Item);
      Item.Free;
    end;
  finally
    FreeAndNil(List)
  end;
end;

Or if you just want to remove from one known parent menu then you can pass it to the procedure as follows and make it even simpler

procedure TForm1.RemoveParentItem(APopupMenu: TPopupMenu; AParentItem: TMenuItem);
var
  Item: TMenuItem;
begin
  while AParentItem.Count > 0 do
  begin
    Item := AParentItem.Items[0];
    AParentItem.Remove(Item);
    APopupMenu.Items.Add(Item);
  end;

  APopupMenu.Items.Remove(AParentItem);
  AParentItem.Free;
end;
Mike McCrackenSenior Consultant
Most Valuable Expert 2011
Top Expert 2013

Commented:
This question has been classified as abandoned and is being closed as part of the Cleanup Program.  See my comment at the end of the question for more details.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial