Merging Two Menus

This function will merge two menues. This can be used for context menus as
well as for top level menus. At top level known popup menus will be appended
or new popups will be created before <Window> or <Help> (currently
untested). The function calles itself recursivley and does not care about
consecutive seperators.


void MergeMenu( CMenu* pMenuDestination, CMenu* pMenuAdd, bool bTopLevel /*=false*/ )
{
// Abstract:
// Merges two menus.
//
// Parameters:
// pMenuDestination – [in, retval] destination menu handle

// pMenuAdd – [in] menu to merge
// bTopLevel – [in] indicator for special top level behavior
//
// Comments:
// This function calles itself recursivley. If bTopLevel is set to true,
// we append popups at top level or we insert before <Window> or <Help>.

// get the number menu items in the menus
int iMenuAddItemCount = pMenuAdd->GetMenuItemCount();
int iMenuDestItemCount = pMenuDestination->GetMenuItemCount();

// if there are no items return
if( iMenuAddItemCount == 0 )
return;

// if we are not at top level and the destination menu is not empty
// -> we append a seperator
if( !bTopLevel && iMenuDestItemCount > 0 )
pMenuDestination->AppendMenu( MF_SEPARATOR );

// iterate through the top level of <pMenuAdd>
for( int iLoop = 0; iLoop < iMenuAddItemCount; iLoop++ ) { // get the menu string from the add menu CString sMenuAddString; pMenuAdd->GetMenuString( iLoop, sMenuAddString, MF_BYPOSITION );

// try to get the submenu of the current menu item
CMenu* pSubMenu = pMenuAdd->GetSubMenu( iLoop );

// check if we have a sub menu
if( !pSubMenu )
{
// read the source and append at the destionation

VERIFY( pMenuDestination->AppendMenu(
pMenuAdd->GetMenuState( iLoop, MF_BYPOSITION ),
pMenuAdd->GetMenuItemID( iLoop ),
sMenuAddString ));
}
else
{
// create or insert a new popup menu item

// default insert pos is like ap
int iInsertPosDefault = -1;

// if we are at top level merge into existing popups rather than
// creating new ones
if( bTopLevel )

// try to find existing popup
for( int iLoop = 0; iLoop < iMenuDestItemCount; iLoop++ ) { // get the menu string from the destination menu CString sDest; pMenuDestination->GetMenuString( iLoop, sDest, MF_BYPOSITION );

// we got a hit -> merge the two popups
if( sMenuAddString == sDest )
{
// try to get the submenu of the desired destionation menu item
CMenu* pSubMenuDest = MenuDestination->GetSubMenu( iLoop );

if( pSubMenuDest )
{
// merge the popup recursivly and continue with for loop
MergeMenu( pSubMenuDest, pSubMenu );
continue;
}
}

// alternativ insert before <Window> or <Help>
if( iInsertPosDefault == -1 && (sDest == “&Window” || sDest == “&Help” ))
iInsertPosDefault = iLoop;
}
}

// if the top level search did not find a position append the menu
if( iInsertPosDefault == -1 )
iInsertPosDefault = pMenuDestination->GetMenuItemCount();

// create a new popup and insert before <Window> or <Help>
CMenu NewPopupMenu;
VERIFY( NewPopupMenu.CreatePopupMenu() );

// merge the new popup recursivly
MergeMenu( &NewPopupMenu, pSubMenu );

// insert the new popup menu into the destination menu

VERIFY( pMenuDestination->InsertMenu(
iInsertPosDefault,
MF_BYPOSITION | MF_POPUP | MF_ENABLED,
(UINT)NewPopupMenu.GetSafeHmenu(),
sMenuAddString ));

// don’t destroy the new menu
NewPopupMenu.Detach();
}
}
}

More by Author

Must Read