Шаг 360 - Элемент управления ComboBox в ListBox

У нас есть CListBox. На основе этого элемента управления можно делать другие элементы управления. Например, мы с Вами сделаем элементом списка CComboBox. Итак, нам нужен проект на базе диалогового окна. Дадим ему имя TestList. Поместим на диалог элемент управления ListBox с идентификатором IDC_LIST1. Добавим в проект класс CListComboBox как наследник от CListBox. И свяжем с элементом управления.

360_1.gif (1481 b)

Вроде как готово. Добавим пару надписей что бы с ними можно было работать.

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);		// спрятать
}

Все можно пробовать использовать.

360_2.gif (4770 b)

Естественно пока наш класс не так хорош как нужно, например не отражает выбор в ListBox но мы его дальше доделаем. В проекте находится класс CListComboBox упакованный для использования в Component Gallery как ogx файл.


Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Каев Артем - 14.08.2001