关于带下拉菜单的TOOLBAR按钮

madbunny 2012-09-21 02:47:46
网上经常会搜到跟这个内容差不多的帖子:
http://wenku.baidu.com/view/6bda2a630b1c59eef8c7b4fd.html

大意是说,要设置按钮风格,建立消息响应,在响应函数里弹出一个cmenu……等等。
我的代码是这样的:
// mainframe声明
class CMainFrame : public CFrameWnd
{

private:
CToolBar m_ToolBar;
CMenu m_AIMenu;


protected: // 仅从序列化创建
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)

// 属性
public:

// 操作
public:
void CreateToolBar();
// 重写
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

// 实现
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

protected: // 控件条嵌入成员
CStatusBar m_wndStatusBar;

// 生成的消息映射函数
protected:
afx_msg void OnAIClicked();
afx_msg void OnCDClicked();
afx_msg void OnUpdateUI(CCmdUI *pCmdUI);
afx_msg void OnToolBarButtonDown(NMHDR* pnmh, LRESULT* plRes);

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()

};

// 消息映射
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_CREATE()
ON_UPDATE_COMMAND_UI( ID_BUTTON_AI, OnUpdateUI )
ON_UPDATE_COMMAND_UI( ID_BUTTON_CD, OnUpdateUI )
ON_COMMAND(ID_BUTTON_CD, OnCDClicked)
ON_COMMAND(ID_BUTTON_AI, OnAIClicked)
ON_NOTIFY(TBN_DROPDOWN, IDR_TOOLBAR, OnToolBarButtonDown)

END_MESSAGE_MAP()

// OnCreate
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;

if (!m_wndStatusBar.Create(this))
{
TRACE0("未能创建状态栏\n");
return -1; // 未能创建
}
m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT));

this->CreateToolBar();

return 0;
}

// CreateToolBar
void CMainFrame::CreateToolBar()
{
this->m_ToolBar.Create(this);
this->m_ToolBar.LoadToolBar(IDR_TOOLBAR);

// make it possiable to let the tool bar contain drop-down menu
m_ToolBar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS);
m_ToolBar.GetToolBarCtrl().SendMessage(TB_SETEXTENDEDSTYLE, 0, (LPARAM)TBSTYLE_EX_DRAWDDARROWS);

// set button ID_3D_VIEW_ZSTEST to be a drop-down-menu button
DWORD dwStyle= m_ToolBar.GetButtonStyle(m_ToolBar.CommandToIndex(ID_BUTTON_AI));
dwStyle |= TBSTYLE_DROPDOWN;
m_ToolBar.SetButtonStyle(m_ToolBar.CommandToIndex(ID_BUTTON_AI), dwStyle);

return;
}

void CMainFrame::OnUpdateUI(CCmdUI *pCmdUI)
{
pCmdUI->Enable(IDR_TOOLBAR);
m_ToolBar.GetToolBarCtrl().EnableButton(ID_BUTTON_AI,true);
m_ToolBar.GetToolBarCtrl().EnableButton(ID_BUTTON_CD,true);
return;
}

void CMainFrame::OnToolBarButtonDown(NMHDR* pnmh, LRESULT* plRes)
{
LPNMTOOLBAR pnmtb = reinterpret_cast<LPNMTOOLBAR>(pnmh);
CWnd *pWnd;
UINT nID;
::AfxMessageBox(_T("C3DFrameDlg::On3DFrameToolBarDropDown"),0);
switch (pnmtb->iItem)
{
case IDR_TOOLBAR:
pWnd = &m_ToolBar;
nID = IDR_MENU_AI;
break;
default:
return;
}
::AfxMessageBox(_T("after switch"),0);
CMenu TestMenu;
TestMenu.LoadMenu(nID);
CMenu* pPopup = TestMenu.GetSubMenu(0);
ASSERT( pPopup);
CRect rc;
pWnd->SendMessage(TB_GETRECT,pnmtb->iItem,(LPARAM)&rc);
pWnd->ClientToScreen(&rc);
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
rc.left,rc.bottom,this,&rc);

return ;
}

void CMainFrame::OnCDClicked()
{
::AfxMessageBox(_T("CD"),0);

return ;
}

void CMainFrame::OnAIClicked()
{
::AfxMessageBox(_T("AI"),0);

return ;
}


基本上是网上照搬的了,可是为什么我做出来的按钮那个黑色的向下箭头点不动呢???那个黑色的箭头一直处于普通按钮鼠标放上去才会成为的那种状态,高亮。求拯救啊,折腾3天了……我发誓我回家肯定好好看书啊!!!
而且创建toolbar的地方那句sendmessage是要闹哪样啊???

...全文
291 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
schlafenhamster 2012-09-27
  • 打赏
  • 举报
回复
例如:
‘IDR_NEW_MENU’
中建立
SUB_MUNE1 // popup 属性
这样就有了个箭头。
在箭头后建立:
IDC_SUB1_XXXX
。。。

然后:
SUB_MUNE2 // popup 属性
。。。

消息响应:
点IDC_SUB1_XXXX
点wizzard
加消息。。。
schlafenhamster 2012-09-26
  • 打赏
  • 举报
回复
'那么我怎么根据notify的参数来判断'
你在资源中打开那个‘IDR_NEW_MENU’
在menu的某项,用向导 给你加 响应 (应该是 command)。
就是说:
pPopup->TrackPopup……
只负责弹出 菜单,它与响应菜单 没关系了。
madbunny 2012-09-26
  • 打赏
  • 举报
