Удаление меню из строки меню и из памяти
Вопрос:Моё приложение создаёт меню и добавляет его используя IAcadPopupMenus.Add. Удаление его позднее при помощи RemoveMenuFromMenuBar или IAcadPopupMenu.RemoveFromMenuBar работает, но повторная попытка добавить тоже самое меню терпит неудачу. Почему и как это исправить?
Ответ:
Хотя пользовательское меню может быть удалено из строки меню после добавления, меню остаётся в памяти AutoCAD. Это можно проверить если сравнить значения IAcadPopupMenus.GetCount() до и после удаления меню – значение останется тем же, так как меню остаётся внутри коллекции меню. Пожалуйста проверьте демонстрационный код ниже: он добавляет 3 меню в первую группу меню. Запустите снова и код удалит одно меню, и сравните счетчик меню до и после удаления.
Если меню добавлено таким способом оно остаётся в памяти до конца сессии AutoCAD. Любые меню, которые были добавлены, остаются до конца сессии. Любое меню, которое уже было добавлено в течение сессии AutoCAD может быть повторно вставлено в строку меню. Метод Add не следует вызвать повторно, так как при этом программа может завершиться аварийно.
Но что будет если ваше приложение выгружено и программа пытается почистить за собой, удаляя меню из строки меню? Меню останется резидентным до конца работы AutoCAD, а приложение повторно загруженное попытается создать и добавть меню повторно в строку меню, что может привести к аварийному завершению.
Хотя вы, возможно, сможете избежать этой проблемы путем перебора меню для проверки меню, которое имеет имя вашего меню. Если нашли, то не вызывайте Add, а вместо этого, получив указатель на существующее меню используйте InsertMenuInMenuBar(). Но к сожалению, это тоже приводит к аварийному завершению, так как указатели на меню недоступны.
В этом случае создавайте свои меню в своей собственной группе меню, которая полностью выгружается при выгрузке приложения в UnLoad().
- // Разрешаем меню загружаться/выгружаться в одной команде.
- static bool bIsMenuLoaded = false;
- void demo()
- {
- AutoCAD::IAcadApplication *pAcad;
- AutoCAD::IAcadMenuBar *pMenuBar;
- AutoCAD::IAcadMenuGroups *pMenuGroups;
- AutoCAD::IAcadMenuGroup *pMenuGroup;
- AutoCAD::IAcadPopupMenus *pPopUpMenus;
- AutoCAD::IAcadPopupMenu *pPopUpMenu;
- AutoCAD::IAcadPopupMenuItem *pPopUpMenuItem;
- HRESULT hr = NOERROR;
- LPUNKNOWN pUnk = NULL;
- LPDISPATCH pAcadDisp = acedGetIDispatch(TRUE);
- if(pAcadDisp==NULL)
- return;
- hr = pAcadDisp->QueryInterface(AutoCAD::IID_IAcadApplication,(void**)&pAcad);
- pAcadDisp->Release();
- if (FAILED(hr))
- return;
- pAcad->put_Visible(true);
- pAcad->get_MenuBar(&pMenuBar);
- pAcad->get_MenuGroups(&pMenuGroups);
- pAcad->Release();
- long numberOfMenus;
- pMenuBar->get_Count(&numberOfMenus);
- pMenuBar->Release();
- VARIANT index;
- VariantInit(&index);
- V_VT(&index) = VT_I4;
- V_I4(&index) = 0;
- pMenuGroups->Item(index, &pMenuGroup);
- pMenuGroups->Release();
- pMenuGroup->get_Menus(&pPopUpMenus);
- pMenuGroup->Release();
- if (!bIsMenuLoaded) {
- // Добавляем три меню
- HRESULT hr = pPopUpMenus->Add(
- _T("myDemoMenu1"), &pPopUpMenu);
- hr = pPopUpMenus->Add(
- _T("myDemoMenu2"), &pPopUpMenu);
- hr = pPopUpMenus->Add(
- _T("myDemoMenu3"), &pPopUpMenu);
- if (hr == S_OK) {
- acutPrintf(_T("\nМеню создано."));
- } else {
- acutPrintf(_T("\nМеню не создано."));
- }
- bIsMenuLoaded = true;
- }
- else // Удаляем меню
- {
- long count = 0;
- pPopUpMenus->get_Count(&count);
- acutPrintf(_T("\n Счетчик до удаления: %d"),count) ;
- long indexOfMyMenu = -1;
- AutoCAD::IAcadPopupMenu* eachMenu = NULL;
- for (long i=0; i< count; i++)
- {
- BSTR np;
- pPopUpMenus->Item(_variant_t(i),&eachMenu);
- eachMenu->get_Name(&np);
- // Удаляем первое меню в группе
- if (_tcscmp(np, _T("myDemoMenu1"))==0)
- {
- indexOfMyMenu = i;
- break;
- }
- }
- // Удаляем
- if(indexOfMyMenu > -1)
- {
- HRESULT hr = pPopUpMenus->RemoveMenuFromMenuBar(_variant_t(indexOfMyMenu));
- assert (hr == S_OK);
- }
- pPopUpMenus->get_Count(&count);
- // Снова пересчитываем после удаления.
- acutPrintf(_T("\n Счетчик после удаления: %d"),count) ;
- bIsMenuLoaded = false;
- }
- pPopUpMenus->Release();
- }
Источник: http://adndevblog.typepad.com/autocad/2013/02/remove-a-menu-from-the-menubar-_and_-memory.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=2874
Опубликовано 23.07.2015Отредактировано 24.07.2015 в 19:57:13