如何限制CComboBox中未选择的某些项目?

时间:2019-06-11 15:01:10

标签: mfc

在MFC对话框中,我将CComboBoxCBS_DROPDOWNLIST一起使用。它是所有者绘制的CComboBox

我要在列表框中列出组名称和组项目。使用链接https://www.codeproject.com/Articles/450/CComboBox-with-disabled-items中给出的源代码。

当我选择或单击组名称时,CComboBox的编辑控件不应更新组项目文本。在该链接中,他们正在执行以下操作来摆脱选择组项目。

  • 通过覆盖所附列表框的WM_LBUTTONUP处理程序,我们实际上可以禁止单击组项目。
  • 覆盖CharToItem处理程序,我们可以禁用通过键盘选择组项目。
  • 最后,通过对反映的CBN_SELENDOK做出反应,我们可以确保未选择组项目。
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);
}

image

单击组项目后,如果我单击CListBox之外的地方,CComboBox的编辑控件仅更新为组名?该如何解决?

1 个答案:

答案 0 :(得分:0)

您的代码已准备好响应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链接的代码有些陈旧。要正确地子类别化组合框的列表框,请使用GetComboBoxInfo并将子类CListBox进行子类别化。我不确定PostMessageOnRealSelEndOK以及那里列出的其他一些功能的用途。