Альтернатива CMFCCaptionMenuButton?

Мне нужно создать кнопку панели заголовка для CDockablePane, которая вызовет меню с различными параметрами. Я попытался использовать CMFCCaptionMenuButton, и кнопка и меню отображаются, но методы карты сообщений для идентификаторов меню не срабатывают. В документации MFC указано, что CMFCCaptionMenuButton предназначен для внутренней инфраструктуры, а не для вашего кода.

Итак, если предположить, что это моя проблема, должен ли я использовать CMFCCaptionBarButton, а затем создавать отдельное всплывающее меню? Кто-нибудь раньше делал подобное меню на основе строки заголовка в MFC?

Вот несколько сокращенных фрагментов кода на случай, если я допустил глупую ошибку при подключении событий:

BEGIN_MESSAGE_MAP(CDockPane, CDockablePane)
    ON_COMMAND(ID_MORPH_BROWSER, OnMorphBrowser)
END_MESSAGE_MAP()

void CDockPane::OnPressButtons(UINT nHit)
{
    // only for custom button handling don't call base
    // close, maximize, and pin will be handled by default

    switch (nHit)
    {
        case ID_MORPHTEST:
        {
            CMorphMenuButton* pButton = dynamic_cast<CMorphMenuButton*>(m_arrButtons.GetAt(m_morphIndex));
            pButton->ShowMenu(this);
            break;
        }
    }
}

void CDockPane::SetCaptionButtons()
{
    CDockablePane::SetCaptionButtons(); // for close, pin etc

    m_morphIndex = m_arrButtons.Add(new CMorphMenuButton(ID_MORPHTEST));
}

void CDockPane::OnMorphBrowser()
{
    // do stuff on menu item click
}

Изменить: удален предыдущий код, который больше не используется.


person AJG85    schedule 03.03.2011    source источник
comment
Конечно, это обречено на провал, если учесть Aero/DWM. У него совсем другая реализация для неклиентской области. Я думаю, у вас должен быть совершенно другой подход к Aero/DWM. Вы смотрели на Firefox или Chromium? Они могут дать вам несколько полезных советов.   -  person David Heffernan    schedule 21.03.2011
comment
@David Что такое Aero/DWM? Это не браузер, а приложение MFC, предназначенное для 64-разрядной версии Windows 7. Возможно, имя обратного вызова могло сбить вас с толку, особенно в моей реализации, где окно браузера представляет собой подробный список оборудования, а не окно 3D-просмотра, иерархический навигатор, панель статистики и т. д. и т. д.   -  person AJG85    schedule 21.03.2011
comment
Aero — это маркетинговое название нового графического фреймворка, представленного в Vista. DWM — это диспетчер окон рабочего стола, часть того же самого. Это то, что обрабатывает стеклянные эффекты в неклиентских областях окон.   -  person David Heffernan    schedule 21.03.2011
comment
Ах, интересно, у меня нет никакого кода, специально связанного с этим, но я только что протестировал приложение с помощью alt + tab, и независимо от того, есть ли у меня плавающие или закрепленные панели, кажется, что оно ведет себя правильно, по крайней мере, в отношении эффекта стекла.   -  person AJG85    schedule 21.03.2011


Ответы (1)


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

Вместо того, чтобы наследовать и расширять CMFCCaptionMenuButton, я создаю свой класс, расширяя CMFCCaptionButton. Затем я создаю меню и предоставляю метод ShowMenu для явного вызова при обработке событий пользовательских кнопок, а также переопределяю GetIconID, чтобы возвращать конкретный системный значок для кнопки для каждого меню, добавленного в панель заголовка, заканчивая чем-то вроде этого для пример, указанный в вопросе:

#pragma once

// CMorphMenuButton command target

class CMorphMenuButton : public CMFCCaptionButton
{
public:
    CMorphMenuButton(UINT nHit);
    virtual ~CMorphMenuButton();

    virtual CMenuImages::IMAGES_IDS GetIconID (BOOL bHorz, BOOL bMaximized) const;
    void ShowMenu(CWnd* pWnd);

private:
    CMenu m_dockMenu;
    CMenu* m_subMenu;
};

// MorphMenuButton.cpp : implementation file
//

#include "stdafx.h"
#include "MorphMenuButton.h"


// CMorphMenuButton
CMorphMenuButton::CMorphMenuButton(UINT nHit)
    : CMFCCaptionButton(nHit)
{
    SetMiniFrameButton(); // already defaulted?

    m_dockMenu.LoadMenu(IDR_DOCKPANE); // resource ID for dock pane menus
}

CMorphMenuButton::~CMorphMenuButton()
{
    m_dockMenu.DestroyMenu();
}

CMenuImages::IMAGES_IDS CMorphMenuButton::GetIconID(BOOL bHorz, BOOL bMaximized) const
{
    return CMenuImages::IdArrowForward;
}

void CMorphMenuButton::ShowMenu(CWnd* pWnd)
{
    CRect windowRect, buttonRect;
    pWnd->GetWindowRect(&windowRect);
    buttonRect = GetRect();
    CPoint menuPos(windowRect.left + buttonRect.right, windowRect.top + buttonRect.bottom);

    m_subMenu = m_dockMenu.GetSubMenu(0);
    if (!m_subMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, menuPos.x, menuPos.y, pWnd))
    {
        DWORD id = GetLastError();
        wchar_t errMsg[256];
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, id, 0, errMsg, sizeof(errMsg), 0);
        MessageBox(0, errMsg, L"Error", MB_OK);
    }
}

Настройка кнопок панели заголовка и обработка событий щелчка для кнопок и меню такие же, как указано в вопросе, и это работает.

person AJG85    schedule 21.03.2011