В литературе TreeCtrl
называют - древовидный список, по аналогии с деревом. После создания дерева
(TreeCtrl) с ветвями, или узлами(item)
у начинающего программиста непременно воспоследует вопрос :
А как же обработать нажатие на ветвь,
чтобы что -то произошло?
В данной статье я попытаюсь на него ответить.
Итак начнём с самого начала, создадим проект на основе диалога и на него
поместим наше дерево TreeCtrl. Ещё нам потребуется
два Edit Boxa.
В редакторе диалоговых окон установите атрибуты стиля элемента управления
«древовидный список», как показано на рисунке:
В файле TreeCtrlDlg.cpp найдём код
инициализации диалога и строку // TODO: Add extra initialization
here под которой необходимо размещать наш код. Запрограммируем наш
древовидный список:
// TODO: Add extra initialization
here
CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_TREE);
// здесь можно устанавливать цвет текста и фона
pTree->SetTextColor(RGB(0, 0, 255));
pTree->SetBkColor(RGB(255,255,128));
pTree->Invalidate();
//общие значения древовидной структуры
TV_INSERTSTRUCT tvin;
tvin.hParent = NULL;
tvin.hInsertAfter = TVI_LAST;
tvin.item.mask = TVIF_TEXT | TVIF_PARAM;
tvin.item.hItem = NULL;
tvin.item.state = 0;
tvin.item. stateMask = 0;
tvin.item.cChildren = 0;
tvin.item.lParam = 0;
// верхний уровень
tvin.item.pszText = "Первый";
tvin.item.lParam = 5;
HTREEITEM hFirst = pTree->InsertItem(&tvin);
tvin.item.pszText = "Второй";
tvin.item.lParam = 6;
HTREEITEM hSecond = pTree->InsertItem(&tvin);
// второй уровень
tvin.hParent = hFirst;
tvin.item.pszText = "A";
pTree->InsertItem(&tvin);
tvin.item.lParam = 0;
tvin.item.pszText = "B";
tvin.item.lParam = 1;
pTree->InsertItem(&tvin);
// второй уровень
tvin.hParent = hSecond;
tvin.item.pszText = "A";
tvin.item.lParam = 2;
pTree->InsertItem(&tvin);
tvin.item.pszText = "B";
tvin.item.lParam = 3;
pTree->InsertItem(&tvin);
tvin.item.pszText = "C";
tvin.item.lParam = 4;
HTREEITEM hOther = pTree->InsertItem(&tvin);
Kод устанавливает в TV_INSERTSTRUCT
общие значения, а затем вызывает Insertltem для создания узлов
в древовидной структуре.Компилируем наш проект и запускаем. Отлично, древовидный
список создан и даже при кликах по нему раскрывается и закрывается. Теперь
обучимся делать так, чтобы при одинарном,двойном клике и при выделении ветвей(они
же узлы, они же Item - ы) происходили события.
Для этого создадим обработчики событий NM_CLICK, NM_DLCLCK
для объекта IDC_TREE
с помощью ClassWizard
. Также обратите внимание на значение поля lParam,
которое мы задаем при заполнении структуры TV_INSERTSTRUCT,
этими значениями следует пользоваться в обработчиках событий
NM_CLICK, NM_DLCLCK .Так же необходимо завести две переменные с помощью
Class Wizard. Открываем вкладку Member Variable
и назначаем переменные,для IDC_EDIT тип String
переменная m_l и для IDC_EDIT_1
тип String переменная m_a,
для IDC_TREE тип CTreeCtrl
имя m_hTree. Запрограммируем одиночное нажатие
клавишей мыши:
void CTreeCtrlDlg::OnClickTree(NMHDR* pNMHDR,
LRESULT* pResult)
{
// TODO: Add your control notification handler code here
CPoint point;
GetCursorPos(&point);
m_hTree.ScreenToClient(&point);
UINT uFlags;
HTREEITEM hItem = m_hTree.HitTest(point, &uFlags);
// && - логическое И, & операция
адресации,которая возвращает адрес операнда
if ((hItem != NULL) && (TVHT_ONITEM & uFlags))
{ m_hTree.Select(hItem, TVGN_CARET);
m_hTree.ClientToScreen(&point);
DWORD ItemData=m_hTree.GetItemData(hItem);
if (ItemData= =0)
m_l="A";
UpdateData(FALSE);
if (ItemData= =1)
m_l="B";
UpdateData(FALSE);
if (ItemData= =2)
m_l="A";
UpdateData(FALSE);
if (ItemData= =3)
m_l="B";
UpdateData(FALSE);
if (ItemData= =4)
m_l="C";
UpdateData(FALSE);
if (ItemData==5)
m_a="Находимся в первом";
UpdateData(FALSE);
if (ItemData==6)
m_a="Находимся во втором";
UpdateData(FALSE);
}
*pResult = 0;
Теперь при одиночном клике на одном из узлов
в EditBox должны отображаться буквы и текст, который
мы запрограммировали. Теперь напишем код для двойного нажатия клавиши мыши:
void CTreeCtrlDlg::OnDblclkTree(NMHDR* pNMHDR,
LRESULT* pResult)
{
// TODO: Add your control notification handler code here
CPoint point;
GetCursorPos(&point);
m_hTree.ScreenToClient(&point);
UINT uFlags;
HTREEITEM hItem = m_hTree.HitTest(point, &uFlags);
if ((hItem != NULL) && (TVHT_ONITEM & uFlags))
{
m_hTree.Select(hItem, TVGN_CARET);
m_hTree.ClientToScreen(&point);
DWORD ItemData=m_hTree.GetItemData(hItem);
if (ItemData==5)
*pResult = 0;
else
if (ItemData==6)
*pResult = 0;
else
AfxMessageBox(" Dblclk Button Click ");
}
*pResult = 0;
}
Теперь при при клике по одной из раскрытых
веток должно появиться сообщение:
В данных примерах при помощи функции HitTest() мы запрограмировали так, что клик будет обрабатываться только при условии нахождения курсора мыши на элементе дерева.
© Goodluck Дмитрий (Cema)