CMFCMenuBar - проблемы применения
От: AlexGin Беларусь  
Дата: 31.10.14 11:25
Оценка:
В разрабатываемом приложении на MFC9 (MSVS 2008) применяю MFC Feature Pack.
Певоначально, когда визард генерирует каркас приложения для MDI-application, меню и тулбар плавающие.
При этом, меню главного окна — это объект класса CMFCMenuBar.

Пользователи нередко "утаскивали" это меню за пределы экрана, а потом жаловались, что пропало меню.
Лечить приходилось чисткой той ветки реестра Windows, что отвечает за мое приложение. Обычно это: HKCU\Software...

Я задумался — как исправить проблему. Нашел вот этот материал:

http://social.msdn.microsoft.com/Forums/en-US/ca76b6c4-bcda-4855-8391-a3dc8310b74a/how-to-disable-the-cmfcmenubar-from-floating?forum=vcgeneral

Это вроде помогло — прибил меню "гвоздиками"

Однако, на днях выяснилась проблема — панели тулбаров иногда оказываются прикрыты этим самым меню, которое "прибито гвоздиками"

В общем — думаю, как с этим бороться?
Re: CMFCMenuBar - проблемы применения
От: AlexGin Беларусь  
Дата: 31.10.14 11:56
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>В разрабатываемом приложении на MFC9 (MSVS 2008) применяю MFC Feature Pack.

AG>Певоначально, когда визард генерирует каркас приложения для MDI-application, меню и тулбар плавающие.
AG>При этом, меню главного окна — это объект класса CMFCMenuBar.

AG>Пользователи нередко "утаскивали" это меню за пределы экрана, а потом жаловались, что пропало меню.

AG>Лечить приходилось чисткой той ветки реестра Windows, что отвечает за мое приложение. Обычно это: HKCU\Software...

Пока я остановился на таком вот решении:

1) В классе, наследнике CMFCMenuBar, переопределяем виртуальный метод OnBeforeFloat:

class CMyMenuBar : public CMFCMenuBar 
{
public:
    virtual BOOL OnBeforeFloat(CRect& rectFloat, AFX_DOCK_METHOD dockMethod)
    {
        if (dockMethod != DM_DBL_CLICK)
            return CMFCMenuBar::OnBeforeFloat(rectFloat, dockMethod); 
        else
            return FALSE;
    };
};

В этом методе просто заблокирован переход меню в плавающее состояние, когда пользователь (возможно, по ошибке) дал по нему двойной-клик.

2) В классе главного окна CMainFrame — тип объекта меню теперь новый: CMyMenuBar, с переопределенным виртуальным методом OnBeforeFloat.

3) В обработчике CMainFrame::OnCreate — все так, как первоначально сгенерировано визардом, одноко я здесь убираю "гриппер" главного меню:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1)
        return -1;

    BOOL bNameValid;

    if (!m_wndMenuBar.Create(this))
    {
        TRACE0("Failed to create menubar\n");
        return -1;      // fail to create
    }

    m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);
    m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() & ~CBRS_GRIPPER); // Я добавил эту строку, для удаления "гриппера" (AlexGin)!!!

    // prevent the menu bar from taking the focus on activation
    CMFCPopupMenu::SetForceMenuFocus(FALSE);
    ...............................................................
    ...............................................................
    CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005));

    return 0;
}


После этих доработок, головное меню уже не "прибито гвоздиками" и в то же время уже не слетает при двойном клике пользователя.
Теперь, главное меню функционорует аналогично главному меню в Visual Studio 2008.

З.Ы. Подчеркиваю, что все доработки, рекомендованные для CMainFrame::OnCreate в приведенной ранее статье с форума social.msdn я откатил,
сделав так, как первоначально сгенерировал визард студии.
Отредактировано 31.10.2014 12:02 AlexGin . Предыдущая версия . Еще …
Отредактировано 31.10.2014 11:58 AlexGin . Предыдущая версия .
Re: CMFCMenuBar - проблемы применения
От: rus blood Россия  
Дата: 05.11.14 16:40
Оценка: +1
Здравствуйте, AlexGin, Вы писали:

AG>В общем — думаю, как с этим бороться?


Я переопределял LoadState/SaveState.
Классы, из которых состоит CMFCMenuBar, читают/записывают разную информацию в реестр — положение, состояние, набор команд и т.п.
Переопределяя методы, можно добавить корректировку положения на экране в плавающем состоянии.

Я, в частности, убирал "кастомизацию" набора кнопок на панелях инструментов.
Для пользователей эта фича не предполагалась, а в разработке сильно мешала.
Имею скафандр — готов путешествовать!
Re[2]: CMFCMenuBar - проблемы применения
От: AlexGin Беларусь  
Дата: 02.02.15 15:16
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>1) В классе, наследнике CMFCMenuBar, переопределяем виртуальный метод OnBeforeFloat:


AG>
AG>class CMyMenuBar : public CMFCMenuBar 
AG>{
AG>public:
AG>    virtual BOOL OnBeforeFloat(CRect& rectFloat, AFX_DOCK_METHOD dockMethod)
AG>    {
AG>        if (dockMethod != DM_DBL_CLICK)
AG>            return CMFCMenuBar::OnBeforeFloat(rectFloat, dockMethod); 
AG>        else
AG>            return FALSE;
AG>    };
AG>}; 
AG>

AG>В этом методе просто заблокирован переход меню в плавающее состояние, когда пользователь (возможно, по ошибке) дал по нему двойной-клик.

Более правильным решением (после feedback со стороны юзверов) мне видится такое:
class CMyMenuBar : public CMFCMenuBar 
{
public:
    virtual BOOL OnBeforeFloat(CRect& rectFloat, AFX_DOCK_METHOD dockMethod)
    {
        if ((dockMethod != DM_DBL_CLICK) && (dockMethod != DM_MOUSE)) // Добавлено DM_MOUSE
            return CMFCMenuBar::OnBeforeFloat(rectFloat, dockMethod); 
        else
            return FALSE;
    };
};


Теперь уже у пользователя нет шансов "утащить" головное меню приложения, даже если пользователь "после хорошей бутылкы"
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.