Search code examples
c++windowsmfcsystemmenu

Remove Move and Close commands from Windows' system menu without losing functionality


I want to remove the Move and Close commands from the system menu in a Windows dialog-based application without losing the functionality of those commands or removing the system menu. (I'm using MFC, but open to a pure c++ solution.)

The following will remove the Move command from the system menu:

CMenu* pSysMenu = GetSystemMenu(FALSE);
if(pSysMenu != NULL)
        pSysMenu->RemoveMenu(SC_MOVE, MF_BYCOMMAND);

But the window can no longer be dragged.

Similarly, this will remove the Close command.

pSysMenu->RemoveMenu(SC_CLOSE, MF_BYCOMMAND);

But it also disables the close button ("x") in the window's title bar.

Thanks!

(I know a few of you are tempted to tell me I shouldn't remove those commands. I hear you, but this is a unique situation. Thanks.)


Solution

  • You can remove those items from the system menu in the WM_INITMENUPOPUP handler.

    This, as you noticed, will disable related functionality in your window.

    However, you can restore those items in the handler of lesser-known WM_UNINITMENUPOPUP message.

    Add this to your dialog's class definition:

    afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu);
    afx_msg void OnUnInitMenuPopup(CMenu *pPopupMenu, UINT nFlags);
    

    Add this to its message map:

    ON_WM_INITMENUPOPUP()
    ON_WM_UNINITMENUPOPUP()
    

    You would then remove those items (just like you did) in OnInitMenuPopup:

    pPopupMenu->RemoveMenu(SC_MOVE, MF_BYCOMMAND);
    

    and re-insert them in OnUnInitMenuPopup:

    pPopupMenu->InsertMenuItemW(SC_MOVE, &m_mii);
    

    Please note &m_mii that I've defined in the class:

    MENUITEMINFO m_mii = {sizeof MENUITEMINFO};
    

    You would declare that structure for each of the menu items you need to hide, and populate it with GetMenuItemInfo right before you remove them. Likely, you only need to do it once and save for later use. This will allow you to save the menu string, bitmap, etc. However, there is no direct way (as I know of) to get the position of your items in the original menu; I would iterate through all items by-position looking for those commands. A bit tedious...

    P.S. Just realize that you would NEVER display those items in the system menu, so you don't need to bother with saving their position, bitmap, or even string. Just append them to the bottom, command IDs only.