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

  • U.S. companies are desperately trying to recruit and hire skilled software engineers and developers, but there is simply not enough quality talent to go around. Tiempo Development is a nearshore software development company. Our headquarters are in AZ, but we are a pioneer and leader in outsourcing to Mexico, based on our three software development centers there. We have a proven process and we are experts at providing our customers with powerful solutions. We transform ideas into reality.

  • Temporary network outages -- even those lasting just a few minutes -- can cripple organizations that rely on local Internet access at remote locations. Failover systems that automatically switch to 4G LTE cellular when landlines go down let organizations maximize uptime, even when the unexpected happens. Read this white paper to learn how 4G failover systems that use standalone gateways supported by a cloud-based management tool are proving to be a solid choice for improved business continuity and productivity …

Most Popular Programming Stories

More for Developers

RSS Feeds

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