Компоненти ttreeview і tlistview - глава 5

Компонент 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.