views:

171

answers:

2

Hi. Anybody knows how to merge two menus with the same name in a MDI application.

More exactly, in the MDI main form I have a menu called 'File' which has a sub-menu called 'Load project'. In the MDI child form, I have a menu called also 'File' which contains a sub-menu called 'Save project'.

How can I force my application to show both 'Load' and 'Save' sub-menus under the 'File' menu?

-

PS: setting the same GoupIndex value will not work.

+1  A: 

Manual merging is a matter of calling FormMain.MainMenu.Merge(SubForm.MainMenu) and its counterpart FormMain.MainMenu.UnMerge(SubForm.MainMenu).

You shouldn't need it though, because if the FormStyles of your forms are properly set to fsMDIForm and fsMDIChild, then menu merging should be automatic.

Having said that, I am not sure that what you want is possible using the built in menu merging.

According to the GroupIndex help (and a couple of experiments), menu items from a child forms replace items on the main form with the same GroupIndex. Only when the GroupIndex of a menu item on the child form falls between GroupIndex values on the main form, will the menu be inserted. So, the File menu on your child form will always replace the File menu on the main form. Only if you give the File menu's different GroupIndex values will the File menu of the Main form remain, but then you have two File menu's...

So, I think the only solution would be to insert and remove the menu items of the subform manually, or to have them on the main menu all the time and enable/disable them according to the active MDIChild. Possibly even show/hide them.

Personally I would go for the option of having them around all the time and enabling/disabling them according to the active MDIChild, as I don't like menu items that "bounce around" (change position).

Marjan Venema
+1  A: 

Hi.

To merge your menus use this procedure:

procedure MergeMenus(var SrcMenu, DstMenu: TMainMenu);
var
  i, i2, i3: Integer;
  Menu: TMenuItem;
begin
  for i := 0 to SrcMenu.Items.Count - 1 do
  begin
    for i2 := 0 to DstMenu.Items.Count - 1 do
    begin
      if (SrcMenu.Items[i].Name = DstMenu.Items[i2].Name) and
        (SrcMenu.Items[i].Count > 0) and (DstMenu.Items[i].Count > 0) then
      begin
        for i3 := 0 to SrcMenu.Items[i].Count - 1 do
        begin
          Menu := TMenuItem.Create(DstMenu.Owner);
          // copy another properties if necessery
          Menu.Name := SrcMenu.Items[i].Items[i3].Name;
          Menu.Caption := SrcMenu.Items[i].Items[i3].Caption;
          Menu.ShortCut := SrcMenu.Items[i].Items[i3].ShortCut;
          Menu.OnClick := SrcMenu.Items[i].Items[i3].OnClick;
          DstMenu.Items[i].Add(Menu);
        end;
      end;
    end;
  end;
end;

Call it in the OnCreate event of your MDIChildForm like this:

procedure TMDIChild.FormCreate(Sender: TObject);
begin
  MergeMenus(YourMainForm.MainMenu1, Self.MainMenu1);
end;

It will work if two different MainMenus will have MenuItems with the same name. Also please note that there is a possible memory leek if your DstMenu does not have an owner (but I guess it have and it is your MDICHildForm).

Wodzu