回复
是有多个需要弹出菜单的按钮,每个按钮对应不同的菜单。[Quote=引用 15 楼 的回复:]

是多级菜单?
[/Quote]
schlafenhamster 2012-09-26
  • 打赏
  • 举报
回复
是多级菜单?
madbunny 2012-09-26
  • 打赏
  • 举报
回复
我的意思是说,在同一个toolbar上存在多个需要弹出窗口的menu,而不是每个toolbar只有一个按钮。所以一定要知道是哪个按钮啊。[Quote=引用 13 楼 的回复:]

TOOLBAR每个都有OnNotify
在每个中用不同的menu
[/Quote]
schlafenhamster 2012-09-26
  • 打赏
  • 举报
回复
TOOLBAR每个都有OnNotify
在每个中用不同的menu
madbunny 2012-09-26
  • 打赏
  • 举报
回复
对啊,我就是这个意思。因为有多个菜单,我得知道是哪个按钮引发的才行啊,这样才能弹出相应的菜单啊。[Quote=引用 11 楼 的回复:]

"引发弹出菜单的按钮有多个"
多个按钮弹出一个菜单?
通常是
多个按钮弹出多个菜单。
[/Quote]
schlafenhamster 2012-09-26
  • 打赏
  • 举报
回复
"引发弹出菜单的按钮有多个"
多个按钮弹出一个菜单?
通常是
多个按钮弹出多个菜单。
madbunny 2012-09-26
  • 打赏
  • 举报
回复
不是这个意思。我前面表述的有问题,我是说,引发弹出菜单的按钮有多个,我在OnNotify里面怎么知道是哪个按钮引发的呢?因为不同的按钮对应着不同的菜单啊。[Quote=引用 9 楼 的回复:]

'那么我怎么根据notify的参数来判断'
你在资源中打开那个‘IDR_NEW_MENU’
在menu的某项,用向导 给你加 响应 (应该是 command)。
就是说:
pPopup->TrackPopup……
只负责弹出 菜单,它与响应菜单 没关系了。
[/Quote]
madbunny 2012-09-25
  • 打赏
  • 举报
回复
大神,再问最后一个问题!!!
我的这个工具条里面可能会有很多个这样的菜单,那么我怎么根据notify的参数来判断是哪个按钮发送来的呢?[Quote=引用 7 楼 的回复:]

"'haha' 应该这样:"

只是产生菜单,那个箭头必须要产生菜单,在菜单中点击才是你的菜单命令。
你可以用向导对menu的命令作响应。
[/Quote]
schlafenhamster 2012-09-24
  • 打赏
  • 举报
回复
"'haha' 应该这样:"

只是产生菜单,那个箭头必须要产生菜单,在菜单中点击才是你的菜单命令。
你可以用向导对menu的命令作响应。
madbunny 2012-09-24
  • 打赏
  • 举报
回复
我明白你的意思了,就是说如果没法用ON_NOTIFY宏收到这个消息就直接在OnNotify里面实现它,对吧?但是网上都是这么写的啊,你能告诉我为什么我的就不行么?[Quote=引用 5 楼 的回复:]

'haha' 应该这样:
// afxDump << "haha\n";
CMenu menu;
VERIFY(menu.LoadMenu(IDR_NEW_MENU));
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup);
CPoint pt;
GetCursorPos(&pt);
pPopup->TrackPopup……
[/Quote]
schlafenhamster 2012-09-22
  • 打赏
  • 举报
回复
'haha' 应该这样:
// afxDump << "haha\n";
CMenu menu;
VERIFY(menu.LoadMenu(IDR_NEW_MENU));
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup);
CPoint pt;
GetCursorPos(&pt);
pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL,
pt.x, pt.y, this,0);
madbunny 2012-09-22
  • 打赏
  • 举报
回复
你的MFC知识都是从何而来啊?能不能推荐几本书,或者给写个学习MFC的路线图啊?还有就是新的MFC版本出来了,教程都是老的,怎么做到与时俱进啊?[Quote=引用 2 楼 的回复:]

1.OnCreate
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRA……
[/Quote]
madbunny 2012-09-22
  • 打赏
  • 举报
回复
非常感谢!
按钮现在正常了,但是响应函数还是不执行啊。
那个onnodify的重写确实输出了HAHA,但是不知道为什么,消息就是没有传递过去……[Quote=引用 2 楼 的回复:]

1.OnCreate
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRA……
[/Quote]
schlafenhamster 2012-09-21
  • 打赏
  • 举报
回复
1.OnCreate
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
// after creation, add new style
m_wndToolBar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS);
// make one bt has droparrows
TBBUTTONINFO tbi;
tbi.dwMask = TBIF_STYLE;
tbi.cbSize = sizeof(TBBUTTONINFO);
m_wndToolBar.GetToolBarCtrl().GetButtonInfo(ID_FILE_SAVE, &tbi);
tbi.fsStyle |= TBSTYLE_DROPDOWN;
m_wndToolBar.GetToolBarCtrl().SetButtonInfo(ID_FILE_SAVE, &tbi);
2.
BOOL CMainFrame::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
// TODO: Add your specialized code here and/or call the base class
LPNMHDR lpnm = (LPNMHDR) lParam;
LPNMTOOLBAR lpnmtb = (LPNMTOOLBAR) lParam;
if(lpnm->code == TBN_DROPDOWN)
afxDump << "haha\n";
return CFrameWnd::OnNotify(wParam, lParam, pResult);
}
madbunny 2012-09-21
  • 打赏
  • 举报
回复
人肉置顶,真心求助。

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