最近遇到了这样一个问题,
我自己创建个工具条,该工具条上一个按钮是TBSTYLE_DROPDOWN类型的(就是具有下拉功能的按钮,带个下拉的三角) 
我用类向导对我建立的工具条关联了一个类CTBGeometry因为在关联的过程中,mfc不自己提供CTOOLBAR选项,就用了ctoolbarctl类代替的,然后手动的把CTBGeometry中所有的ctoolbarctl替换ctoolbar给出该类的整个定义和实现文件
头文件如下:
class CTBGeometry : public CToolBar
{
// Construction
public:
CTBGeometry();// Attributes
public:// Operations
public:// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTBGeometry)
//}}AFX_VIRTUAL// Implementation
public:
virtual ~CTBGeometry(); // Generated message map functions
protected:
//{{AFX_MSG(CTBGeometry)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG DECLARE_MESSAGE_MAP()
};
实现文件如下
CTBGeometry::CTBGeometry()
{
}CTBGeometry::~CTBGeometry()
{
}
BEGIN_MESSAGE_MAP(CTBGeometry, CToolBar)
//{{AFX_MSG_MAP(CTBGeometry)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
该工具条的资源标识符为IDR_TB_GeometricNetwork
现在资源里面的工具条已经关联上了一个ctoolbar类了
该工具条上有个按钮 其资源ID为ID_BT_EDIT(就是想让这个按钮具有下拉的功能)
然后按照msdn的建立下拉对话框的说明进行了如下的操作
(在msdn的搜索中输入TBSTYLE_EX_DRAWDDARROWS 
就会出现Using Drop-Down Buttons in a Toolbar Control这篇文章)
给出这篇文章的部分
1. Once your CToolBarCtrl object has been created, set the TBSTYLE_EX_DRAWDDARROWS style, using the following code: 
m_wndToolBar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS);
2. Set the TBSTYLE_DROPDOWN style for any new (InsertButton or AddButtons) or existing (SetButtonInfo) buttons that will be drop-down buttons. The following example demonstrates modifying an existing button in a CToolBarCtrl object: 
TBBUTTONINFO tbi;tbi.dwMask= TBIF_STYLE;
tbi.cbSize= sizeof(TBBUTTONINFO);
m_wndToolBar.GetToolBarCtrl().GetButtonInfo(ID_EDIT_CUT, &tbi);
tbi.fsStyle |= TBSTYLE_DROPDOWN;
m_wndToolBar.GetToolBarCtrl().SetButtonInfo(ID_EDIT_CUT, &tbi);
3. Add a WM_NOTIFY handler to the parent class of the toolbar object. 
前两部都没有问题,我的自定义工具条上也由代码产生的向下的三角尖头
下面给出我的这部分实现代码CTBGeometry m_tbGeometryNetwork;//在工程的CMainFrame类中定义自定义对话框
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (!m_tbGeometryNetwork.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_tbGeometryNetwork.LoadToolBar(IDR_TB_GeometricNetwork))
{
TRACE0("Failed to create toolbar\n");
return -1;      // fail to create
}
//对话框停靠
m_tbGeometryNetwork.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
//DockControlBar(&m_wndToolBar);
DockControlBar(&m_tbGeometryNetwork);
//使m-tbbeometrynetwork工具条上的按钮具有下拉的属性
TBBUTTONINFO tbi;
tbi.dwMask= TBIF_STYLE;
tbi.cbSize= sizeof(TBBUTTONINFO);
m_tbGeometryNetwork.GetToolBarCtrl().GetButtonInfo(ID_BT_EDIT, &tbi);
tbi.fsStyle |= TBSTYLE_DROPDOWN;
m_tbGeometryNetwork.GetToolBarCtrl().SetButtonInfo(ID_BT_EDIT, &tbi);
return 0;
}问题出在了第三部(添加通告消息这里)
Add a WM_NOTIFY handler to the parent class of the toolbar object.
在CMainFrame类中进行了消息映射
代码如下(粗体是我加的代码)
。h文件中
protected:
//{{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnToolbarDropDown(NMTOOLBAR* pnmh, LRESULT* plRes);
// NOTE - the ClassWizard will add and remove member functions here.
//    DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
.cpp文件中
IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
// NOTE - the ClassWizard will add and remove mapping macros here.
//    DO NOT EDIT what you see in these blocks of generated code !
ON_WM_CREATE()
ON_NOTIFY(TBN_DROPDOWN, ID_BT_EDIT, OnToolbarDropDown)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
并且实现了OnToolbarDropDown这个函数
正常情况下,加上上面的代码后 按钮ID_BT_EDIT应该由灰色(不可用)变成正常可用的按钮。但是可以调试通过。
问,1我的错误在那里呢
我查看了msdn的关于ON_NOTIFY的说明
ON_NOTIFY( wNotifyCode, id, memberFxn )
where the italicized parameters are replaced with: 
wNotifyCode 
The code for the notification message to be handled, such as LVN_KEYDOWN. 
id 
The child identifier of the control for which the notification is sent. 
memberFxn 
The member function to be called when this notification is sent. 
如果我把上面代码中所有的m_tbGeometryNetwork 都换成 mfc生成的m_wndToolBar并且把
ON_NOTIFY(TBN_DROPDOWN, ID_BT_EDIT, OnToolbarDropDown)
换成
ON_NOTIFY(TBN_DROPDOWN, AFX_IDW_TOOLBAR, OnToolbarDropDown)
就可以通过了
2 )AFX_IDW_TOOLBAR 跟踪进去后发现 这个id微软给的注释为
#define AFX_IDW_TOOLBAR        0xE800  // main Toolbar for window
而mfc产生的默认工具条的id是IDR_MAINFRAME 这个AFX_IDW_TOOLBAR与IDR_MAINFRAME 是什么关系?
3 我的问题应该怎么解决
看在我写了这么多分子上,知道原因的高手门给个解释吧
也可以给我写信[email protected]

