Итак, у дерева есть несколько элементов. Можно считать, что есть корневые элементы, есть ветвления и есть подчиненные элементы. Общее представление можно получить посмотрев картинку внизу.
Важное место при работе с деревом занимает указатель HTREEITEM, который указывает на элемент дерева. Именно этот указатель возвращается при многих операциях с деревом, например, получение текущего элемента, получение элемента выше или подчиненных элементов. Имея этот указатель можно получить доступ ко многим операциям над элементами и свойствам элемента. Практически все функции класса CTreeCtrl используют этот указатель в качестве параметров. Но это только указатель.
У дерева есть стили, с помощью которых можно управлять аспектами его отображения. Описание каждого стиля можно посмотреть в подробностях.
TVS_HASLINES TVS_LINESATROOT TVS_HASBUTTONS TVS_EDITLABELS TVS_SHOWSELALWAYS
Стили устанавливаются при создании окна. Для этого нужно перегрузить функцию Create вида наследника от CTreeView. В последствии стили можно изменить используя функции GetWindowLong и SetWindowLong.
Для добавления пункта необходимо послать сообщение TVM_INSERTITEM, это сообщение вернет указатель HTREEITEM однозначно определяющий пункт дерева. К счастью MFC скрывает от нас подобные подробности. Давайте посмотрим как это делается. Для вставки элемента мы должны послать сообщение и указать в параметрах структуру TVINSERTSTRUCT, которая содержит структуру TVITEM. Сложно ??? Класс CTreeCtrl скрывает эти подробности позволяя вместо посылки сообщений вызывать функции. Например, вот так это выглядит.
GetTreeCtrl().InsertItem(GetTreeCtrl().GetItemText(hi),notselect,select,hit,0);
В данном коде никаких сообщений посылать не надо.
Внимание !!! Работать с элементами управления Windows нужно на основе сообщений. Классы ....CTRL заменяют посылку сообщений вызывами функций классов. Это значительно упрощает программирование. Но вероятно и ведет к усечению ряда возможностей. Еще раз посылка сообщений заменена вызовом функции. Это очень важно для понимания работы многих элементов управления. Вот так реализована подмена сообщения.
_AFXCMN_INLINE BOOL CTreeCtrl::GetItem(TVITEM* pItem) const { ASSERT(::IsWindow(m_hWnd)); return (BOOL)::SendMessage(m_hWnd, TVM_GETITEM, 0, (LPARAM)pItem); }
С этим понятно. Теперь надо разобраться, как получить информацию от элемента дерева. Если без MFC, то нужно послать сообщение, а с MFC вызвать функцию GetItem, что одно и тоже. Вот она.
BOOL GetItem( TVITEM* pItem );
В эту функцию передается адрес структуры TVITEM, вот её описание.
typedef struct tagTVITEM { UINT mask; HTREEITEM hItem; UINT state; UINT stateMask; LPTSTR pszText; int cchTextMax; int iImage; int iSelectedImage; int cChildren; LPARAM lParam; } TVITEM, FAR *LPTVITEM;
Что здесь главное, ну во-первых, hItem должен указывать на элемент дерева, который существует. Дальше mask, а вот здесь указывается какие данные мы хотим извлечь.
Обратите внимание на то, что название это LPTSTR. То есть нужен буфер, в который она поместится. Вот пример кода извлекающего имя активного элемента.
void CLeftView::OnTest() { HTREEITEM hi; hi=GetTreeCtrl().GetSelectedItem(); if (hi!=NULL) { TV_ITEM pItem; // структура char szBuffer[20]; // буфер для названия memset(&pItem,0,sizeof(pItem)); // обнуляем структуру pItem.hItem=hi; // этого элемента информацию мы хотим получить pItem.mask= TVIF_TEXT ; // тип получаемой информации pItem.pszText = szBuffer; // куда вернуть pItem.cchTextMax=19; // размер буфера = размер char-1 для завершения строки GetTreeCtrl().GetItem(&pItem); // получить информацию AfxMessageBox(pItem.pszText); } else AfxMessageBox("Not Selected Item"); }
Итак, воспользовавшись этим можно получить всю информацию о элементе дерева и перевести указатель HTREEITEM в реальную структуру TV_ITEM.