MFC CEdit 控件在添加到加速器后不处理 Key Pressed

Posted

技术标签:

【中文标题】MFC CEdit 控件在添加到加速器后不处理 Key Pressed【英文标题】:MFC CEdit Control does not handle Key Pressed after added to Accelerator 【发布时间】:2019-10-21 12:39:15 【问题描述】:

我的 MFC 应用程序中的 del 密钥有问题。

我已经定义了一个加速器条目以在我的CTreeView. 中使用del

我的应用程序使用拆分视图。 CTreeView 位于左侧面板中,CEdit 控件位于右侧面板中 CFormView 内。

Entry 是这样定义的:

VK_DELETE,      ID_EDIT_DELETE,         VIRTKEY, NOINVERT

ID_EDIT_DELETE 事件在 CTreeView 内部处理。

在我添加它之后,del 键在 CEdit 控件中停止工作。

我必须做什么才能恢复 CEdit Control 中的功能? 我是否必须添加类似的内容:

ON_COMMAND(ID_EDIT_DELETE, &StationView::OnDelete)

到每个包含CEdit Control 的面板?然后手动实现删除字符功能? 或者有没有更简单的方法将del Key 事件传递给CEdit 控件?

更新:

我重写了 CFormView 类中的 PreTranslateMessage 方法,并且 Del Key Press 被捕获。但是我该如何继续呢?

更新 V2:

如此处询问的拆分器创建代码:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext) 

    // create splitter window
    if (!m_wndSplitter.CreateStatic(this, 1, 2)) 
        return FALSE;
    

    if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftView), CSize(250, 1000), pContext) ||
        !m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CLineSyncView), CSize(500, 1000), pContext)) 
        m_wndSplitter.DestroyWindow();
        return FALSE;
    

    return TRUE;

【问题讨论】:

您的 CEdit 控件在哪里?它属于树吗? 我使用拆分面板,因此树视图位于左侧面板,编辑控件位于右侧面板。我已经更新了问题。 我覆盖了 CFormView 类中的 PreTranslateMessage 方法,并且 Del Key Press 被捕获。但是我该如何进一步进行? 你能添加一些代码来创建分割视图吗? 将代码添加到问题中。 【参考方案1】:

From MSDN:

MFC 具有菜单处理程序和加速键的默认实现 AppWizard 添加到您的应用程序以处理这些功能。 这些菜单处理程序获取加速键击而不是您的 编辑控件。

解决方案是加载快捷键表并将消息发送到您的编辑控件以备不时之需。

代码如下:

    在您的CFormView 派生类中,添加HACCEL m_hAccelTable 成员。

    在覆盖的OnInitialUpdate中加载加速器:

    void CFormRight::OnInitialUpdate()
    
        CFormView::OnInitialUpdate();
    
        m_hAccelTable = ::LoadAccelerators(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
    
    

    覆盖CFormView 派生类中的PreTranslateMessage 函数。 我们需要检查这是否是关键消息,焦点窗口是否为编辑控件以及是否有加速键。

    BOOL CFormRight::PreTranslateMessage(MSG* pMsg)
    
        if (m_hAccelTable)
        
            // cheaper to check the message range then TranslateAccelerator
            if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST)
            
                CWnd* pWnd = GetFocus();
                if (IsEdit(pWnd) && ::TranslateAccelerator(m_hWnd, m_hAccelTable, pMsg))
                
                    pWnd->SendMessage(pMsg->message, pMsg->wParam, pMsg->lParam);
                    return FALSE;
                
            
        
        return CFormView::PreTranslateMessage(pMsg);    
    
    
    BOOL CFormRight::IsEdit(CWnd* pWnd)
    
        ASSERT(pWnd != NULL);
        HWND hWnd = pWnd->GetSafeHwnd();
        if (hWnd == NULL)
            return FALSE;
    
        TCHAR szClassName[6];
        return ::GetClassName(hWnd, szClassName, 6) &&
            _tcsicmp(szClassName, _T("Edit")) == 0;
    
    

    最后,销毁加速器。

    void CFormRight::OnDestroy()
    
        CFormView::OnDestroy();
    
        ::DestroyAcceleratorTable(m_hAccelTable);   
    
    

【讨论】:

【参考方案2】:

另一种方法是处理 ON_UPDATE_COMMAND_UI:

ON_UPDATE_COMMAND_UI(ID_EDIT_DELETE, &StationView::OnDelete)

void StationView::OnDelete(CCmdUI* pCmdUI)

    // TODO: Add your command update UI handler code here

    pCmdUI->Enable(! IsEdit(GetFocus())); // see previous post for IsEdit method

但是,我没有尝试过。你试试:)

附:如何实现 IsEdit(摘自上一篇):

BOOL CFormRight::IsEdit(CWnd* pWnd)

    ASSERT(pWnd != NULL);
    HWND hWnd = pWnd->GetSafeHwnd();
    if (hWnd == NULL)
        return FALSE;

    TCHAR szClassName[6];
    return ::GetClassName(hWnd, szClassName, 6) &&
        _tcsicmp(szClassName, _T("Edit")) == 0;

【讨论】:

以上是关于MFC CEdit 控件在添加到加速器后不处理 Key Pressed的主要内容,如果未能解决你的问题,请参考以下文章

为啥 UpdateData() 在 MFC CEdit 控件的 EN_CHANGE 处理程序中不起作用

在 mfc 的 cedit 控制中处理箭头键

MFC:更改 CEdit 的颜色

为啥子控件不出现在 MFC 派生的 CWnd 中

MFC对话框的CEdit控件回车换Tab键,并获得焦点全选中文本

在 MFC 中,当 CEdit 控件达到最大字符时,退格不起作用