Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS General Discussion » Menu Items not enabled,Why? Collapse All
Subject Author Date
Henry Van Voorhis Mar 29, 2006 - 5:59 PM

When I attach a menu to a toolbar button the menu Items are not enabled(greyed out)(though they do show up).
Any Ideas?

Another issue I am having is that when I add a toobar button and I click it it gets disabled. Any ideas on this? and How do I add an event handler for the toolbar button.

Technical Support Mar 30, 2006 - 5:23 AM

There is not enough information in your message to come to any conclusion about why the toolbar button gets disabled after clicking it. Please let us know more details about your toolbar. Where is it created? Inside a frame window? Inside a dialog window?

The toolbar buttons and menu items are fully controlled by MFC’s command updating mechanism. So, you need to define command handling and/or command updating methods for all your toolbar buttons and menu items to make them enabled.


Henry Van Voorhis Mar 30, 2006 - 8:36 AM

I am trying to make an IE toolbar. This is a mixed ATL/MFC app. I create the toolbar as follows (m_hWndParent comes from the IOleWindowPtr that IE provides):

    AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Needed for any MFC usage in DLL
    
        CExtPopupMenuWnd::g_bMenuExpanding = false;
    CRect rcClientParent;
    CWnd* pWndParent = CWnd::FromHandle(m_hWndParent);
    pWndParent->GetClientRect(&rcClientParent);

    // We need to create a reflection window in between our toolbar control
    // and the rebar in order to get WM_COMMAND messages sent from the toolbar to its
    // parent.
    if (!m_wndReflectionWnd.Create(NULL, NULL, WS_CHILD, rcClientParent, pWndParent, 0))
        return false;
    CWinApp * pApp = ::AfxGetApp();

    VERIFY(
        g_CmdManager->ProfileSetup( "RsaToolbarProfile", pWndParent->GetSafeHwnd() )
        );

    VERIFY(
        g_CmdManager->UpdateFromMenu(
        "RsaToolbarProfile",
        IDR_TOOLBAR_OPTIONS_MENU
        )
        );
    

    SetupCommandManager(ID_BUTTON_RSA_LOGO,"RsaToolbarProfile",IDI_RSA_LOGO);
    SetupCommandManager(ID_GETTING_STARTED_BUTTON,"RsaToolbarProfile",IDI_GETTINGSTARTED_LOGO);
    SetupCommandManager(ID_BUTTON_OPTIONS,"RsaToolbarProfile",IDI_RSA_LOGO);
    


    m_wndToolBar = new CRsaToolbar();
    
    m_wndToolBar->Create("RSA",pWndParent,DEFAULT_TOOLBAR_STYLE);

    
    ///////////// Menu Begin ///////////////////////////
    m_wndToolBar->InsertButton(
        -1,
        ID_BUTTON_RSA_LOGO
    );

///////
    INT nBtnIdx =
        m_wndToolBar->CommandToIndex(
ID_BUTTON_RSA_LOGO
        );
    //add a menu to the toolbar button

    
    ASSERT( nBtnIdx >= 0 );
        CMenu _menu;
    
    VERIFY(
        _menu.LoadMenu(
IDR_TOOLBAR_OPTIONS_MENU
        )
        );
    _menu.EnableMenuItem(
    
    VERIFY(
        m_wndToolBar->SetButtonMenu(
nBtnIdx,
_menu.Detach(),        TRUE,
        TRUE,
        FALSE
        )
        );
    
        
    //the next three lines add the arrow to the drop down button
    CExtBarButton * pTBB2 = m_wndToolBar->GetButton( nBtnIdx );

    ASSERT_VALID( pTBB2 );
    pTBB2->SetSeparatedDropDown();
    pTBB2->SetAutoChangeID();
    
    
    pTBB2->SetCmdID(ID_MENU_OPTIONS,true); //ID_MENU_OPTIONS is the first menu item ID
    

Henry Van Voorhis Mar 30, 2006 - 9:01 AM

clarify code above: class CRsaToolbar : public CExtToolControlBar

Technical Support Mar 31, 2006 - 1:47 AM

You need to implement the command updating mechanism for your toolbar window. First of all, invoke toolbar’s SetOwner() method and specify a pointer to the command target window. This window will receive both command events and command updating events. The command target window is responsible for handling all the command/updating requests of both the toolbar and menus.

Henry Van Voorhis Mar 31, 2006 - 2:27 PM

When you say "You need to implement the command updating mechanism for your toolbar window", what does this entail? what messages do I need to handle? Do you have an example of this?

So in the case of an IE toolbar the "command target window" would be a hidden window that I create that handles some specific events? or am I missing somthing?

Technical Support Apr 2, 2006 - 6:13 AM

The command target can be either some hidden window in your project or even the toolbar itself. Let’s assume you have some ID_YOUR_COMMAND toolbar button or menu item. The command target window should have the following two methods and message map entries:

1. Command handler method, invoked when the ID_YOUR_COMMAND toolbar button or menu item is clicked:

afx_msg void OnYourCommand();
ON_COMMAND( ID_YOUR_COMMAND, OnYourCommand )
void CYourCommandTargetWnd::OnYourCommand() 
{
    // PUT YOUR COMMAND HANDLER CODE HERE
}
2. Command updating method, which modifies the state of the ID_YOUR_COMMAND toolbar button or menu item:
afx_msg void OnUpdateYourCommand( CCmdUI * pCmdUI );
ON_UPDATE_COMMAND_UI( ID_YOUR_COMMAND, OnUpdateYourCommand )
void CYourCommandTargetWnd::OnUpdateYourCommand( CCmdUI * pCmdUI )
{
    // TO ENABLE OR DISABLE THE COMMAND ID_YOUR_COMMAND
    pCmdUI->Enable( bEnable );
    // TO SET/REMOVE CHECK MARK
    pCmdUI->SetCheck( bChecked );
    // TO SET/REMOVE RADIO MARK
    pCmdUI->SetRadio( bChecked );
}
The last method is optional. If the first method is defined, then the ID_YOUR_COMMAND toolbar button or menu item becomes enabled. A command which has no handler method automatically gets disabled.

Menu item commands invoke the command updating mechanism just before the menu is about to appear on the screen. Toolbar commands invoke the command updating mechanism automatically in MFC/EXE applications where the application’s message loop is controlled by the MFC host (which is typically a global variable called theApp of a CWinThread-derived class type). Your IE extension module does not control the message loop of IE instance. This means you need to invoke the command updating mechanism for the toolbar manually. You may use the following code to forcibly update all the toolbar buttons:
CWnd * pCommandTargetWnd = pToolBar->GetOwner();
    pToolBar->OnUpdateCmdUI( pCommandTargetWnd, TRUE );
It is possible to emulate the command updating mechanism in your IE extension module and make all the MFC objects working exactly as they work in MFC/EXE projects. Just set a timer for some window (for instance, for your toolbar) using the 100 millisecond timer’s period and invoke the following code from the WM_TIMER handler method:
CWinThread * pWinThread = ::AfxGetThread();
    ASSERT_VALID( pWinThread );
    pWinThread->OnIdle( 0 );
In your IE extension module, it is not possible to use the MFC’s message pretranslation based on the CWnd::PreTranslateMessage() virtual method and route invocations of this method. But you can emulate this mechanism with hooks.