Solved

How to disable a submenu item that is a popup menu?

Posted on 2000-03-31
11
2,448 Views
Last Modified: 2012-06-21
Scenario - Programming in Visual C++ version 5 using MFC wherever possible.  I have a top level pulldown menu, several of teh submenu items are themselves popup menus which leads to submenu items and even further popup menus.

I need to be able to disable or enable or even remove andleter reinsert,  one or several of these popups during runtime depending in my applications internal state.  Enabling/disableing a submenu item that is not a popup is easy, each submenu item has an ID so I just have class wizard overide the ON_UPDATE_COMMAND_UI handlers and enable or disable it there.

But the popup portions of the submenu items do not have an ID associtated with them that I can see in the resource editor or class wizard.  How do I traverse/ find the popup submenu item to perform the enable/disabling/removing/inserting?  And once I find it how do I perform the enable/disabling/removing/inserting?  Any help would be appreciated.
0
Comment
Question by:cbursk
  • 7
  • 4
11 Comments
 
LVL 22

Accepted Solution

by:
nietod earned 100 total points
ID: 2673470
You can use EnableMenuItem() to enable/disable the item, but you have to specify the item by position (use the MF_BYPOSITION) option.  

However, if I remember correctly, when you disable a sub-menu item, you can't pop-up the sub-menu at all, so the user will not be able to see (much less choose) the items on the sub-menu.  For that reason this is usually not done.  Usually you just disable the appropriate command items and let the sub-menus continue to work, so the user can see the dissabled commands items.  (This lets them see what features could be available, but aren't.)
0
 
LVL 22

Expert Comment

by:nietod
ID: 2673486
You can remove a menu item by using RemoveMenu() function.  Again you will need to use MF_BYPOSITION when deleteing a sub-menu item.

You can insert a menu item into a menu by using InsertMenuItem() function

Let me know if you have any questions.
0
 
LVL 22

Expert Comment

by:nietod
ID: 2673496
Note you might find you need to maintain a data structure of some sort that helps you track the position of the menus and their other attributes.  You might creating a structure like

struct MenuItem
{
   bool  Cmd; // Command?  or sub-menu?
   bool Ena;  // Enabled?
   UINT ID; // Command ID, if a command.
   HMENU MenHnd; // Sub-menu handle, if a submenu.
   vector<MenuItem> *SubMenDat; // -> data fro sub-menu.
};

then creating arrays of these (using vectors) to track information for each menu, like

vector<MenuItem> MenuData;
0
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 

Author Comment

by:cbursk
ID: 2673818
Part of the probelm that I'm still having is reaching into the submenus.

Using EnableMenuItem by postion doen't work if I use a number exceeding the top level menu pull downs ( I have six toplevel pulldowns ) and even if I use MF_BYCOMMAND and pass n the submeu item ID it still doesn't work.  Of  course using the ON_UPDATE_COMMAND_UI handlers works fine foe enabling and disabling submenu items that I can setup thru class wizard, but I have somemany that it may become problematic.

I have tried reaching into the submenus to get to the popups using:

MainFrame::OnInitMenu

HMENU subMenu = GetSubMenu(      m_hMenuDefault, // handle of menu
   0 // menu item position
  );

BOOL flag = EnableMenuItem(  
 subMenu, // handle to menu
5, // menu item to enable, disable, or gray  
MF_BYPOSITION | MF_GRAYED // menu item flags
 );

but this doen't seem to work either.

My requirements are what is forcing me to actually remove a submenu item popup in some cases and I had planned on using the RemoveMenu() function to do that if I could just get there.

Thanks for your help.  ANy further ideas?
0
 

Author Comment

by:cbursk
ID: 2673916
What is real strange is that I have just discovered that using the above method for getting the , RemoveMenu seems to work fine, but EnableMenuItem doesn't?!?
0
 
LVL 22

Expert Comment

by:nietod
ID: 2674042
Did you check that the handles you are getting are valid?  make sure none are NULL?

Are there 6 items in the sub-menu you obtained?  You specified an index of 5, that is for the 6th item.
0
 
LVL 22

Expert Comment

by:nietod
ID: 2674076
Try using the MF_DISABLED flag instead.  If I remember correctly there is something a little weird about dissabled sub-menu items--that;s why you usually don't see them.  I don't remember the details, I ended up writting my own menus instead of using the built-in ones..
0
 

