cbursk
asked on
How to disable a submenu item that is a popup menu?
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.
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/
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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;
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;
ASKER
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?
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?
ASKER
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?!?
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.
Are there 6 items in the sub-menu you obtained? You specified an index of 5, that is for the 6th item.
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..
ASKER
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.
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.
>> 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.
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.
ASKER
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->GetMenuItemCou nt();
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->GetMenuItemCou nt();
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
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->GetMenuItemCou
for ( int i = 0; i < z; i++ )
{
pPopupMenu->EnableMenuItem
}
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->GetMenuItemCou
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
}
}
By changing the last if to look for NULL or !NULL I can exclude popup or vica-versa
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.
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.
You can insert a menu item into a menu by using InsertMenuItem() function
Let me know if you have any questions.