API и FreeBasic. (дочерние окна-TreeView)

При упорядочивании какой-либо информации часто требуется создать древовидную структуру. Примеры древовидной структуры можно встретить практически везде. Самый наверно простой пример - это проводник Windows (колонка слева), в которой в порядке иерархии размещены папки. Создать подобную колонку нетрудно с помощью контрола TreeView.

Для создания контрола TreeView нужно:

  1. Создать дочернее окно на базе имеющегося контрола SysTreeView32
  2. Создать структурную переменную TVINSERTSTRUCT
  3. Заполнить поля структуры для каждого добавляемого пункта контрола
  4. Отправить контролу сообщение TVM_INSERTITEM и в параметре LPARAM передать указатель на заполненную структуру TVINSERTSTRUCT (в нашем случае мы используем макрос TreeView_InsertItem)

Необязательно , но практически всегда к контролу подключают список изображений с иконками или изображениями. В нашем примере ниже так и сделано.

Структура TVINSERTSTRUCT выглядит так:

Type TVINSERTSTRUCTA
    hParent As HTREEITEM
    hInsertAfter As HTREEITEM
    Union
        itemex As TVITEMEX
        item As TVITEM
    End Union
End Type

  • hParent - идентификатор родительского пункта, если есть или TVI_ROOT
  • hInsertAfter - идентификатор пункта, после которого будет выполнена вставка
  • itemex - информация о вставляемом пункте (расширенная структура TVITEM)
  • item - информация о вставляемом пункте (структура TVITEM)

Вложенная структура TVITEM выглядит так:

Type TVITEM
    mask As UINT
    hItem As HTREEITEM
    state As UINT
    stateMask As UINT
    pszText As LPSTR
    cchTextMax As Integer
    iImage As Integer
    iSelectedImage As Integer
    cChildren As Integer
    lParam As LPARAM
End Type

  • mask - маска использования нужных полей структуры
    • TVIF_TEXT - поле pszText
    • TVIF_IMAGE - поле iImage
    • TVIF_SELECTEDIMAGE - поле iSelectedImage
    • TVIF_PARAM - поле lParam
    • TVIF_CHILDREN - поле cChildren
    • TVIF_HANDLE - поле hItem
    • TVIF_STATE - поле state
  • hItem - определяет элемент, к которому относится эта структура
  • state - текущее состояние элемента
  • stateMask - маска состояния элемента
  • pszText - указатель на буфер строки для пункта
  • cchTextMax - размер строкового буфера
  • iImage - индекс в списке изображений невыбранного пункта
  • iSelectedImage - индекс в списке изображений выбранного пункта
  • cChildren - флаг дочерних элементов
  • lParam - дополнительное 32-битное значение, связанное с элементом

Собственно из вышеописанного должно быть понятно, что для использования в контроле строк , необходимо указать маску TVIF_TEXT. Так же обязательно при использовании строк указать буфер с нужной строкой и размер этого буфера. Если понадобится использовать изображения\иконки , то нужно определить дополнительно маски TVIF_IMAGE , TVIF_SELECTEDIMAGE. А в полях структуры iImage и iSelectedImage передать индексы списка изображений , который перед этим нужно создать и заполнить (про списки изображений рассказывалось в этой статье). И конечно в любом случае нужно определить место каждого пункта в иерархии. Для этого нужно правильно определить пункты структуры TVINSERTSTRUCT hInsertAfter и hParent

Обработка сообщений контрола ведется как и у всех контролов в процедуре родительского окна. При получении сообщения WM_NOTIFY как и в случае с LISTVIEW в параметре LPARAM оказывается указатель на структуру NMHDR . Далее проверяется код извещения и вынимаются нужные данные из структур либо заполняются и отправляются соответствующие сообщения. Кол-во извещений, сообщений довольно значительно и для разных задач. Некоторые из них (остальные можете посмотреть ЗДЕСЬ.):

