Search code examples
delphidelphi-10-seattle

Main Menu SubItem


I try to create MainMenu at runtime , so I create two Procedure for that :

Procedure 1:

Procedure AddMenuItem ( Const Menu : TMenu ; Caption : String );
  Var MenuItem : TMenuItem;
Begin
  MenuItem := TMenuItem.Create(Menu);
  MenuItem.Caption := Caption;
  Menu.Items.Add(MenuItem);
End;

Procedure 2:

Procedure MenuAddSubItem ( Const Menu : TMenu ; Index : Integer ; Caption : String ) ;
  Var Item : TMenuItem;
Begin
  Item := TMenuItem.Create(Menu);
  Item.Caption := Caption;
  Menu.Items[Index].Add(Item);
End;

The first Procedure create Items , and the second one create SubItems .

The call of this two Procedure is :

AddMenuItem(MainMenu1,'File');
MenuAddSubItem(MainMenu1,0,'Open');
MenuAddSubItem(MainMenu1,0,'Save');
MenuAddSubItem(MainMenu1,0,'Save as..');
MenuAddSubItem(MainMenu1,0,'-');
MenuAddSubItem(MainMenu1,0,'Exit');

I want to add Items to Save as.. Item, like :

File -> Save as.. -> PDF

File -> Save as.. -> Doc

File -> Save as.. -> Txt

So , my question is : How can I add Items to Save as.. Item ?

Update: I try to create another Procedure to do that , So the Procedure search for Save as.. Item , When he find it , Add other items to it.

Note: I'm Using Delphi 10 seattle


Solution

  • If you have a TMenuItem, you can simply use its Add method to add other menu items to it. Then, they are accessible through its Items property.

    The code below shows how to do this and also how to do a recursive search through a menu to find a menu item with a specified caption and add a new menu item to its sub-menu.

    function FindMenuItemByCaption(AMainMenu : TMainMenu; const Caption : String) : TMenuItem;
    
    
      function FindItemInner(Item : TMenuItem; const Caption : String) : TMenuItem;
      var
        i : Integer;
      begin
        Result := Nil;
        if Item.Caption = Caption then begin
          Result := Item;
          exit;
        end
        else begin
          for i := 0 to Item.Count - 1 do begin
            Result := FindItemInner(Item.Items[i], Caption);
            if Result <> Nil then
              Break;
          end;
        end;
      end;
    
    begin
      Result := FindItemInner(AMainMenu.Items, Caption);
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      FileItem,
      SaveItem,
      SaveAsItem,
      OtherItem,
      QuitItem : TMenuItem;
      i : integer;
      ItemToFind,
      ExtraItem : TMenuItem;
    begin
      FileItem := TMenuItem.Create(Self);
      FileItem.Caption := 'File';
      MainMenu1.Items.Add(FileItem);
    
      SaveItem := TMenuItem.Create(Self);
      SaveItem.Caption := 'Save';
      FileItem.Add(SaveItem);
    
      SaveAsItem := TMenuItem.Create(Self);
      SaveAsItem.Caption := 'Save as';
      FileItem.Add(SaveAsItem);
    
      for i := 1 to 3 do begin
        OtherItem := TMenuItem.Create(Self);
        OtherItem.Caption := 'Other ' + IntToStr(i);
        SaveasItem.Add(OtherItem);
      end;
    
      QuitItem := TMenuItem.Create(Self);
      QuitItem.Caption := 'Quit';
      FileItem.Add(QuitItem);
    
      Caption := SaveAsItem.Items[2].Caption;
    
      ItemToFind := FindMenuItemByCaption(MainMenu1, 'Save as');
      Assert(ItemToFind <> Nil);
      ExtraItem := TMenuItem.Create(Self);
      ExtraItem.Caption := 'Extra';
      ItemToFind.Add(ExtraItem);
    end;
    

    You can, of course, populate TPopUpMenus in a similar way;