C + + overload editbox default ContextMenu

Time:2021-2-26

Background of the problem

In the development of C + + client program under windows, we often encounter the development of function point of user-defined right-click menu.
At this time, we generally only need to deal with WM in the window event process_ ContextMenu message. When processing, you can create a pop-up menu by using create PopupMenu, insert the specified submenu item, and finally process the message of the corresponding menu item to realize a custom right-click menu list. You can also overload some implemented or defined menu lists by getting the handle of menu items, enumerating and modifying the menu list.
Previously, we met a requirement that we need to inherit the default right-click menu of edit and add some custom right-click menu items on this basis. However, according to the previous understanding, the process of writing code found that WM_ When the ContextMenu message is triggered, the default context menu handle information cannot be obtained, and the menu list items in the context menu cannot be obtained. Therefore, you cannot continue to customize the right-click menu items. The following code demonstrates the general method of customizing the right-click menu and the method of overloading the default context in editbox.

Custom right click menu

Here, code is used to represent the process of creating and processing the general right-click menu

//Edit box event handling
#define EDIT_NEW_MENU_ITEM WM_USER + 800
static LRESULT CALLBACK WndProcForEditCtrl(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_CONTEXTMENU: {
            //Create menu item list
             HMENU popup = CreatePopupMenu();
             WCHAR temp[50] = {0};
             Wcscpy (temp, l "custom menu");
             AppendMenu(popup, MF_STRING, (UINT_PTR)EDIT_NEW_MENU_ITEM, tmp);
             POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
             TrackPopupMenu(popup, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, pt.x,
             pt.y, 0,hwnd, nullptr);
            return true;
        }
        break;
        case EDIT_NEW_MENU_ITEM:{
        //Process messages according to specific requirements
        }
        break;
        default:
            break;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

The default right-click menu of overload system

//Gets the menu item at POS in the list
MENUITEMINFO GetMenuInfoByPosition(HMENU menu, UINT nPos) {
    TCHAR szMenuStr[256] = {0};
    MENUITEMINFO mInfo = {0};

    mInfo.cbSize = sizeof(mInfo);
    mInfo.fMask = 0 |MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_SUBMENU| MIIM_TYPE| 0;
    mInfo.dwTypeData = szMenuStr;
    mInfo.cch = _countof(szMenuStr);

    GetMenuItemInfo(menu, nPos, TRUE, &mInfo);
    return mInfo;
}

#define EDIT_NEW_MENU_ITEM WM_USER + 800
static bool isInitMenu = true;
static LRESULT CALLBACK WndProcForEditCtrl(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_CONTEXTMENU: {
            isInitMenu = true;
        } break;
        case WM_ENTERIDLE: {
            if (wParam == MSGF_ Menu) {// represents a menu message when wParam is MSGF_ Dialog box represents dialog box messages
                //This means that the menu is idle
                if (isInitMenu) {
                    isInitMenu = false;
                    MENUBARINFO mbi;
                    memset(&mbi, 0, sizeof(MENUBARINFO));
                    mbi.cbSize = sizeof(MENUBARINFO);
                    GetMenuBarInfo((HWND)lParam, OBJID_CLIENT, 0, &mbi);
                    if (::IsMenu((HMENU)mbi.hMenu)) {
                        for (int i = 0; i < GetMenuItemCount(mbi.hMenu) - 1; i++) {
                            MENUITEMINFO menuInfo = GetMenuInfoByPosition(mbi.hMenu, i);
                            auto aa = menuInfo.dwTypeData;
                            if (str::Len(menuInfo.dwTypeData)) {
                                WCHAR menuName[50] = {0};
                                wcscpy(menuName, menuInfo.dwTypeData);
                                win::menu::SetText(mbi.hMenu, menuInfo.wID, menuName);
                            }
                        }
                        WCHAR menuStr[50] = {0};
                        Wcscpy (menu STR, l "custom menu");
                        AppendMenu(mbi.hMenu, MF_STRING, (UINT_PTR)9000, menuStr);
                    }
                }
            }
        } break;
        default:
            break;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

reference material

https://stackoverrun.com/cn/q…
https://docs.microsoft.com/en…

Important note

==Huan welcome everyone to pay attention to my personal WeChat official account, and explore and learn the knowledge of C++’s back-end and client development.==
C + + overload editbox default ContextMenu