Solved

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

Posted on 2000-03-31
11
2,359 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

863 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

19 Experts available now in Live!

Get 1:1 Help Now