Операционная система Windows 95 для программиста© Александр Фролов, Григорий ФроловТом 22, М.: Диалог-МИФИ, 1993, 271 стр. 4.1. Создание органа управления Tree ViewНиже мы перечислили основные действия, которое должно выполнить приложение для того чтобы создать орган управления Tree View:
Создание окна Tree ViewОкно органа управления Tree View создается функцией CreateWindowEx на базе класса окна WC_TREEVIEW: hwndTree = CreateWindowEx(0L, WC_TREEVIEW, "", WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hWnd, (HMENU) IDC_TREEVIEW, hInst, NULL); Перед вызовом этой функции (как и для других рассмотренных в этой книге органов управления) вы должны загрузить в память DLL-библиотеку COMCTL32.DLL . Это можно сделать при помощи функции InitCommonControls , вызвав ее без параметров. Для окна органа управления Tree View вы можете
использовать следующие дополнительные стили
окна:
Дополнительные стили окна могут комбинироваться между собой и со стандартными стилями окна при помощи логической операции ИЛИ. С помощью пары функций GetWindowLong и SetWindowLong приложение может изменить стиль созданного ранее окна органа управления Tree View (можно использовать тот же способ, что и для органа управления List View). Создание списка изображенийДля органа управления Tree View вы должны создать список изображений, которые будут использованы для отображения состояния элементов дерева. Заметим, что каждый элемент может находиться в выбранном или невыбранном состоянии. Соответственно, для отображения этих состояний вы можете использовать разные изображения. Список изображений создается рассмотренной нами ранее функцией ImageList_Create : HIMAGELIST WINAPI ImageList_Create( int cx, // ширина изображения int cy, // высота изображения UINT flags, // тип изображения int cInitial, // первоначальное количество изображений int cGrow); // количество изображений, на которое // увеличится размер списка при добавлении новых изображений Вот, например, как создается список из трех изображений размером 33 х 33 пиксела в нашем приложении Some Books, исходные тексты которого мы приведем немного позже: himl = ImageList_Create(33, 33, FALSE, 3, 0); Заполнение списка изображенийОбычно в список изображений для органа управления Tree View добавляют не пиктограммы, имеющие квадратную форму и относительно большой размер, и битовые изображения. Это можно сделать при помощи макрокоманды ImageList_Add : hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BOOKS)); idxBooks = ImageList_Add(himl, hBmp, NULL); hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BOOK_CLOSED)); idxBookClosed = ImageList_Add(himl, hBmp, NULL); hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BOOK_OPENED)); idxBookOpened = ImageList_Add(himl, hBmp, NULL); Эта макрокоманда возвращает номера добавленных изображений, которые потребуются в дальнейшем при добавлении элементов в дерево. Подключение списка изображенийСозданный список изображений подключается к органу управления Tree View при помощи макрокоманды TreeView_SetImageList : HIMAGELIST TreeView_SetImageList( HWND hwnd, // идентификатор окна органа Tree View HIMAGELIST himl, // идентификатор подключаемого списка int iImageTree); // тип изображений в списке Первые два параметра макрокоманды задают, соответственно, идентификатор окна органа Tree View и идентификатор подключаемого списка, который мы только что создали и заполнили. Параметр iImageTree может иметь следующие значения:
Ниже приведена строка исходного текста приложения, подключающая список изображений himl к органу управления hwndTree: TreeView_SetImageList(hwndTree, himl, TVSIL_NORMAL); Вставка элементов дереваВставка элементов в дерево выполняется при помощи макрокоманды TreeView_InsertItem , которая посылает органу управления Tree View сообщение TVM_INSERTITEM : HTREEITEM TreeView_InsertItem( HWND hwnd, // идентификатор окна органа Tree View TV_INSERTSTRUCT lpis); // указатель на структуру TV_INSERTSTRUCT Через параметр hwnd Этой макрокоманде необходимо передать идентификатор созданного органа управления Tree View, а через параметр lpis - адрес структуры типа TV_INSERTSTRUCT . Эта структура и указатель на нее определены так: typedef struct _TV_INSERTSTRUCT { HTREEITEM hParent; // идентификатор родительского элемента HTREEITEM hInsertAfter; // идентификатор элемента, после // которого будет выполнена вставка TV_ITEM item; // информация о вставляемом элементе } TV_INSERTSTRUCT, FAR *LPTV_INSERTSTRUCT; Если вставляется корневой элемент, поле hParent должно содержать значение TVI_ROOT или NULL. Если же вставляется вложенный элемент, в это поле необходимо записать идентификатор родительского элемента (т. е. элемента, расположенного выше по иерархии). В поле hInsertAfter следует записать идентификатор
элемента, после которого будет вставлен данный
элемент или одно из следующих значений:
Структура item содержит информацию о вставляемом элементе. Соответствующий тип TV_ITEM определен следующим образом: typedef struct _TV_ITEM { UINT mask // маска использования полей структуры TV_ITEM HTREEITEM hItem; // номер элемента UINT state; // текущее состояние элемента UINT stateMask; // маска состояния элемента LPSTR pszText; // адрес текстового буфера int cchTextMax; // размер текстового буфера int iImage; // номер изображения невыбранного элемента int iSelectedImage;// номер изображения выбранного элемента int cChildren; // флаг дочерних элементов LPARAM lParam;// 32-битное значение, связанное с элементом } TV_ITEM, FAR *LPTV_ITEM; Назначение большинства полей такое же, как и одноименных полей структуры LV_ITEM. Поле маски mask определяет, какие из полей
структуры TV_ITEM будут использованы при добавлении
элементов. Возможны следующие значения масок (их
можно объединять при помощи логической операции
ИЛИ):
В поля iImage и iSelectedImage следует записать номера изображений из списка, которые будут использованы для элемента, соответственно, в выбранном и невыбранном состоянии. Поле cChildren содержит флаг, который показывает, есть ли у данного элемента связанные с ним дочерние элементы. Если есть, то в этом поле должно быть записано значение 1, в противном случае - 0. Если же в поле cChildren записать значение I_CHILDRENCALLBACK, приложение должно обрабатывать извещения TVN_GETDISPINFO и TVN_SETDISPINFO (аналогичные извещениям LVN_GETDISPINFO и LVN_SETDISPINFO, которые посылаются органу управления List View). Для удобства в приложении Some Books мы добавляем элементы дерева при помощи функции InsTreeItem, исходный текст которой приведен ниже: HTREEITEM InsTreeItem(HTREEITEM hParent, LPSTR szText, HTREEITEM hAfter, int iImage, int iSelectedImage) { TV_INSERTSTRUCT tvins; HTREEITEM hItem; memset(&tvins, 0, sizeof(tvins)); tvins.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; tvins.item.pszText = szText; tvins.item.cchTextMax = lstrlen(szText); tvins.item.iImage = iImage; tvins.item.iSelectedImage = iSelectedImage; tvins.hInsertAfter = hAfter; tvins.hParent = hParent; hItem = TreeView_InsertItem(hwndTree, &tvins); return hItem; } Процедура заполнения дерева в приложении Some Books выглядит следующим образом. Вначале мы вставляем корневой элемент, которому соответствует строка szBooks ("Книги издательства АО 'Диалог-МИФИ'"): hItem = InsTreeItem((HTREEITEM)TVI_ROOT, szBooks, (HTREEITEM)TVI_FIRST, idxBooks, idxBooks); Этот элемент является корневым, поэтому параметр hParent имеет значение TVI_ROOT. Вставляемый элемент будет расположен первым по порядку, так как для параметра hAfter задано значение TVI_FIRST. Далее мы вставляем два элемента, расположенные ниже по иерархии (первый уровень вложенности). Это текстовые строки szBSPSeries ("Библиотека системного программиста, (C) Фролов А.В., Фролов Г.В., 1991-1995 г.") и szStepSeries ("Персональный компьютер. Шаг за шагом, (C) Фролов А.В., Фролов Г.В., 1994-1995 г."): hBSPItem = InsTreeItem(hItem, szBSPSeries, (HTREEITEM)TVI_SORT, idxBooks, idxBooks); hStepItem = InsTreeItem(hItem, szStepSeries, (HTREEITEM)TVI_SORT, idxBooks, idxBooks); Затем для каждого элемента первого уровня вставляем по два элемента второго уровня: InsTreeItem(hBSPItem, rgSPLBookInfo[0].szBookName, (HTREEITEM)TVI_SORT, idxBookClosed, idxBookOpened); InsTreeItem(hBSPItem, rgSPLBookInfo[1].szBookName, (HTREEITEM)TVI_SORT, idxBookClosed, idxBookOpened); InsTreeItem(hStepItem, rgStepBookInfo[0].szBookName, (HTREEITEM)TVI_SORT, idxBookClosed, idxBookOpened); InsTreeItem(hStepItem, rgStepBookInfo[1].szBookName, (HTREEITEM)TVI_SORT, idxBookClosed, idxBookOpened); Так как в параметре hAfter указана константа TVI_SORT, все добавленные элементы будут отображаться в алфавитном порядке. |