We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you a podcast all about Citrix Workspace, moving to the cloud, and analytics & intelligence. Episode 2 coming soon!Listen Now

x

Drop down button notification

minnirok
minnirok asked
on
Medium Priority
965 Views
Last Modified: 2013-11-20
Hi,

I am using a custom toolbar class in my MDI app. I am adding a dropdown button to it, which is working fine. My problem is that I am not receiving any notification as to when the drop down menu for the button is being created, though I have a handler for that event. Here are the pieces I am executing:

    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
        ...
        ON_NOTIFY(TBN_DROPDOWN, IDR_MYTOOLBAR, OnToolbarDropDown) // call me when user clicks button drop down!

    END_MESSAGE_MAP()

    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        ...
        m_MyToolbar.AddDropDownButton(this, BUTTON_ID_DRAW_A_HOUSE, MENU_ID_DRAW_A_HOUSE);
    }

    void CMainFrame::OnToolbarDropDown(NMHDR* pNMHDR, LRESULT* plRes)
    {
        // Shouldn't this be called when the user clicks the drop down arrow for my button?
        AfxMessageBox("user hit drop down for toolbar button");
    }

    void CTrueColorToolBar::AddDropDownButton(CWnd* pParent, UINT uButtonID, UINT uMenuID)
    {
        // Custom toolbar class method for making a button 'drop down' - able.
        GetToolBarCtrl().SendMessage(TB_SETEXTENDEDSTYLE, 0, (LPARAM)TBSTYLE_EX_DRAWDDARROWS);
      
        SetButtonStyle(CommandToIndex(uButtonID), TBSTYLE_DROPDOWN);

        stDropDownInfo DropDownInfo;
        DropDownInfo.pParent      = pParent;
        DropDownInfo.uButtonID      = uButtonID;
        DropDownInfo.uMenuID      = uMenuID;
        m_lstDropDownButton.Add(DropDownInfo);
    }

So my button has a dropdown with the menu I supplied, but my OnToolbarDropDown() handler is never getting called when my menu pops up. Any ideas why it is not getting called? I can supply more source code if necessary,

Thanks
Comment
Watch Question

AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT

Commented:
I think the window isn't getting the message.
(Have a quick test - put the handler into the main frame of the app)

Commented:
Maybe it is enough to add WM_COMMAND handlers for every menu item? What do you need to do when menu is opened?
AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT

Commented:
Just a sec.
Notify messages will go through the  OnNotify virtual function.

Try overriding the OnNotify (NO message map entry) and test for the message there.

Author

Commented:
Ok I  added the OnNotify() handler to Main frame, i am getting notify messages when I click on the drop down arrow. But how do I handle only those messages for the drop down activation as opposed to all the rest like when the user is clicking around the window etc?

The reason I need to handle this action is because I want to check off one of the drop down menu items when the menu is created. This way the user can see the last option they chose.

Thanks
AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT

Commented:
The menu is like any other menu.
You handle the menu clicks as Alex suggests, the updating in the update handler (pCmdUI->SetCheck(..))

Author

Commented:
Hi Andy,

Can you just explain how to do that? This is what I have now:

    BOOL CMainFrame::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
    {
        TRACE("yes being notified!......\n");

        return CMDIFrameWnd::OnNotify(wParam, lParam, pResult);  
    }

But I am getting messages for any type of user interaction now. How do I 'know' that the notify message that is coming in is due to my drop down menu coming up, how do I then access it to set the check mark?

Thanks
CERTIFIED EXPERT
Author of the Year 2009
Commented:
As AndyAinscow said:  Use the MFC system that is designed to handle this automatically and easily.  Create an
    ON_UPDATE_COMMAND_UI
handler.  It gets called automatically just before the menu is displayed.  That's when you do the SetCheck -- based on the current values of global or memeber variables.  See:

     How to: Update User-Interface Objects  
     http://msdn2.microsoft.com/en-us/library/72t5ykb7.aspx

In your message map, you'll have a line like:
      ON_UPDATE_COMMAND_UI(BUTTON_ID_DRAW_A_HOUSE, OnUpdateDrawHouse)

Then you'll write a handler like:
//-----------------------------------------------------
void CWhatever::OnUpdateDrawHouse(CCmdUI* pCmdUI)
{
      if ( m_fDrawAHouseToolCurrentlyActive ) {
            pCmdUI->SetCheck(1);
      }
      else {
            pCmdUI->SetCheck(0);   // note 2 means indeterminate
      }
}

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts
CERTIFIED EXPERT
Author of the Year 2009

Commented:
Note: The first item in the ON_UPDATE_COMMAND_UI macro is the Command ID (usually, but not always the same as the button ID)  It will be the same as used in the ON_COMMAND handler that is in the same message map.
AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT

Commented:
I use
((LPNMHDR)lParam)->code
in the OnNotify to get at the ID.

Author

Commented:
Hi guys,

Sorry I'm a bit confused now -

If I were to add that update command UI mapping, won't I get messages anytime that button is being drawn? How do I know that the dropdown menu for the button is coming up? That's all I'm really interested in. I just want to get a pointer to the menu and check the appropriate item right before it's to be displayed.

Can I have a few more instructions?

Thanks

AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT

Commented:
Menu and toolbar.
You get a message when the user selects one (typically you have an OnDoSomething function to react to that).
Just prior to the menu item / toolbar button being shown there is another message passed.
If you use the wizard to add an event handler for the button you will see TWO messages you can respond to.  If you select the one for the updating then you will see a function like
OnUpdateDoSomething(CCmdUI* pCmdUI)
Now add the line
pCmdUI->SetCheck(true);
in the function and you should get a check mark next to the menu item you have the update handler for.

Author

Commented:
Ok I guess that's where my confusion is. I've added an update UI function for my toolbar button:

    ON_UPDATE_COMMAND_UI(TOOLBAR_BUTTON_ID, OnUpdateMyToolbarButton)

And its body is:

    void CMainFrame::OnUpdateDrawOneClickDropDown(CCmdUI* pCmdUI)
    {
        pCmdUI->SetCheck(1);
    }

But this just has the effect of making the toolbar button look de-pressed, as if it is selected. I need to know how to check an item off in the drop down menu associated with the button.

I'm increasing the points for this question, sorry to be such a pain, thanks for your continuing help
AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT
Commented:
replace TOOLBAR_BUTTON_ID with the ID of the menu item you want to display the check next to.

Author

Commented:
Ahhhhh ok that's what I was missing.

Works perfectly now, thanks!
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.