如何将WM_KEYDOWN消息重定向到MFC中的另一个控件?

时间:2011-08-27 03:53:01

标签: winapi visual-c++ mfc

我今天和MFC一起开始了! :d

我有一个文本框和一个列表视图控件。

当用户按下文本框中的VK_UPVK_DOWN时,我希望发生这种情况:

  1. 做一些事情。
  2. 让列表视图控件处理消息(突出显示上一个/下一个项目)。
  3. 我希望列表视图环绕当前选择,如果按键是第一个序列。
  4. 做更多的事情。
  5. 我尝试在对话框中对我的编辑框进行子类化:

    class MyEditBox : public CWnd
    {
        bool allowWrap;
    
        afx_msg void OnKeyUp(UINT, UINT, UINT) { this->allowWrap = true; }
    
        afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
        {
            CListCtrl &listView = static_cast<CListView *>(
                this->GetParent()->GetDlgItem(IDC_LIST_VIEW))->GetListCtrl();
    
            if (nChar == VK_UP || nChar == VK_DOWN)
            {
                int iSelBefore = listView.GetNextItem(-1, LVNI_SELECTED);
    
                this->GetParent()->GetDlgItem(IDC_LIST_VIEW)
                    ->OnKeyDown(nChar, nRepCnt, nFlags);  //Oops! Protected member :(
    
                int iSelAfter  = listView.GetNextItem(-1, LVNI_SELECTED);
    
                if (iSelBefore == iSelAfter &&  // Did the selection reach an end?
                    this->allowWrap)            // If so, can we wrap it around?
                {
                    int i = a == 0 ? listView.GetItemCount() - 1 : 0;
                    listView.SetItemState(i, LVIS_SELECTED | LVIS_FOCUSED,
                                             LVIS_SELECTED | LVIS_FOCUSED);
                }
            }
            this->allowWrap = false;
        }
    }
    

    OnKeyDown()是受保护的成员,所以我不能只在另一个控件上调用它。

    与使用SendMessage手动发送命令相比,是否有更好解决方法?我应该改变我的设计,例如继承其他东西等等?

2 个答案:

答案 0 :(得分:0)

您打算在列表控件中选择上一个或下一个项目,对吧?然后你应该调用方法直接执行该操作,要求CListCtrl“处理”你的消息。

您可以拨打CListCtrl::SetSelectionMarkCListCtrl::SetItemState来选择下一次或上一次击键。例如:

 cListCtrl.SetSelectionMark(nIndex);
 cListCtrl.SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED, 0xFF);

您可以通过编辑框处理按键,按键以及Page Down,Page Up,End,Home或任何任何键。但是你需要做计算。

或者你可以SendMessage。无需直接致电OnKeyDown。当您发送消息时,让框架为您调用。

答案 1 :(得分:0)

我也看到了解决这个问题的其他方法:

  1. 从名为CListCtrl的{​​{1}}中导出一个班级,然后选择以下两种方法之一:

    1.1将MyListCtrl声明为朋友,现在您可以在MyEditBox上调用受保护的方法

    1.2将公共方法MyEditBoxCallOnKeyDown(...)添加到其中,只执行所需操作。

    创建控件时,请设置CallOnKeyup(...)而不是MyListCtrl。同时将此处显示的CListCtrl变量替换为listView并使用您现有的方法

  2. 使用MyListCtrl。我认为这种“锤子”解决方案比发送消息更糟糕。