0
votes

I need to selectively enable certain menu items based upon the status of the user. I've managed to get code to enable the actual items I want but I can't see how to enable all the parent menu items above each one that I enable in a multi-level menu. Without enabling them as well the menu item still can't be used as the user cannot reach it.

eg if I have

EditTop
   EditSub1
   Editsub2
      EditSubSub1
   EditSub3 

I can enable EditSubSub1 but I also therefore need to enable Editsub2 and EditTop as well or it can't be reached by the user. That's what I would appreciate help with.

The code I have at the moment is the following (Assume that other code has given me a TstringList containing the menu names I want enabled)

First some code to disable everything.

procedure DisableMenu(AMenu: TMenuItem);
//recurses through all the menu and disables eveything 
var
  i: integer;
begin
for i := 0 to AMenu.Count - 1 do
   begin
   AMenu[i].enabled := false;
   DisableMenu(AMenu[i]);
   end;
end;

Then code that searches for and returns a TmenuItem based upon its name (This came from http://www.delphipages.com/forum/showthread.php?t=45723)

function FindMnuItem(Menu: TMenu; MenuName: string): TMenuItem;

      procedure FindSubItems(mnuItem: TMenuItem);
      var i: integer;
      begin
        for i:=0 to mnuItem.Count- 1 do
          if mnuItem.Items[i].Name= MenuName then
             begin
             Result:= mnuItem.Items[i];
             break;
             end
          else
             FindSubItems(mnuItem.Items[i]);
      end;

var i: integer;
begin
Result:= nil;
for i:= 0 to Menu.Items.Count -1 do
    begin
    if Menu.Items[i].name = MenuName then
       begin
       Result:= Menu.Items[i];
       break;
       end
    else
       if Result<> nil then
          break
       else
          FindSubItems(Menu.Items[i]);
    end;
end;

Finally the code I would like some help with. This selectively enables each menu item based upon the names in the Stringlist AllowedMenus but only those ones, not the ones above each one in the tree. How do I do that?

//first disable all menu items
DisableMenu(MainMenu1.Items); 
//now enable the ones we want enabled       
for i := 0 to AllowedMenus.count-1 do
    begin
    MenuName := AllowedMenus[i];
    FindMnuItem(MainMenu1, MenuName).Enabled := true; //enable an item   
    end
2
You could use Actions and simply write an OnUpdate event handler for each action.Ondrej Kelle

2 Answers

3
votes

All you need to do is walk up the menu tree using the TMenuItem.Parent property.

var vMenuItem : TMenuItem;
[...]
//first disable all menu items
    DisableMenu(MainMenu1.Items); 
    //now enable the ones we want enabled       
    for i := 0 to AllowedMenus.count-1 do
    begin
      MenuName := AllowedMenus[i];
      vMenuItem := FindMnuItem(MainMenu1, MenuName);
      while Assigned(vMenuItem) do
      begin
        vMenuItem.Enabled := true; //enable an item   
        vMenuItem := vMenuItem.Parent;
      end;
    end
0
votes

i think that u can use this function; (D21 is your Actual Items):

procedure UpdateMenuParent(MyItemMenu: TMenuItem);
begin
  TMenuItem(MyItemMenu).Enabled := true;
  if TMenuItem(MyItemMenu).Parent <> nil then
    UpdateMenuParent(TMenuItem(MyItemMenu).Parent);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  UpdateMenuParent(D21);
end;