C++ 重載EditBox默認ContextMenu

問題背景

      在作windows下的C++客戶端程序開發的時候,常常會遇到自定義右鍵菜單的功能點的開發。
      這時候,咱們通常只須要在窗口的事件過程當中處理WM_CONTEXTMENU消息。處理時,根據須要能夠使用CreatePopupMenu建立彈出菜單,並插入指定的子菜單項,最後處理對應菜單項的消息這樣的流程來實現一個自定義的右鍵菜單列表。也能夠經過拿到菜單項的句柄,枚舉並修改菜單列表的形式重載一些已經實現的或者已經定義的菜單列表。
      以前遇到一個需求,須要繼承Edit默認的右鍵菜單,在此基礎上添加一些自定義的右鍵菜單項。然而,按照以前的理解,寫代碼的過程當中發現,WM_CONTEXTMENU消息觸發的時候,不能獲取到默認的右鍵菜單句柄信息,也就拿不到右鍵菜單中的菜單列表條目。所以也不能繼續進行右鍵菜單項的自定義操做。下面用代碼演示一下,通常自定義右鍵菜單的方法和在editbox中實現重載默認Context的方法。windows

自定義右鍵菜單

在這裏用代碼表示通常的右鍵菜單建立和處理的過程:後端

//編輯框事件處理
#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: {
            //建立菜單項列表
             HMENU popup = CreatePopupMenu();
             WCHAR temp[50] = {0};
             wcscpy(temp, L"自定義菜單");
             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:{
        //根據具體的需求處理消息
        }
        break;
        default:
            break;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

重載系統默認右鍵菜單

//獲取列表中pos處的菜單項
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) {//表示爲菜單消息,當wParam爲MSGF_DIALOGBOX表示的是對話框消息
                //這裏表示菜單進入空閒狀態
                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(menuStr, L"自定義菜單");
                        AppendMenu(mbi.hMenu, MF_STRING, (UINT_PTR)9000, menuStr);
                    }
                }
            }
        } break;
        default:
            break;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

參考資料

https://stackoverrun.com/cn/q...
https://docs.microsoft.com/en...微信

重要說明

==歡歡迎你們關注個人我的微信公衆號,一塊兒探討和學習C++後端、客戶端的開發知識!==
在這裏插入圖片描述學習

相關文章
相關標籤/搜索