Я хотел бы добавить пункт меню в свое главное меню, а затем заполнить его элементами во время выполнения. Как мне это сделать? И помимо добавления элементов, как у меня будет запись в виде карты сообщений, поскольку я не знаю идентификатор?
Динамическое меню с использованием mfc
Ответ 1
Вы можете создать объект CMenu
динамически следующим образом:
CMenu *menu = new CMenu;
menu->CreatePopupMenu();
// Add items to the menu
menu->AppendMenu(MF_STRING, menuItemID, "Text");
...
Затем добавьте это подменю в главное меню:
wnd->GetMenu()->AppendMenu(MF_POPUP, (UINT_PTR)menu->m_hMenu, "Menu Name");
Что касается карты сообщений, если все идентификаторы элементов меню находятся в определенном диапазоне, вы можете использовать ON_COMMAND_RANGE
для отображения всего диапазон до одной функции. Эта функция получит идентификатор в качестве параметра, и внутри этой функции вы можете выполнять различные операции на основе идентификатора.
Ответ 2
define the menu using #define
#define ID_SHOW 2002
#define ID_HIDE 2004
//create a menu object for main menu
CMenu *menu = new CMenu();
menu->CreateMenu();
//another menu object for submenu
CMenu *subMenu = new CMenu();
subMenu->CreatePopupMenu();
subMenu->AppendMenu(MF_STRING, ID_HIDE, _T("four"));
subMenu->AppendMenu(MF_STRING, ID_SHOW, _T("three"));
//append submenu to menu
menu->AppendMenu(MF_POPUP|MF_STRING, (UINT)subMenu->m_hMenu, _T("Advanced") );
SetMenu(menu);
Ответ 3
CMenu menuPopup;
menuPopup.LoadMenu(IDR_CNTXT_PLAN);
subMenu.CreatePopupMenu();
subMenu.AppendMenu(MF_STRING, MENU1,"Menu1");
subMenu.AppendMenu(MF_STRING, MENU2,"Menu2");
CMenu* pMenu = menuPopup.GetSubMenu(0);
pMenu->InsertMenu(0,MF_BYPOSITION|MF_POPUP,(UINT)subMenu.m_hMenu,"Layers");
menuPopup.GetSubMenu(0)->InsertMenu(1,MF_BYPOSITION|MF_SEPARATOR,0,"");
menuPopup.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this);
Ответ 4
Следующий пример, если вы хотите динамически добавить пункт меню & также прикрепите данные к этому пункту меню.
struct MyStruct
{
int abc;
};
CMenu MyMenu;
MyMenu.CreatePopupMenu();
CMenu MyMainMenu;
VERIFY(MyMainMenu.LoadMenu(IDR_MAIN_MENU_ID));
MyMainMenu.InsertMenu(0, MF_POPUP, (UINT_PTR)MyMenu.m_hMenu, _T("Main Menu"));
const int iMenuAdds = 5;
for (int i = 0; i < iMenuAdds; ++i)
{
MyStruct myStruct;
myStruct.abc = i+10001;
CString MenuDesc;
MenuDesc.Format(_T("MenuNo: %d"), i);
MENUITEMINFO tmpItem;
tmpItem.fMask = MIIM_STRING | MIIM_ID | MIIM_DATA;
tmpItem.fType = MFT_STRING;
tmpItem.fState = MFS_ENABLED;
tmpItem.wID = i + 101; //See note 1. below.
tmpItem.dwItemData = (ULONG_PTR)&myStruct; //data set.
tmpItem.dwTypeData = MenuDesc.GetBuffer(); //string description
tmpItem.cch = MenuDesc.GetLength();
tmpItem.cbSize = sizeof(tmpItem);
MyMenu.InsertMenuItem(i, (LPMENUITEMINFO)& tmpItem, FALSE);
}
Для получения пункта меню & связанные данные:
CMenu* pPopup = &MyMenu; //or CMenu* pPopup = MyMainMenu.GetSubMenu(0); depending on parent.
ULONG_PTR lRetVal = pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, point.x, point.y, this, NULL);
//^^lRetVal should return same value as tmpItem.wID above.
MENUITEMINFO tmpItem;
tmpItem.cbSize = sizeof(MENUITEMINFO);
tmpItem.fMask = MIIM_STRING | MIIM_ID | MIIM_DATA;
tmpItem.fType = MFT_STRING;
TCHAR dwTypeData[256];
tmpItem.dwTypeData = dwTypeData;
tmpItem.cch = 256;
pPopup->GetMenuItemInfo(lRetVal, &tmpItem, FALSE);
MyStruct *myStruct = (MyStruct*)tmpItem.dwItemData; //and now we have our data.
- Используется как ваш #define & может использоваться для ON_COMMAND_RANGE (idFirst, idLast, Function), поэтому все равно необходимо иметь какой-то определенный диапазон, если вы планируете использовать ON_COMMAND_RANGE. В качестве альтернативы: используйте диапазон команд для динамического меню или создайте свой собственный в наборе данных. Также необходимо убедиться, что все используемые диапазоны не конфликтуют с какими-либо уже определенными пунктами меню в том же или родительском меню.
Добавленный выше, поскольку я нашел эту нить от googling из-за проблемы & Я уже использовал метод принятых ответов для добавления пунктов меню.