Поиск:

Ответ в темуСоздание новой темы Создание опроса
> обработать CMenu у CView 
V
    Опции темы
17dufa
Дата 10.8.2009, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: нет
Всего: 5



Нужно удалить пункт из вьюшного меню в зависимости от настроек. Как это делается уже нашел. Проблема в другом: никак не могу найти, в какой же обработчик вставить свой код для удаления. Пробовал: CView::OnCreate, CView::OnInitialUpdate, CView::OnUpdate, CView::OnActivate, WM_SETFOCUS и даже WM_TIMER (таймер запускал в OnCreate). Постоянно получаю Assert 
Код

int FindMenuItem(CMenu* Menu, LPCTSTR MenuString)
{
    int count = Menu->GetMenuItemCount(); //!!! строка с Assert
    for (int i = 0; i < count; ++i)
    {
        CString str;
        if (Menu->GetMenuString(i, str, MF_BYPOSITION) &&
            (strcmp(str, MenuString) == 0))
        return i;
    }

    return -1;
}
....
//а вот этот код я и вставлял по разным обработчикам
    if (!CInfoHolder::GetInstance()->GetCanDelete())
    {
        CMenu * m = GetMenu();
        int iPos = FindMenuItem(m,"&Пользователь");
        if (iPos >= 0)
        {
            CMenu * sub = m->GetSubMenu(iPos);
            iPos = FindMenuItem(sub,"&Удалить");
            if (iPos >= 0)
            {
                sub->RemoveMenu(iPos, MF_BYPOSITION);
            }
        }
    }

Assert вылетает на первом же вызове FindMenuItem. Если не ошибаюсь срабатывает вот этот ASSERT(::IsMenu(m_hMenu)). Если не заморачиваться на FindMenuItem, а самому прописать индексы, то получаю этот же ассерт на строке 
Код

CMenu * sub = m->GetSubMenu(iPos);


Это сообщение отредактировал(а) 17dufa - 10.8.2009, 15:08
PM MAIL   Вверх
Earnest
Дата 10.8.2009, 12:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



А что ты понимаешь под "вьюшным меню"? Может, это меню динамически формируется?
В зависимости от этого нужно поступать по разному.
Но в общем случае самый удобный момент - это OnInitMenuPopup - т.е. непосредственно перед выпадением меню. Но получает это сообщение только собственник меню, а не кто попало. Т.е. если это меню SDI или MDI фрейма, то собственником является главное окно, а если контекстное меню, то то окно, которое указано в TrackPopupMenu.

Цитата(17dufa @  10.8.2009,  13:32 Найти цитируемый пост)
 Если не ошибаюсь срабатывает вот этот ASSERT(::IsMenu(m_hMenu)). 

Как тут можно ошибаться? Либо этот срабатывает, либо не этот, одладчик должен показать. Если это оно, то стало быть не нашел ты меню, невалидно оно.



--------------------
...
PM   Вверх
17dufa
Дата 10.8.2009, 13:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: нет
Всего: 5



Earnest, точно ASSERT(::IsMenu(m_hMenu)) smile 
вьюшное меню - это меню, которое я вижу при открытии CView, ID которого указывается в CMultiDocTemplate::CMultiDocTemplate(...). Я не знаю кому оно принадлежит, но думал, что CView.
с OnInitMenuPopup не вышло, обработчик просто не вызывается, видимо это только для popup, а это меню больше на MainMenu похоже.
Вышло так:
Код

BOOL CUserSplitterWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle, CWnd* pParentWnd, CCreateContext* pContext) 
{
    EXECUTOR_RAII raii;
    BOOL f = CMDIChildWnd::LoadFrame(nIDResource, dwDefaultStyle, pParentWnd, pContext);
    if (!CInfoHolder::GetInstance()->GetCanDelete())
    {
        if (m.m_hMenu != NULL)
            m.DestroyMenu();
        m.LoadMenu(nIDResource);
        int iPos = FindMenuItem(&m,"&Пользователь");
        if (iPos >= 0)
        {
            CMenu * sub = m.GetSubMenu(iPos);
            iPos = FindMenuItem(sub,"&Удалить");
            if (iPos >= 0)
            {
                sub->RemoveMenu(iPos, MF_BYPOSITION);
            }
        }
        GetParent()->GetParent()->SetMenu(&m);
    }
    return f;
}

это в классе, который указывается третьим аргументом в CMultiDocTemplate::CMultiDocTemplate():
Код

CMultiDocTemplate * docTemplate = new CMultiDocTemplate(IDR,
RUNTIME_CLASS(Doc),
RUNTIME_CLASS(CUserSplitterWnd), //ВОТ ЭТОТ КЛАСС
 RUNTIME_CLASS(View));


Это сообщение отредактировал(а) 17dufa - 10.8.2009, 15:08
PM MAIL   Вверх
Earnest
Дата 11.8.2009, 06:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Действительно, это меню вовсе не вью принадлежит, а главному фрейму. 
У него и надо бы OnInitMenuPopup ловить. Но это не кошерно: фрейм имеет свой обработчик OnInitMenuPopup, где для каждого подменю и каждой команды рассылает апдейты.
Вот их и надо обрабатывать, т.е. написать обработчик OnUpdate и поставить в карту - вот его можно и в карту вью, если так удобнее. Если не ошибаюсь, обработчик-апдейт попап меню вешается на идентификатор первой команды подменю. Отличить его от обработчика для собственно команды можно по члену CCmdUI:m_pSubMenu, который не нулевой. Там немного мутно, но не очень, хотя я конкретику подзабыла. Проще всего разобраться так: 1) найти обработчик фрейма OnInitMenuPopup и посмотреть как что рассылается 2) Найти обработчик mdi-фрейма, обновляющий меню Windows (где список открытых окон показывается) - как пример обновления подменю. Попробуй разобраться сам. А не сможешь, я поищу у себя куски кода с примерами.



--------------------
...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0433 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.