Author Comment

by:cbursk
ID: 2674211
OK - I'm officially a pain... but I'm getting closer to a solution.

Here is my latest weird behavior...
In MainFrame::OnInitMenu

CMenu* submenu = pMenu->GetSubMenu( 2 );

if ( NULL != subMenu )
{  
   int itemCount = submenu->GetMenuItemCount();

   // stiple out all menu items
    for ( int i = 0; i < itemCount; i++ )
   {
      submenu->EnableMenuItem( i,
                                                MF_BYPOSITION |                                                                                                                                                                                                                                                                                                                                       MF_GRAYED          );
   }
}

The EnableMenuItem is now working for me except... it is only disabling the popups.  Using MF_DISABLED has the same results.  That would be fine except I have a mixture of popups and non-popups.  I am checking my handles before using them and I am within the index range.
0
 
LVL 22

Expert Comment

by:nietod
ID: 2674283
>>  I'm officially a pain
Apparently you haven't seen other questions.

I didn't realize this was for MFC.  of course now I see it in the original quesiton....

After you dissable an item, use the GetMenuState() or GetMenuItemInfo() function to see if the item is really being dissabled.
0
 

Author Comment

by:cbursk
ID: 2674630
OK folks here what I got going, don't understand why ther is a difference but I'm tired of fight the system...

In MainFrame::OnInitMenu
----------------------------------------------------------
// The following for some reason will only stiple the
// popups in the submenu
CMenu* submenu1 = pMenu->GetSubMenu( 0 );

int z1 = submenu1->GetMenuItemCount();

for ( int i1 = 0; i1 < z1; i1++ )
{
      // disabling only popups???????????
      submenu1->EnableMenuItem( i1, MF_BYPOSITION | MF_GRAYED );

}

However in MainFrame::OnInitMenuPopup
---------------------------------------------------------
int z = pPopupMenu->GetMenuItemCount();

for ( int i = 0; i < z; i++ )
{
      pPopupMenu->EnableMenuItem( i, MF_BYPOSITION | MF_GRAYED );

}

Does stiple everything.  Although for me it seems to work only if I don't touch any of the menu items in MainFrame::OnInitMenu??  Don't know why...

Furter more if I replace the above code in OnInitMenuPopup with:
int z = pPopupMenu->GetMenuItemCount();

   for ( int i = 0; i < z; i++ )
   {
      LPMENUITEMINFO lpmii = new MENUITEMINFO;

      memset( lpmii, 0, sizeof(MENUITEMINFO) );

      lpmii->cbSize = sizeof(MENUITEMINFO);
      lpmii->fMask = MIIM_CHECKMARKS |  MIIM_DATA       | MIIM_ID  | MIIM_STATE  |MIIM_SUBMENU    | MIIM_TYPE;
 

      HMENU hMenu = pPopupMenu->GetSafeHmenu( );

     BOOL flag1 = GetMenuItemInfo( hMenu,
                                   i,
                                   TRUE,  
                                   lpmii  
                                  );

     // hSubMenu = Handle to the drop-down menu or           //  submenu associated with
     // the menu item. If the menu item is not an item           // that opens a drop-down
     // menu or submenu, this member is NULL.                  //------------------------------------------------------
     if ( NULL == lpmii->hSubMenu )
     {
        pPopupMenu->EnableMenuItem( i, MF_BYPOSITION | MF_GRAYED );
     }

   }

By changing the last if to look for NULL or !NULL I can exclude popup or vica-versa
0
 
LVL 22

Expert Comment

by:nietod
ID: 2675837
What may be happening is that when you make changes in the OnInitMenu() function, the MFC system then undoes some of those changes (probably trying to help you) before it calls OnInitMenuPopup().  
You should be able to confirm that.  Check to see if the change is successfully made when you are in OnInitMenu() (which is what i was getting at before) and then check to see if the change was undone when OnIniutMenuPopup() is called.
0

Featured Post

Migrating Your Company's PCs

To keep pace with competitors, businesses must keep employees productive, and that means providing them with the latest technology. This document provides the tips and tricks you need to help you migrate an outdated PC fleet to new desktops, laptops, and tablets.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question