Компонент TTreeView називають деревом (рис. 5.3).
Компонент TTreeView - правонаступник компонента TOutiine, розробленого Borland ще для Delphi 1 і призначений для відображення ієрархічної інформації. Його "серцем" є властивість
property Items: TTreeNodes;
Мал. 5.3. Зовнішній вигляд компонента TTreeView
Дана властивість - це список всіх вершин дерева, причому список, що володіє додатковими корисними властивостями. Кожен з елементів списку - це об'єкт типу TTreeNode. Властивості його зведені в табл. 5.3.
Таблиця 5.3. Список властивостей об'єкта TTreeNode
Елементи списку з'являються в декількох колонках один під іншим. У першій міститься маленький значок і напис, в інших - певна програмістом інформація. Якщо властивість ShowColumnHeaders встановлено в значення True, колонки забезпечуються заголовками
Як і для попереднього компонента, елементи списку містяться у властивості items. Це і є власне список; нічого незвичайного, крім методів додавання / видалення, там немає. Кожен елемент списку (об'єкт TListitem) в свою чергу схожий на компонент TTreeNode. Але у нього є і важлива відмінність - він може стати носієм великої кількості додаткової інформації. Крім властивості Data у нього є і властивість
property Subltems: TStrings;
За допомогою цієї властивості з кожним елементом списку може бути пов'язаний цілий набір рядків і об'єктів. Але як ці рядки показати користувачеві?
Саме вони повинні, за задумом розробників цього елемента управління, відображатися в режимі відображення vsReport. Спочатку слід створити необхідну кількість заголовків колонок (заповнивши властивість columns), враховуючи, що перша з них буде відведена під сам текст елемента списку (властивість caption). Наступні ж колонки будуть відображати текст рядків ІЗ властивості Items. Subltems (рис. 5.5).
Мал. 5.5. Так буде розташовуватися інформація компонента TListView в режимі vsReport
Елементи в списку можуть бути відсортовані - за це відповідає властивість SortType. Можна впорядкувати елементи не тільки за назвою (це можливо при значенні SortType, рівному stText), але і за даними (значення stData і stBoth), як це зроблено в утиліті Explorer. Для реалізації такого сортування потрібно обробити події OnColumnClick І OnComparel
var ColNum. Integer;
procedure TMainForm.ListViewlColumnClick (Sender: TObject; Column:
procedure TMainForm.ListViewlCompare (Sender: TObject; Iteml, Item2:
TListltem; Data: Integer; var Compare: Integer);
if ColNum = 0 then // Тема
Compare: = CompareStr (Iteml.Caption, Item2 .Caption);
Item2 .Subltems [ColNum-1]); end;
Розглянемо приклад використання компонентів TTreeview і TListview. Де їх спільне застосування буде корисним? Виберемо для цього відображення даних системного реєстру. З одного боку, ключі в реєстрі впорядковані ієрархічно. З іншого, кожен з них може мати кілька
різнотипних значень. Таким чином, ми майже прийшли до того ж рішення, що і розробники з Microsoft, які створили утиліту Registry Editor - зліва дерево ключів, праворуч - розширений список їх вмісту.
Рис.5.6. Додаток Mini-Registry browser А ось і весь його вихідний код:
Лістинг 5.1. Додаток Mini-Registry-browser, головний модуль
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Grids, Outline, ComCtrls, ImgList, ExtCtrls;
procedure FormCreate (Sender: TObject);
procedure TreeViewlChange (Sender: TObject; Node: TTreeNode);
procedure FormDestroy (Sender: TObject);
procedure TreeViewlExpanded (Sender: TObject; Node: TTreeNode);
procedure TreeViewlGetlmagelndex (Sender: TObject; Node: TTreeNode);
procedure ShowSubKeys (ParentNode: TTreeNode; depth: Integer);
function GetFullNodeName (Node: TTreeNode): string;
if Expanded then Imagelndex: = 2
else Imagelndex: = 3;
Для роботи з системним реєстром використовується об'єкт VCL TRegistry, вдало інкапсулює всі призначені для цього функції Windows API. У обробнику події OnCreate головною форми створюється об'єкт Reg, а також до списку Listview1 додаються два заголовка (властивість Columns).
Пояснень вимагає принцип побудови дерева ключів. По-перше, це додаток відображає тільки один з системних ключів (а саме HKEY_LOCAL_MACHINE); при бажанні його можна замінити або додати інші. По-друге, спроба побудувати все "розлоге" дерево ключів відразу займе дуже багато часу і напевно не сподобається користувачам. Згадаймо, адже утиліта Registry Editor працює досить швидко. Значить, доведеться будувати дерево динамічно - створювати і показувати дочірні вузли в момент розгортання батьківського вузла. Для цього використовується подія OnExpand компонента TreeView1.
Зупинимося на секунду. А які вузли позначати кнопкою розгортання (з позначкою "+"), адже у батьківського вузла ще немає нащадків? Вихід зі становища такої - в момент побудови ключа перевірити, чи є у нього дочірні. Якщо так, то до нього додається один (фіктивний) порожній ключ. Його єдина роль - дати системі поставити "+" проти батьківського вузла.
Коли ж користувач клацнув на кнопці, зазначеної знаком "+", і батьківський вузол розгортається, фіктивний дочірній вузол видаляється і замість нього створюються вузли справжні, отримані шляхом сканування реєстру (див. Метод ShowSubKeys).
Забезпечимо вузли картинками. Для цього в компонент imageList1 помістимо картинки, відповідні відкритою і закритою папок. Нагадаємо, що для відтворення і зміни картинок є спеціальні події - OnGetlmageIndex І OnGetSelectedIndex. В даному прикладі у двох ЦИХ подій один обробник: розгорнутому вузлу він зіставляє картинку розкритої папки, а згорнутому - закритою.
На завершення слід сказати про дуже важливу особливість компонента TListview. Коли він відображає великий обсяг інформації, обробка даних може затягнутися дуже і дуже надовго і зайняти занадто багато пам'яті. Вихід - перевести список в так званий віртуальний режим. Він застосовується для тих випадків, коли елементів в списку занадто багато і зберігати їх там неможливо з міркувань економії часу або пам'яті. Вихід з положення простий:
1. Переводимо компонент у віртуальний режим установкою властивості OwnerData в значення True.
2. Повідомляємо списку скільки в ньому має бути елементів установкою потрібного значення items.Count.
3. Щоб надати потрібні дані, програміст повинен передбачити обробку подій OnData, OnDataFind, OnDataHint і OnDataStateChange. Як мінімум потрібно описати обробник події OnData.
TLVOwnerDataEvent = procedure (Sender: TCbject; Item: TListltem) of object;
Вам передається об'єкт TListitem, і всередині обробника події OnData необхідно динамічно "оформити" його - повністю, від заголовка до картинок.
Виникає ця подія перед кожною перемальовуванням списку. Так що, якщо збір даних для вашого списку займає більш-менш тривалий час, краще не пов'язувати його з подією OnData - перерисовка сильно затягнеться. До того ж у віртуальному режимі сортувати список неможливо.
Borland докладає до Delphi 7 прекрасний приклад до вищесказаного - Virtual Listview. До нього і відсилаємо зацікавленого читача.
Відповіді на питання по компоненту TListview можна знайти відразу в двох місцях: "рідному" файлі довідки d7vcl.hlp і файлі довідки Windows Win32.hip. У другому з них інформація міститься у вигляді опису повідомлень, що посилаються вікна класу Listview, і відповідних їм макросів. Деякі з них дозволять вам розширити функціональні можливості компонента TListview. Ці макроси містяться в файлі CommCtrl.pas.