解决方案 »

  1.   

    解决方法
    分析发现,
    1 通过代码使得向下的尖头产生了,那么这部分应该没有错误
    2 错误很可能是响应通告函数部分,给资源ID_BT_EDIT添加了响应事件后发现,由代码产生的向下的尖头按钮变成了正常的可使用形式,但是点击后却没有菜单出现,仔细观察ON_NOTIFY( wNotifyCode, id, memberFxn )
    这个函数其中难于理解的就是 那个id的意义,无论把他设置成ID_BT_EDIT还是IDR_TB_GeometricNetwork都结果都一样,那么最后把它设置成AFX_IDW_TOOLBAR
    编译后通过
    得出的结论
    1 id代表的是什么呢
    由#define AFX_IDW_TOOLBAR        0xE800  // main Toolbar for window
    可以知道,程序的工具条(大的方面,无论是mfc给我们产生的工具条,还是我们自定义的工具条,都是工具条)来响应这个函数,而不是某个具体的工具条,(就好象我们常说的水果一样,虽然苹果也是水果,但苹果不是个抽象)那么当程序执行起来后怎么知道到底是那个工具条上的下拉按钮被点击了呢(很有可能一个工具条上有多个下拉按钮,还有可能是多个工具条上都有下拉按钮)那么就由响应函数中的参数来决定了
    OnToolbarDropDown(NMTOOLBAR* pnmh, LRESULT* plRes);
    也就应该是NMTOOLBAR这个参数查看msdn的ON_NOTIFY message后发现果然是这样的 许多的附加信息,包括鼠标按下的位置,都放在NMTOOLBAR这个东东里面,呵呵问题到此清楚了,呵呵,和大家分享吧
    如果你也遇到了这样的问题,而且你觉得我写的不是很清楚的话,可以email给我。[email protected]
      

  2.   

    未找到CToolBar是继承Class Type时选用了MFC Class吧,继承Generic Class是可以找到CToolBar的。
    我目前碰到的问题是如何在View中Disable掉ToolBar上的按钮,可碰到过此问题?麻烦告知下。