Извещения:

  • TVN_SELCHANGED - Уведомляет родительское окно TreeView, что выбор изменился от одного пункта к другому.
  • TVN_BEGINDRAG - Начало операции переноса "drag and drop" для левой кнопки мыши
  • TVN_BEGINLABELEDIT - Начало операции редактирования названия элемента
  • TVN_BEGINRDRAG - Начало операции переноса "drag and drop" для правой кнопки мыши
  • TVN_DELETEITEM - Удаление определенного элемента дерева
  • TVN_ENDLABELEDIT - Завершение операции редактирования названия элемента
  • TVN_GETDISPINFO - Контрол запрашивает информацию, необходимую для отображения элемента
  • TVN_KEYDOWN - Была нажата клавиша

Сообщения:

  • TVM_GETTEXTCOLOR - Получение цвета текста котрола
  • TVM_CREATEDRAGIMAGE - Создание изображения, необходимого для выполнения операции перемещения "drag and drop"
  • TVM_GETTOOLTIPS - Получение хендла tooltip, определенного для treeview
  • TVM_DELETEITEM - Удаление элемента из дерева
  • TVM_EDITLABEL - Начать процесс редактирования имени элемента
  • TVM_GETCOUNT - Получение количества элементов в дереве
  • TVM_GETEDITCONTROL - Получение хендла редактора, который используется для редактирования названия элемента
  • TVM_SETTOOLTIPS - Установка tooltip для treeview
  • TVM_GETIMAGELIST - Получение хендла списка изображения
  • TVM_GETINDENT - Определение размера сдвига вложенных элементов(в пикселах)
  • TVM_GETISEARCHSTRING - Получение инкрементальной строки поиска
  • TVM_GETITEM - Получение всех или некоторых атрибутов элемента дерева
  • TVM_GETITEMRECT - Определение границ, занимаемых элементом в окне просмотра.
  • TVM_GETVISIBLECOUNT - Определение количества видимых элементов в контроле
  • TVM_HITTEST - Определение элемента, расположенного в данной позиции
  • TVM_INSERTITEM - Вставка элемента
  • TVM_SETTEXTCOLOR - Установка цвета текста для контрола
  • TVM_SELECTITEM - Выделение заданного элемента
  • TVM_SETIMAGELIST - Подключение списка изображений к контролу
  • TVM_SETINDENT - Установка размера сдвига вложенных элементов(в пикселах)
  • TVM_SETITEM - Установка всех или некоторых атрибутов заданного элемента дерева
  • TVM_SORTCHILDREN - Сортировка вложенных элементов для заданного элемента дерева

И конечно пример:

#INCLUDE "windows.bi"
#INCLUDE "win/commctrl.bi"
#INCLUDE "win/shellapi.bi"

Dim msg As MSG
Dim As WNDCLASSEX wc
Dim As String NameClass="MyClass"
Dim As HINSTANCE Hinst=GetModuleHandle(0)
Dim Shared As ZString*15 szArray(6) = {_
"First_Root",_
"One",_
"Two",_
"Three",_
"Four",_
"Five",_
"Second_Root" _
}


