Click here to Skip to main content
Click here to Skip to main content

Reduced context menus

, 5 Nov 2002
Rate this:
Please Sign up or sign in to vote.
This code provides a simple way to remove disabled items from a context menu.
<!-- Download Links --> <!-- Article image -->

Sample Image - ReducedMenu.gif

Introduction

This code provides a simple way to remove disabled items from a context menu. It is not good coding practice to remove disabled menu items from an application's main menus but it is often desirable to do this for popup context menus.

Using the code

Using the code is very simple. Add the two files "ReducedMenu.h" and "ReducedMenu.cpp" to your project.

Cast the menu you wish to popup to a CReducedMenu so that our custom  TrackPopupMenu function is called

((CReducedMenu*) menu.GetSubMenu(0))->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, x, y ,AfxGetMainWnd());

Points of Interest

The CReducedMenu class uses the internal class CEnabledCmdUI derived from CCmdUI to check the enabled state for each menu item using the MFC command update handlers. You can find the same class definition in MFC's WinCore.cpp.

class CReducedMenu: public CMenu
{
public:
    CReducedMenu() {}
    BOOL TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, 
                         LPCRECT lpRect = NULL );

protected:
    void CullDisabledItems(CMenu* pMenu);


    // class to test if a command is enabled or not. Taken from MFC's WinCore.cpp
    class CEnabledCmdUI : public CCmdUI
    {
    public:
        CEnabledCmdUI():m_bEnabled(false) {}
        virtual void Enable(BOOL bOn)
        {
            m_bEnabled = bOn;
            m_bEnableChanged = TRUE;
        }

        virtual void SetCheck(int nCheck) {}
        virtual void SetRadio(BOOL bOn) {}
        virtual void SetText(LPCTSTR) {}

        BOOL m_bEnabled;
    }

};

The actual removal of disabled items is called recursively for any sub menus. After the disabled items are removed, surplus separators are then removed.

BOOL CReducedMenu::TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect )
{
    CullDisabledItems(this);
    return CMenu::TrackPopupMenu( nFlags,x,y,pWnd,lpRect);
}


void CReducedMenu::CullDisabledItems(CMenu* pMenu)
{
    CEnabledCmdUI state;
    UINT n;

    // go through each menu item and remove disabled items
    for(n =0; n < pMenu->GetMenuItemCount(); n++)
    {
        state.m_nID = pMenu->GetMenuItemID( n );

        // menu separator or invalid cmd - ignore it
        if (state.m_nID == 0)
            continue;
        if (state.m_nID == (UINT)-1)
        {
            // possibly a popup menu, route to child menu if so
            CMenu* pSub=pMenu->GetSubMenu(n);
            if(pSub)
                CullDisabledItems(pSub);
        }
        else
        {
            // normal menu item, Remove it if the command is disabled
            AfxGetMainWnd()->OnCmdMsg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL);
            if( !state.m_bEnabled )
            {
                pMenu->DeleteMenu( n--, MF_BYPOSITION );
            }
        }
    }
    
    // now remove spare separators
    for (n =0; n < pMenu->GetMenuItemCount(); n++)
    {
        UINT nID = pMenu->GetMenuItemID( n );
        
        // if separator is first or last item in menu- remove it
        if (nID == 0 && (n == 0 || n == pMenu->GetMenuItemCount()-1) )
        {
            pMenu->DeleteMenu( n--, MF_BYPOSITION );
        }
        
        // if two adjacent separators, remove one
        if (n > 0 && nID == 0 && pMenu->GetMenuItemID( n-1 ) == 0 )
        {
            pMenu->DeleteMenu( n--, MF_BYPOSITION );
        }
    }
}

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

S Fewings
Web Developer
Australia Australia
No Biography provided

Comments and Discussions

 
GeneralRe: Good Idea PinmemberChristian Graus6-Nov-02 21:34 
bruno leclerc wrote:
others go away!
 
I agree with Thomas, it's probably as easy to hide items in an update command handler as it is to disable them, and it's better that users see the items are there. However, if you feel otherwise, by all means use this class, and I applaud the person who submitted it for taking the time to do so. Saying 'others go away', on the other hand, is childish and rude. Is that how you always hide from people whose opinion you do not agree with ?

 
Christian
 
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
 
Hey, at least Logo had, at it's inception, a mechanical turtle. VB has always lacked even that... - Shog9 04-09-2002
 
During last 10 years, with invention of VB and similar programming environments, every ill-educated moron became able to develop software. - Alex E. - 12-Sept-2002

GeneralBad idea PinmemberThomas Freudenberg6-Nov-02 11:37 
GeneralRe: Bad idea PinmemberTakeru Koushirou10-Jun-03 23:51 

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.

| Advertise | Privacy | Mobile
Web01 | 2.8.140709.1 | Last Updated 6 Nov 2002
Article Copyright 2002 by S Fewings
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid