Click here to Skip to main content
Licence 
First Posted 15 Dec 1999
Views 183,644
Bookmarked 63 times

Adding a drop arrow to a toolbar button

By | 15 Dec 1999 | Article
Demonstrates how to use the new toolbar styles to add dropdown arrows to toolbar buttons
  • Download demo project - 28 Kb
  • Sample Image - toolbar_droparrow.gif

    If you wanted to add a drop menu like the ones seen in internet explorer, it is pretty straight forward. This approach for will work for both Visual C++ 5 and 6, however you may want to read up on the enhancements to the toolbar class for VC 6.0.

    First off, after your toolbar has been created in CMainFrame::OnCreate(), you will need to make a call to the following

    DWORD dwExStyle = TBSTYLE_EX_DRAWDDARROWS;
    m_wndToolBar.GetToolBarCtrl().SendMessage(TB_SETEXTENDEDSTYLE, 0, (LPARAM)dwExStyle);
    

    This will enable your toolbar to handle drop arrows. The next thing you will need to do, is to actually add the drop arrow to your desired button. This will be done via the SetButtonStyle() method:

    DWORD dwStyle = m_wndToolBar.GetButtonStyle(m_wndToolBar.CommandToIndex(ID_FILE_OPEN));
    dwStyle |= TBSTYLE_DROPDOWN;
    m_wndToolBar.SetButtonStyle(m_wndToolBar.CommandToIndex(ID_FILE_OPEN), dwStyle);
    

    Now, you will need to add a message handler for the drop arrow, as well a menu to the application resources. Assuming you already know how to create a menu, ( if not, click on the resource tab, select the resource name ie: MyApp Resources, then right click. Select insert, then select Menu, then press the New button ) and assuming that the resource id for our menu is IDR_MENU1, add the following code to CMainFrame's message map:

    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
    	//{{AFX_MSG_MAP(CMainFrame)
    	...
    	ON_NOTIFY(TBN_DROPDOWN, AFX_IDW_TOOLBAR, OnToolbarDropDown)
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    

    Add the following method to CMainFrame's .cpp file:

    void CMainFrame::OnToolbarDropDown(NMTOOLBAR* pnmtb, LRESULT *plr)
    {
    	CWnd *pWnd;
    	UINT nID;
    
    	// Switch on button command id's.
    	switch (pnmtb->iItem)
    	{
    	case ID_FILE_OPEN:
    		pWnd = &m_wndToolBar;
    		nID  = IDR_MENU1;
    		break;
    	default:
    		return;
    	}
    	
    	// load and display popup menu
    	CMenu menu;
    	menu.LoadMenu(nID);
    	CMenu* pPopup = menu.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);
    }
    

    Then add the following to CMainFrame's .h file:

    	//{{AFX_MSG(CMainFrame)
    	...
    	afx_msg void OnToolbarDropDown(NMTOOLBAR* pnmh, LRESULT* plRes);
    	//}}AFX_MSG
    

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    About the Author

    Kirk Stowell

    CEO
    Codejock Software
    United States United States

    Member



    Sign Up to vote   Poor Excellent
    Add a reason or comment to your vote: x
    Votes of 3 or less require a comment

    Comments and Discussions

     
    You must Sign In to use this message board. (secure sign-in)
     
    Search this forum  
     FAQ
        Noise  Layout  Per page   
      Refresh
    GeneralRe: Cannot click arrow PinmemberKirk Stowell10:21 14 Mar '05  
    GeneralRe: Cannot click arrow PinmemberRummey10:55 14 Mar '05  
    GeneralRe: Cannot click arrow PinmemberKirk Stowell4:29 15 Mar '05  
    GeneralRe: Cannot click arrow PinmemberRummey4:53 15 Mar '05  
    GeneralRe: Cannot click arrow PinmemberKirk Stowell5:06 15 Mar '05  
    GeneralRe: Cannot click arrow PinmemberCodeHead8:50 2 Sep '05  
    AnswerRe: Cannot click arrow PinmemberKirk Stowell10:49 2 Sep '05  
    Hi Eric,
     
    I just tried this using the sample and it seems to work ok for me. I changed IDR_MENU1 to have 4 menu items "Item One", "Item Two", "Item Three" and "Item Four". I then added command handlers to CMainFrame. The command handlers _have_to_ be added to the owner of the popup menu, in this case CMainFrame.
     
    In MainFrm.h add:

    enum EnumItem { item1, item2, item3, item4 };
     
    class CMainFrame : public CMDIFrameWnd
    {
    snip...
     
    protected: // control bar embedded members
    CStatusBar m_wndStatusBar;
    CToolBar m_wndToolBar;
    EnumItem m_item;
     
    snip...
     
    //{{AFX_MSG(CMainFrame)
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnOntoolbardroparrowItemone();
    afx_msg void OnUpdateOntoolbardroparrowItemone(CCmdUI* pCmdUI);
    afx_msg void OnOntoolbardroparrowItemtwo();
    afx_msg void OnUpdateOntoolbardroparrowItemtwo(CCmdUI* pCmdUI);
    afx_msg void OnOntoolbardroparrowItemthree();
    afx_msg void OnUpdateOntoolbardroparrowItemthree(CCmdUI* pCmdUI);
    afx_msg void OnOntoolbardroparrowItemfour();
    afx_msg void OnUpdateOntoolbardroparrowItemfour(CCmdUI* pCmdUI);

    //}}AFX_MSG
     
    snip...
     
    };

    In MainFrm.cpp add:

    snip...
     
    /////////////////////////////////////////////////////////////////////////////
    // CMainFrame construction/destruction
     
    CMainFrame::CMainFrame()
    {
    // TODO: add member initialization code here
    m_item = item2;
    }
     
    snip...
     
    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
    //{{AFX_MSG_MAP(CMainFrame)
    ON_WM_CREATE()
    ON_COMMAND(ID_ONTOOLBARDROPARROW_ITEMONE, OnOntoolbardroparrowItemone)
    ON_UPDATE_COMMAND_UI(ID_ONTOOLBARDROPARROW_ITEMONE, OnUpdateOntoolbardroparrowItemone)
    ON_COMMAND(ID_ONTOOLBARDROPARROW_ITEMTWO, OnOntoolbardroparrowItemtwo)
    ON_UPDATE_COMMAND_UI(ID_ONTOOLBARDROPARROW_ITEMTWO, OnUpdateOntoolbardroparrowItemtwo)
    ON_COMMAND(ID_ONTOOLBARDROPARROW_ITEMTHREE, OnOntoolbardroparrowItemthree)
    ON_UPDATE_COMMAND_UI(ID_ONTOOLBARDROPARROW_ITEMTHREE, OnUpdateOntoolbardroparrowItemthree)
    ON_NOTIFY(TBN_DROPDOWN, AFX_IDW_TOOLBAR, OnToolbarDropDown)
    ON_COMMAND(ID_ONTOOLBARDROPARROW_ITEMFOUR, OnOntoolbardroparrowItemfour)
    ON_UPDATE_COMMAND_UI(ID_ONTOOLBARDROPARROW_ITEMFOUR, OnUpdateOntoolbardroparrowItemfour)

    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
     
    snip...
     
    /////////////////////////////////////////////////////////////////////////////
    // CMainFrame message handlers
     
    void CMainFrame::OnOntoolbardroparrowItemone() {
    m_item = item1;
    }
    void CMainFrame::OnUpdateOntoolbardroparrowItemone(CCmdUI* pCmdUI) {
    pCmdUI->SetCheck(m_item == item1);
    }
    void CMainFrame::OnOntoolbardroparrowItemtwo() {
    m_item = item2;
    }
    void CMainFrame::OnUpdateOntoolbardroparrowItemtwo(CCmdUI* pCmdUI) {
    pCmdUI->SetCheck(m_item == item2);
    }
    void CMainFrame::OnOntoolbardroparrowItemthree() {
    m_item = item3;
    }
    void CMainFrame::OnUpdateOntoolbardroparrowItemthree(CCmdUI* pCmdUI) {
    pCmdUI->SetCheck(m_item == item3);
    }
    void CMainFrame::OnOntoolbardroparrowItemfour() {
    m_item = item4;
    }
    void CMainFrame::OnUpdateOntoolbardroparrowItemfour(CCmdUI* pCmdUI) {
    pCmdUI->SetCheck(m_item == item4);
    }


    You will also need to add the 4 menu items to IDR_MENU1 but that should be all you need to do.
     
    Cheers,
     
    Kirk Stowell
    Codejock Software
    www.codejock.com
     
    -- modified at 16:50 Friday 2nd September, 2005
    GeneralRe: Cannot click arrow PinmemberCodeHead2:52 6 Sep '05  
    QuestionHow can I do it in a docking toolbar? PinmemberPaulaPaziani6:42 25 Jul '03  
    QuestionHow to do it in C#? PinmemberCarl Mercier11:18 23 Feb '03  
    GeneralGood Job PinmemberOld Timer2:57 8 Jan '03  
    GeneralVC++.NET Problem PinsussAnonymous13:28 12 Aug '02  
    GeneralRe: VC++.NET Problem PinmemberKirk Stowell4:44 13 Aug '02  
    GeneralRe: VC++.NET Problem Pinmemberhaoshenghan0:05 1 May '04  
    GeneralRe: VC++.NET Problem PinmemberBausch23:17 23 May '06  
    GeneralRe: VC++.NET Problem PinmemberAni18:51 4 Jul '06  
    GeneralRe: VC++.NET Problem Pinmemberkarthikeyan nithiyanandavelu19:49 1 Jan '07  
    GeneralRe: VC++.NET Problem Pinmemberdangero17:04 19 Jun '08  
    GeneralAbsolutely brilliant PinmemberDanPetitt10:08 9 Aug '02  
    GeneralRedo/Undo Dropdown Window PinmemberAnonymous5:13 20 Jun '02  
    GeneralA very little addition PinmemberMorozov Alexey13:56 19 Feb '02  
    GeneralText Menus Pinmemberswinefeaster12:29 28 Oct '01  
    GeneralDoing this in a CDialog window PinsussJeremy Davis5:36 20 Mar '00  
    GeneralTrouble with doing this in a CDialog PinsussJeremy Davis3:29 21 Feb '00  
    GeneralBug in VC6 MFC with dropdown arrows in toolbars PinsussMartin Speiser3:55 21 Jan '00  

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    Permalink | Advertise | Privacy | Mobile
    Web04 | 2.5.120529.1 | Last Updated 16 Dec 1999
    Article Copyright 1999 by Kirk Stowell
    Everything else Copyright © CodeProject, 1999-2012
    Terms of Use
    Layout: fixed | fluid