Function wndproc(hwnd As HWND, msg As Uinteger,_
    wparam As WPARAM, lparam As LPARAM) As Integer
    Static As HWND hTree
    Select Case msg
        Case WM_CREATE

            ' создаем контрол
            hTree = CreateWindowEx( 0, "SysTreeView32", 0,_
                    WS_CHILD+WS_VISIBLE+TVS_HASBUTTONS+_
                    TVS_LINESATROOT+WS_BORDER+TVS_HASLINES,_
                    10, 10, 200, 200, hwnd, Cast(HMENU,1), 0, 0)

            ' узнаем путь к системной папке
            Dim szPath As String*512
            GetSystemDirectory(Cast(LPSTR,@szPath),Len(szPath))

            ' извлекаем иконки из DLL файла
            Dim As HICON icon1,icon2
            icon1 = ExtractIcon(0,szPath & "\Shell32.DLL",3)
            icon2 = ExtractIcon(0,szPath & "\Shell32.DLL",45)

            ' создаем список изображений
            Dim As HIMAGELIST ImageList = ImageList_Create(_
            16,16,ILC_COLOR32 Or ILC_MASK,1,1)

            ' делаем цвет фона иконок в списке прозрачным
            ImageList_SetBkColor(ImageList,_
                TreeView_GetBkColor(hTree) Xor &hff000000)

            ' добавляем иконки в список изображений
            Dim As Integer iNoSelect = ImageList_AddIcon(ImageList,icon1)
            Dim As Integer iSelect = ImageList_AddIcon(ImageList,icon2)

            ' подключаем список изображений к контролу TreeView
            SendMessage(hTree,TVM_SETIMAGELIST,TVSIL_NORMAL,Cast(LPARAM,ImageList))

            '------------------заполняем контрол пунктами-----------------
            Dim tvis As TVINSERTSTRUCT
            Dim htr(11) As HTREEITEM

            ' Создаем корневые пункты
            For i As Integer = 0 To 1
                tvis.Item.Mask           = TVIF_TEXT+TVIF_IMAGE+TVIF_SELECTEDIMAGE
                tvis.item.pszText        = Strptr(szArray(i*6))
                tvis.item.cchTextMax     = Len(szArray(i*6))
                tvis.hParent             = Cast(HTREEITEM,TVI_ROOT)
                htr(i)                       = TreeView_InsertItem(hTree, @tvis )
                'Создаем подпункты
                For j As Integer = 1 To 5
                    tvis.Item.Mask           = TVIF_TEXT+TVIF_IMAGE+TVIF_SELECTEDIMAGE
                    tvis.item.pszText        = Strptr(szArray(j))
                    tvis.item.cchTextMax     = Len(szArray(j))
                    tvis.item.iImage         = iNoSelect
                    tvis.item.iSelectedImage = iSelect
                    tvis.hInsertAfter        = Cast(HTREEITEM,j)
                    tvis.hParent             = Cast(HTREEITEM,htr(i))
                    htr(j+i*5+1)                 = TreeView_InsertItem(hTree, @tvis )
                Next
            Next


        Case WM_NOTIFY
            ' получаем текст из пункта TreeView
            Dim As NMHDR Ptr nmhdr = Cast(NMHDR Ptr,lParam)
            If nmhdr->code =  TVN_SELCHANGED Then
                Dim As NMTREEVIEW Ptr NMTW = Cast(NMTREEVIEW Ptr,LPARAM)
                Dim TV_ITEM As TVITEM
                Dim As String*256 szBuf
                TV_ITEM.pszText = Cast(LPSTR,@szBuf)
                TV_ITEM.cchTextMax = 20
                TV_ITEM.mask = TVIF_TEXT
                TV_ITEM.hItem = NMTW->itemNew.hItem
                SendMessage(hTree,TVM_GETITEM,0,Cast(LPARAM,@TV_ITEM))
                MessageBox(0,szBuf,"",0)
            Endif

        Case WM_DESTROY
            PostQuitMessage(0)
    End Select
    Return DefWindowProc(hwnd,msg,wparam,lparam)
End Function

With wc
    .cbSize=SizeOf(WNDCLASSEX)
    .style=CS_HREDRAW Or CS_VREDRAW
    .lpfnWndProc=@wndproc
    .hInstance=Hinst
    .hIcon=LoadIcon(0,IDI_WINLOGO)
    .hCursor=LoadCursor(0,IDC_ARROW)
    .hbrBackground=Cast(HBRUSH,COLOR_WINDOWFRAME)
    .lpszClassName=StrPtr(NameClass)
    .hIconSm=.hIcon
End With

If RegisterClassEx(@wc)=0 Then
    Print "Register error, press any key"
    Sleep
    End
Endif

CreateWindowEx(0,NameClass,"TreeView",_
    WS_VISIBLE Or WS_OVERLAPPEDWINDOW,100,100,235,255,0,0,Hinst,0)

While GetMessage(@msg,0,0,0)
    TranslateMessage(@msg)
    DispatchMessage(@msg)
Wend

treeview.png

содержание | назад | вперед