【问题标题】:How can i modify the context menu of a CEdit control?如何修改 CEdit 控件的上下文菜单?
【发布时间】:2011-06-07 12:39:02
【问题描述】:

在 Windows 7 之前,解决方案很简单。只需添加您自己的菜单并编写您自己的“撤消、重做、剪切、复制、粘贴、删除、全选”菜单项。但是现在这已经不可能了,因为菜单已经变得非常复杂,包含 unicode 和输入消息的东西。

【问题讨论】:

    标签: windows-7 mfc cedit


    【解决方案1】:

    你需要子类化编辑控件然后使用钩子,下面是一个示例代码:

    首先是对编辑控件进行子类化,一般在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 */
        }
    }
    

    然后在子类函数中:

    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;
    }
    

    【讨论】:

    • 将其标记为答案,即使我目前无法尝试。
    • 感谢代码 sn-p。我们如何在上下文中使用它?假设我们有一个对话框控件映射到一个变量调用m_editControl?或者你能链接到你所指的东西吗?充实这个答案?
    • @AndrewTruckle 我已经编辑了答案以添加详细信息。
    • 谢谢。对我来说,我想我可以因此使用m_editControl.SubclassDlgItem(IDC_EDIT, this); 作为第一位。
    • 我想你的方式避免了从CEdit派生一个新类的需要?我不熟悉您在这里使用的方法 - 看起来更像原生 Win32,而不是 MFC/
    【解决方案2】:

    好的,我找到了方法

    static bool is_first_time;
    
    case WM_CONTEXTMENU: {
       is_first_time = true;
       original_window_proc(message,wparam,lparam);
       break;
    
    case WM_ENTERIDLE:
        if (wparam == MSGF_MENU) {
            if (is_first_time) {
                is_first_time = false; 
                MENUBARINFO mbi;
                memset(&mbi, 0, sizeof(MENUBARINFO));
                mbi.cbSize = sizeof(MENUBARINFO);
                GetMenuBarInfo((HWND)lparam, OBJID_CLIENT, 0, &mbi);
                if (::IsMenu((HMENU)mbi.hMenu)) {
                   .... add your menu items here
                }
            }
        }
    

    不幸的是,这不起作用,因为代码使用带有TPM_RETURNCMDTPM_NONOTIFY 标志的TrackPopupMenu。因此,您可以添加新的菜单项,但无法处理命令。糟糕的微软,非常糟糕的设计。

    【讨论】:

      猜你喜欢
      • 2020-04-20
      • 2013-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多