Finding a menuitem from command id

This is taken from a Doc/View-App that is mostly straight from the AppWizard of VC5.

I recently got the Problem, that I had to insert Menuitem at a specific position _below_ a defined MenuItem. Unfortunaletly I found no easy way to enumerate all item in the menubar, so I had to do it myself. In MFC there is a func to get the Command-ID if you know the Menu and Position but no func gives you the Menu and the Menupos from the CommandID :-(

This function will find the first menu item with the given command id looping through the submenu until it is found.

It is used like this:


	CWnd* pWnd = AfxGetMainWnd();
	CMenu *pMenu = pWnd->GetMenu();
	int m_Pos = 0;
	CMenu *pmMenu = pMenu;

	// Insert the Menuitem ID_DUMPRECORD exactly 2 Positions below FileSaveAs
	FindMenuPos( pMenu, ID_FILE_SAVE_AS, pmMenu, m_Pos );

	m_Pos += 2;

	InsertMenu(pmMenu, m_Pos, MF_BYPOSITION, ID_DUMPRECORD, "Print Record" );

with a little Hack for InsertMenu:


void CMainFrame::InsertMenu(CMenu* pMenu, UINT oldID, int Flags, UINT newID, const char * MenuText)
{
	if( pMenu == NULL )     return;
	if(pMenu->GetMenuState( newID, Flags) == 0xFFFFFFFF )
		pMenu->InsertMenu(oldID, Flags, newID, MenuText );
	else
		SetMenuState( newID, MF_ENABLED );
}

void CMainFrame::InsertMenu(UINT oldID, int Flags, UINT newID, const char * MenuText)
{
	CWnd* pWnd = AfxGetMainWnd();
	CMenu *pMenu = pWnd->GetMenu();
	InsertMenu(pMenu, oldID, Flags, newID, MenuText);
}

So that my InsertMenu inserts the MenuItem if it dos not exist, if it exist, it will be enabled.

Find a specific Menupos based on the Command-ID

I havn't cheched it with cascading submenues, but IF MS tells the truth about their MFC-functions, there should be no problems.


bool CMainFrame::FindMenuPos(CMenu *pBaseMenu, UINT myID, CMenu * & pMenu, int & mpos)
{
	// REMARK: pMenu is a pointer to a Cmenu-Pointer
	int myPos;
	if( pBaseMenu == NULL )
	{
		// Sorry, Wrong Number
		pMenu == NULL;
		mpos = -1;
		return true;
	}
	for( myPos = pBaseMenu->GetMenuItemCount() -1; myPos >= 0; myPos-- )
	{
		int Status = pBaseMenu->GetMenuState( myPos, MF_BYPOSITION);
		CMenu* mNewMenu;
		
		if( Status == 0xFFFFFFFF )
		{
			// That was not an legal Menu/Position-Combination
			pMenu = NULL;
			mpos = -1;
			return true;
		}
		// Is this the real one?
		if( pBaseMenu->GetMenuItemID(myPos) == myID )
		{
			// Yep!
			pMenu = pBaseMenu;
			mpos = myPos;
			return true;
		}
		// Maybe a subMenu?
		mNewMenu = pBaseMenu->GetSubMenu(myPos);
		// This function will return NULL if ther is NO SubMenu
		if( mNewMenu != NULL )
		{
			// rekursive!
			bool found = FindMenuPos( mNewMenu, myID, pMenu, mpos);
			if(found)
				return true;	// return this loop
		}
		// I have to check the next in my loop
	}
	return false; // iterate in the upper stackframe
}



Comments

  • Just what I needed

    Posted by Legacy on 03/25/2003 12:00am

    Originally posted by: moodboom

    Too bad this isn't part of CMenu, thanks for filling that gap.

    Reply
  • undefined function SetMenuState( newID, MF_ENABLED )

    Posted by Legacy on 09/29/1999 12:00am

    Originally posted by: zhiwen

    Undefined function SetMenuState( newID, MF_ENABLED )on VC 6.0;
    
    

    Another bug is at:
    // That was not an legal Menu/Position-Combination
    pMenu == NULL;
    mpos = -1;
    return true;

    it sould be:
    pMenu = NULL;
    ...

    To prevent from inserting twice:

    if (!FindMenuPos( pMenu, ID_DUMPRECORD, pmMenu, m_Pos ))
    {
    FindMenuPos( pMenu, ID_FILE_SAVE_AS, pmMenu, m_Pos );

    m_Pos += 2;

    InsertMenu(pmMenu, m_Pos, MF_BYPOSITION, ID_DUMPRECORD, "Print Record" );
    }

    Reply
  • what if menu is defined twice?

    Posted by Legacy on 10/30/1998 12:00am

    Originally posted by: Corey House

    So what happens if you have a menu item defined twice in the menu, does this only return the first one?

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Featuring Kate Leggett, VP and Principal Analyst, Forrester Research Live Event Date: October 19, 2016 @ 10 AM PT / 1 PM ET Omnichannel self-service is the new paradigm. Firms are organizing to provide self-service options across all channels in order to meet customer needs and expectations—going beyond traditional IVR. Are you prepared to offer your customers personalized self-service across all channels including legacy applications like your IVR?

  • The future of cloud platforms is at hand. Even if your cloud applications are basic now, your next set of apps will require strong analytics services and tools, as well as features that ease enterprise integration. To fill these needs, consider using not only your current cloud provider but also specialists. Take advantage of not only the big cloud platforms, but also specialized providers in vertical industries; countries and regions; and functional domains including omnichannel, analytics, integration, and …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date