У нас есть CListBox. На основе этого элемента управления можно делать другие элементы управления. Например, мы с Вами сделаем элементом списка CComboBox. Итак, нам нужен проект на базе диалогового окна. Дадим ему имя TestList. Поместим на диалог элемент управления ListBox с идентификатором IDC_LIST1. Добавим в проект класс CListComboBox как наследник от CListBox. И свяжем с элементом управления.
Вроде как готово. Добавим пару надписей что бы с ними можно было работать.
BOOL CTestListDlg::OnInitDialog() { ...... m_List.AddString("Hello"); m_List.AddString("List"); // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control }
Добавляем объект класс CComboBox к нашему списку.
class CListComboBox : public CListBox { //}}AFX_MSG CComboBox cb; CRect rect; DECLARE_MESSAGE_MAP() };
Нам нужно перехватить событие выбора элемента списка.
BEGIN_MESSAGE_MAP(CListComboBox, CListBox) //{{AFX_MSG_MAP(CListComboBox) ON_CONTROL_REFLECT(LBN_SELCHANGE, OnSelchange) //}}AFX_MSG_MAP END_MESSAGE_MAP() ////////////////////////////////// // CListComboBox message handlers void CListComboBox::OnSelchange() { // TODO: Add your control notification handler code here }
По этому событию нам нужно показать ComboBox.
void CListComboBox::OnSelchange() { GetItemRect(GetCurSel(),rect); // получить прямоугольник текущей ячейки rect.bottom += 200; // добавить расстояние вниз для выпадающего списка if (!cb) // если не создан { cb.Create(CBS_DROPDOWNLIST | CBS_NOINTEGRALHEIGHT | WS_VISIBLE | WS_CHILD | WS_BORDER,CRect(rect),this,IDC_BOX_LIST); cb.SetFont(GetFont()); // установить шрифт одинаковый со списком cb.AddString("MFC"); // несколько новых элементов cb.AddString("VB"); } else { cb.MoveWindow(rect); // а вот если создан то поместить к текущему элементу cb.ShowWindow(SW_SHOW); // показать } }
Теперь нам нужно маленькая хитрость. Нам нужно перехватить момент выбора элемента ComboBox для того что бы убрать его с экрана.
BEGIN_MESSAGE_MAP(CListComboBox, CListBox) //{{AFX_MSG_MAP(CListComboBox) ON_CONTROL_REFLECT(LBN_SELCHANGE, OnSelchange) //}}AFX_MSG_MAP ON_CBN_SELCHANGE(IDC_BOX_LIST, OnCanselSelectComboBox) END_MESSAGE_MAP()
Объявить соответствующею функцию.
class CListComboBox : public CListBox { ...... public: virtual ~CListComboBox(); afx_msg void OnCanselSelectComboBox(); // пользователь выбрал // Generated message map functions ...... };
Ну и создать ее.
void CListComboBox::OnCanselSelectComboBox() { cb.ShowWindow(SW_HIDE); // спрятать }
Все можно пробовать использовать.
Естественно пока наш класс не так хорош как нужно, например не отражает выбор в ListBox но мы его дальше доделаем. В проекте находится класс CListComboBox упакованный для использования в Component Gallery как ogx файл.