Solved

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

Posted on 2000-03-31
11
2,274 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
 

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
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
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

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
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 use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

746 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

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now