windows-7mfccedit

How can i modify the context menu of a CEdit control?


Before Windows 7 the solution was easy. Just add your own menu and write your own "Undo,Redo,Cut,Copy,Paste,Delete,Select All" menu items. But now this is not possible anymore because the menu has became really complex with the unicode and input message stuff.


Solution

  • You need to subclass the edit control then use a hook, following is an example code:

    First is to subclass the edit control, usually in the WndProc:

    LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
    {
        switch (Message)
        {
        case WM_CREATE:
        {
            HANDLE m_editControl; /* Supposing it is created */
            SetWindowSubclass(m_editControl, EditSubclassProc, 0, NULL);
        }
        break;
        default:
            /* default message handling */
        }
    }
    

    Then in the subclass function:

    LRESULT CALLBACK EditSubclassProc(HWND hWndEdit, UINT Msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIDSubclass, DWORD_PTR dwRefData)
    {
        LRESULT ret{};
    
        switch (Msg)
        {
        case WM_CONTEXTMENU:        
        {
            HWINEVENTHOOK hWinEventHook{ SetWinEventHook(EVENT_SYSTEM_MENUPOPUPSTART, EVENT_SYSTEM_MENUPOPUPSTART, NULL,
                [](HWINEVENTHOOK hWinEventHook, DWORD Event, HWND hWnd, LONG idObject, LONG idChild, DWORD idEventThread, DWORD dwmsEventTime)
                {
                    if (idObject == OBJID_CLIENT && idChild == CHILDID_SELF)
                    {
                        HMENU hMenuContextEdit{ (HMENU)SendMessage(hWnd, MN_GETHMENU, NULL, NULL) };
    
                        // Do what you want to do
                    }
                },
                GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_OUTOFCONTEXT) };
    
            ret = DefSubclassProc(hWndEditMessage, Msg, wParam, lParam);
    
            UnhookWinEvent(hWinEventHook);
        }
        break;
        default:
            {
                ret = DefSubclassProc(hWndEdit, Msg, wParam, lParam);
            }
            break;
        }
    
        return ret;
    }