CComboBox中如何限制某些项目不被选中?
How to restrict some items to be not selected in CComboBox?
在 MFC 对话框中,我使用 CComboBox
和 CBS_DROPDOWNLIST
。这是自画像 CComboBox
。
我正在列表框中列出群组名称和群组项目。使用linkhttps://www.codeproject.com/Articles/450/CComboBox-with-disabled-items.
中给出的源代码
当我select或点击组名时,CComboBox
的编辑控件应该不会更新组项文本。在那个 link 中,他们正在做以下事情来摆脱 selection 组项目。
- 覆盖封闭列表框的
WM_LBUTTONUP
处理程序,我们实际上可以禁止单击组项目。
- 覆盖
CharToItem
处理程序,我们可以禁用通过键盘选择组项目。
- 最后,通过对反映的
CBN_SELENDOK
作出反应,我们可以确保组项目未被 selected。
const UINT nMessage=::RegisterWindowMessage("ComboSelEndOK");
BEGIN_MESSAGE_MAP(CODrawCombo, CComboBox)
ON_CONTROL_REFLECT(CBN_SELENDOK, OnSelendok)
ON_REGISTERED_MESSAGE(nMessage, OnRealSelEndOK)
ON_CONTROL_REFLECT(CBN_EDITUPDATE, OnComboEdited)
ON_MESSAGE(WM_CTLCOLORLISTBOX, OnCtlColor)
END_MESSAGE_MAP()
void CODrawCombo::OnSelendok()
{
// TODO: Add your control notification handler code here
GetWindowText(m_strSavedText);
PostMessage(nMessage);
}
LRESULT CODrawCombo::OnRealSelEndOK(WPARAM,LPARAM)
{
CString currentText;
GetWindowText(currentText);
int index=FindStringExact(-1,currentText);
if (index>=0 && !IsItemEnabled)
{
SetWindowText(m_strSavedText);
GetParent()->SendMessage(WM_COMMAND,MAKELONG(GetWindowLong(m_hWnd,GWL_ID),CBN_SELCHANGE),(LPARAM)m_hWnd);
}
return 0;
}
void CListBoxInsideComboBox::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CRect rect; GetClientRect(rect);
if (rect.PtInRect(point))
{
BOOL outside=FALSE;
int index=((CListBox *)this)->ItemFromPoint(point,outside);
if (!outside && !m_Parent->IsItemEnabled(index))
return; // don't click there
}
CWnd::OnLButtonUp(nFlags, point);
}
单击组项目后,如果我在 CListBox
之外单击,CComboBox
的编辑控件是否只更新了组名?如何解决?
您的代码已准备好响应 CBN_SELENDOK
,但在用户进行列表选择然后取消选择时未准备好。
您也可以回复 CBN_SELENDCANCEL
通知。当你这样做时,你可能想要响应 CBN_SELCHANGE
以便用户无法使用键盘更改为无效选择。
ON_CONTROL_REFLECT(CBN_SELENDCANCEL, CheckIfEnabled)
ON_CONTROL_REFLECT(CBN_SELCHANGE, CheckIfEnabled)
...
int m_save_index;
...
CExtendedComboBox::CExtendedComboBox()
{
m_save_index = 0;
m_ListBox.SetParent(this);
}
void CExtendedComboBox::OnSelendok()
{
GetWindowText(m_strSavedText);
PostMessage(nMessage);
int index = GetCurSel();
if(index >= 0 && IsItemEnabled(index))
m_save_index = index;
}
void CExtendedComboBox::CheckIfEnabled()
{
int index = GetCurSel();
if(index >= 0 && !IsItemEnabled(index))
SetCurSel(m_save_index);
}
顺便说一下,codeproject link 中的代码有点旧。要正确地继承组合框的列表框,请使用 GetComboBoxInfo
并继承 a CListBox
。我不确定 PostMessage
和 OnRealSelEndOK
以及那里列出的其他一些功能的目的是什么。
在 MFC 对话框中,我使用 CComboBox
和 CBS_DROPDOWNLIST
。这是自画像 CComboBox
。
我正在列表框中列出群组名称和群组项目。使用linkhttps://www.codeproject.com/Articles/450/CComboBox-with-disabled-items.
中给出的源代码当我select或点击组名时,CComboBox
的编辑控件应该不会更新组项文本。在那个 link 中,他们正在做以下事情来摆脱 selection 组项目。
- 覆盖封闭列表框的
WM_LBUTTONUP
处理程序,我们实际上可以禁止单击组项目。 - 覆盖
CharToItem
处理程序,我们可以禁用通过键盘选择组项目。 - 最后,通过对反映的
CBN_SELENDOK
作出反应,我们可以确保组项目未被 selected。
const UINT nMessage=::RegisterWindowMessage("ComboSelEndOK");
BEGIN_MESSAGE_MAP(CODrawCombo, CComboBox)
ON_CONTROL_REFLECT(CBN_SELENDOK, OnSelendok)
ON_REGISTERED_MESSAGE(nMessage, OnRealSelEndOK)
ON_CONTROL_REFLECT(CBN_EDITUPDATE, OnComboEdited)
ON_MESSAGE(WM_CTLCOLORLISTBOX, OnCtlColor)
END_MESSAGE_MAP()
void CODrawCombo::OnSelendok()
{
// TODO: Add your control notification handler code here
GetWindowText(m_strSavedText);
PostMessage(nMessage);
}
LRESULT CODrawCombo::OnRealSelEndOK(WPARAM,LPARAM)
{
CString currentText;
GetWindowText(currentText);
int index=FindStringExact(-1,currentText);
if (index>=0 && !IsItemEnabled)
{
SetWindowText(m_strSavedText);
GetParent()->SendMessage(WM_COMMAND,MAKELONG(GetWindowLong(m_hWnd,GWL_ID),CBN_SELCHANGE),(LPARAM)m_hWnd);
}
return 0;
}
void CListBoxInsideComboBox::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CRect rect; GetClientRect(rect);
if (rect.PtInRect(point))
{
BOOL outside=FALSE;
int index=((CListBox *)this)->ItemFromPoint(point,outside);
if (!outside && !m_Parent->IsItemEnabled(index))
return; // don't click there
}
CWnd::OnLButtonUp(nFlags, point);
}
单击组项目后,如果我在 CListBox
之外单击,CComboBox
的编辑控件是否只更新了组名?如何解决?
您的代码已准备好响应 CBN_SELENDOK
,但在用户进行列表选择然后取消选择时未准备好。
您也可以回复 CBN_SELENDCANCEL
通知。当你这样做时,你可能想要响应 CBN_SELCHANGE
以便用户无法使用键盘更改为无效选择。
ON_CONTROL_REFLECT(CBN_SELENDCANCEL, CheckIfEnabled)
ON_CONTROL_REFLECT(CBN_SELCHANGE, CheckIfEnabled)
...
int m_save_index;
...
CExtendedComboBox::CExtendedComboBox()
{
m_save_index = 0;
m_ListBox.SetParent(this);
}
void CExtendedComboBox::OnSelendok()
{
GetWindowText(m_strSavedText);
PostMessage(nMessage);
int index = GetCurSel();
if(index >= 0 && IsItemEnabled(index))
m_save_index = index;
}
void CExtendedComboBox::CheckIfEnabled()
{
int index = GetCurSel();
if(index >= 0 && !IsItemEnabled(index))
SetCurSel(m_save_index);
}
顺便说一下,codeproject link 中的代码有点旧。要正确地继承组合框的列表框,请使用 GetComboBoxInfo
并继承 a CListBox
。我不确定 PostMessage
和 OnRealSelEndOK
以及那里列出的其他一些功能的目的是什么。