MFC CEdit 控件在添加到加速器后不处理按键

MFC CEdit Control does not handle Key Pressed after added to Accelerator

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

我在 CTreeView.

中定义了一个加速器条目以使用 del

我的应用程序使用拆分视图。 CTreeView 在左侧面板上,CEdit 控件在 CFormView.

内的右侧面板上

条目定义如下:

VK_DELETE,      ID_EDIT_DELETE,         VIRTKEY, NOINVERT

ID_EDIT_DELETE 事件在 CTreeView 内部处理。

添加后,del 键在 CEdit 控件内停止工作。

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

ON_COMMAND(ID_EDIT_DELETE, &StationView::OnDelete)

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

更新:

我覆盖了 CFormView Class 中的 PreTranslateMessage 方法,Del 键按下被捕获。但是我该如何继续呢?

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

From MSDN:

MFC has default implementation for menu handlers and accelerator keys that AppWizard adds to your application to handle these functions. These menu handlers get the accelerator keystrokes instead of your edit control.

解决方案是加载加速器 table 并在需要时将消息发送到您的编辑控件。

代码如下:

  1. 在您的 CFormView 派生 class 中,添加 HACCEL m_hAccelTable 成员。
  2. 加载加速器覆盖 OnInitialUpdate:

    void CFormRight::OnInitialUpdate()
    {
        CFormView::OnInitialUpdate();
    
        m_hAccelTable = ::LoadAccelerators(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
    }
    
  3. 覆盖 CFormView 派生的 class 中的 PreTranslateMessage 函数。 我们需要在那里检查这是否是关键消息,焦点 window 是否是编辑控件以及是否有加速器。

    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;
    }
    
  4. 最后,摧毁加速器

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

另一种方法是处理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
}

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

P.S。如何实现 IsEdit(取自之前的 post):

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