我今天和MFC一起开始了! :d
我有一个文本框和一个列表视图控件。
当用户按下文本框中的VK_UP
和VK_DOWN
键时,我希望发生这种情况:
我尝试在对话框中对我的编辑框进行子类化:
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
手动发送命令相比,是否有更好解决方法?我应该改变我的设计,例如继承其他东西等等?
答案 0 :(得分:0)
您打算在列表控件中选择上一个或下一个项目,对吧?然后你应该调用方法直接执行该操作,要求CListCtrl
“处理”你的消息。
您可以拨打CListCtrl::SetSelectionMark和CListCtrl::SetItemState来选择下一次或上一次击键。例如:
cListCtrl.SetSelectionMark(nIndex);
cListCtrl.SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED, 0xFF);
您可以通过编辑框处理按键,按键以及Page Down,Page Up,End,Home或任何任何键。但是你需要做计算。
或者你可以SendMessage
。无需直接致电OnKeyDown
。当您发送消息时,让框架为您调用。
答案 1 :(得分:0)
我也看到了解决这个问题的其他方法:
从名为CListCtrl
的{{1}}中导出一个班级,然后选择以下两种方法之一:
1.1将MyListCtrl
声明为朋友,现在您可以在MyEditBox
上调用受保护的方法
1.2将公共方法MyEditBox
和CallOnKeyDown(...)
添加到其中,只执行所需操作。
创建控件时,请设置CallOnKeyup(...)
而不是MyListCtrl
。同时将此处显示的CListCtrl
变量替换为listView
并使用您现有的方法
使用MyListCtrl
。我认为这种“锤子”解决方案比发送消息更糟糕。