C++ 重载EditBox默认ContextMenu(含详细代码)

10 篇文章 0 订阅

本人微信公众号:CPP进阶之旅
如果觉得这篇文章对您有帮助,欢迎关注 “CPP进阶之旅” 学习更多技术干货

问题背景

      在做windows下的C++客户端程序开发的时候,经常会遇到自定义右键菜单的功能点的开发。
      这时候,我们一般只需要在窗口的事件过程中处理WM_CONTEXTMENU消息。处理时,根据需要可以使用CreatePopupMenu创建弹出菜单,并插入指定的子菜单项,最后处理对应菜单项的消息这样的流程来实现一个自定义的右键菜单列表。也可以通过拿到菜单项的句柄,枚举并修改菜单列表的形式重载一些已经实现的或者已经定义的菜单列表。
      之前遇到一个需求,需要继承Edit默认的右键菜单,在此基础上添加一些自定义的右键菜单项。然而,按照之前的理解,写代码的过程中发现,WM_CONTEXTMENU消息触发的时候,不能获取到默认的右键菜单句柄信息,也就拿不到右键菜单中的菜单列表条目。因此也不能继续进行右键菜单项的自定义操作。下面用代码演示一下,一般自定义右键菜单的方法和在editbox中实现重载默认Context的方法。

自定义右键菜单

在这里用代码表示一般的右键菜单创建和处理的过程:

//编辑框事件处理
#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/1566456
https://docs.microsoft.com/en-us/troubleshoot/cpp/cannot-change-state-menu-item

重要说明

欢迎关注我的个人微信公众号,查看专业的客户端/服务端开发知识、笔试面试题目、程序员职场经验与心得分享。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值