The menu objects are always grouped as sub or pop-up menus. Now, considering your code post, there is one crucial difference in creating pop-up menus. Firstly, you need to create a new CMenu object. Then initialize it with CreatePopupMenu like you have done. After that, you need to create a yet another CMenu item, and initialize it with CreatePopupMenu again. The second menu object behaves like a pop-up menu on the first one. In order to link these two, first add items and their respective command IDs to the second menu by using AppendMenu or InsertMenu. Then use AppendMenu/InsertMenu on the first menu object, and specify MF_POPUP flag in the first parameter. Adding a MF_STRING flag allows you to have an item text as well, specified in the third parameter. Instead of a command ID in the second parameter, you now must supply a handle to the sub-menu object (HMENU). You can get this from the second menu object by querying CMenu::operator HMENU or CMenu::m_hMenu. After this, you can launch the first menu object as a pop-up menu with a sub pop-up by calling TrackPopupMenuEx. Here is a complete code fragment to give you a better clue:
// Create a CMenu object and initialize
CMenu* pMenu = new CMenu();
pMenu->CreatePopupMenu();
// Create the sub pop-up menu object
CMenu* pSubMenu = new CMenu();
pSubMenu->CreatePopupMenu();
// Add menu items into the second menu
pSubMenu->AppendMenu( MF_STRING, 1, "Option 1" );
pSubMenu->AppendMenu( MF_STRING, 2, "Option 2" );
// Add the pop-up menu
pMenu->AppendMenu( MF_STRING | MF_POPUP, (UINT_PTR) pSubMenu->m_hMenu, "Sub menu" );
// Launch and do cleanup
pMenu->TrackPopupMenuEx(...);
pMenu->RemoveMenu( 0, MF_BYPOSITION );
pSubMenu->DestroyMenu(); delete pSubMenu; pSubMenu = NULL;
pMenu->DestroyMenu(); delete pMenu; pMenu = NULL;
I am not certain if the RemoveMenu call is necessary, as the menu cleanup code might have a routine that destroys sub-menus as well. Also, the code has no error-checking routines for possible error states like