C++ CMFCCaptionMenuButton替代方案?

C++ CMFCCaptionMenuButton替代方案?,c++,mfc,button,menu,C++,Mfc,Button,Menu,我需要为CDockablePane创建一个标题栏按钮,它将调用一个包含各种选项的菜单。我尝试使用CMFCCaptionMenuButton,按钮和菜单显示出来,但是菜单ID的消息映射方法没有启动。MFC文档指出,CMFCCaptionMenuButton用于内部基础设施,而不是真正用于代码 假设这就是我的问题所在,我应该使用CMFCCaptionBarButton然后创建一个单独的弹出菜单吗?以前有人在MFC中制作过类似的基于标题栏的菜单吗 下面是一些精简的代码片段,以防我在连接事件时犯了一个愚

我需要为
CDockablePane
创建一个标题栏按钮,它将调用一个包含各种选项的菜单。我尝试使用
CMFCCaptionMenuButton
,按钮和菜单显示出来,但是菜单ID的消息映射方法没有启动。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
}
BEGIN\u MESSAGE\u映射(CDockPane,CDockablePane)
ON_命令(ID_MORPH_浏览器,OnMorphBrowser)
结束消息映射()
void CDockPane::on按按钮(UINT nHit)
{
//仅适用于自定义按钮处理,不呼叫基地
//默认情况下,将处理关闭、最大化和pin
交换机(nHit)
{
案例ID_测试:
{
cmorphomenubutton*pButton=dynamic_cast(m_arrbutons.GetAt(m_morphIndex));
p按钮->显示菜单(此);
打破
}
}
}
void CDockPane::SetCaptionButtons()
{
CDockablePane::SetCaptionButtons();//用于关闭、锁定等
m_morphIndex=m_arrbutons.Add(新的cmorphenubutton(ID_MORPHTEST));
}
void CDockPane::OnMorphBrowser()
{
//在菜单项上做一些事情单击
}

编辑:删除了以前不再使用的代码

现在背景中蟋蟀的鸣叫声已经减弱,我想我将发布我目前的解决方法:

我不是继承和扩展
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);
    }
}

标题栏按钮的设置以及按钮和菜单点击事件的处理与问题中的定义相同,这是有效的。

如果考虑Aero/DWM,这肯定会失败。对于非客户端区域,它有一个完全不同的实现。我认为对于Aero/DWM,您必须采用完全不同的方法。你看过Firefox或Chromium吗?他们可能会给你一些有用的提示。@David什么是Aero/DWM?这不是一个浏览器,而是一个针对Windows7 64位的MFC应用程序。可能是回调名称让您绊倒了,这是我的实现所特有的,浏览器窗口是一个逐项列出的设备列表,而3d查看器窗口、分层导航器、统计仪表板等,etcAero是Vista中引入的新图形框架的营销名称。DWM是桌面窗口管理器,也是同一事物的一部分。这是在windows的非客户端区域处理玻璃效果的东西。啊,有趣的是,我没有任何专门与此相关的代码,但我只是用alt+tab测试了应用程序,无论我有浮动窗格还是停靠窗格,至少就玻璃效果而言,它似乎表现正常。