0
votes

In a MFC dialog box I am using CComboBox with CBS_DROPDOWNLIST. It is an ownerdrawn CComboBox.

I am listing Group name and items of group in the listbox. Using the source code given in the link https://www.codeproject.com/Articles/450/CComboBox-with-disabled-items.

When I select or click group name, the edit control of CComboBox should not be updated group item text. In that link they are doing the following things to get rid of selection group item.

  • Overriding the WM_LBUTTONUP handler of the enclosed list box, we can actually disable clicking on the group items.
  • Overriding CharToItem handler, we can disable picking the group items by keyboard.
  • And finally, by reacting to reflected CBN_SELENDOK, we can assure that a group item was not 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);
}

image

After clicking group item and if I click outside of CListBox, the edit control of CComboBox updated with group name only? How to resolve this?

1

1 Answers

0
votes

Your code is prepared to respond to CBN_SELENDOK, but is not prepared when the user makes a list selection and then cancels the selection.

You can respond to CBN_SELENDCANCEL notification as well. While you are at it, you may want to respond to CBN_SELCHANGE so that the user cannot change to invalid selection using the keyboard.

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

By the way, the code from codeproject link is a bit old. To properly subclass the combobox's listbox, use GetComboBoxInfo and subclass a CListBox. I am not sure what is the purpose of PostMessage and OnRealSelEndOK and some of the other functions listed there.