Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
942
Добавлен:
27.01.2014
Размер:
6.3 Mб
Скачать

Глава 6 Программирование приложений с графическим интерфейсом

____________________________________________________________________

// Определение логических дисков

if Find_Logical_Disks() then

begin

SetAllDirectories;

SetDirWin:= true;

end

else

{Если произошла ошибка в функции Find_Logical_Disks(),

то выбираем корневой каталог текущего диска}

SetCurrentDir('\');

{$ELSE}

SetCurrentDir('/'); // корневой каталог в Linux {$ENDIF}

if not SetDirWin then begin

path:= GetCurrentDir;

if FindFirst(path + '*', faDirectory, srNode) = 0 then

begin repeat

// Показываем только каталоги

if (srNode.Attr and faDirectory <> 0) and (Real_Directory(srNode.Name)) then begin

Node:= TreeView1.Items.AddChild(nil,

SysToUTF8(srNode.Name));

Node.ImageIndex:= 0;

Node.SelectedIndex:= 0;

{$IFDEF WINDOWS}

671

6.3 Визуальное программирование в среде Lazarus

____________________________________________________________________

searchMask:= path + srNode.Name + '\*'; {$ELSE}

searchMask:= path + srNode.Name + '/*'; {$ENDIF}

if FindFirst(searchMask, faDirectory, srChild) = 0 then

repeat

if (srChild.Attr and faDirectory <> 0) and Real_Directory(srChild.Name)

then Node.HasChildren:= true; until (FindNext(srChild) <> 0) or Node.HasChildren;

// Освобождение занятых ресурсов

SysUtils.FindClose(srChild);

end;

until FindNext(srNode) <> 0;

// Освобождение занятых ресурсов

SysUtils.FindClose(srNode);

end;

end;

TreeView1.EndUpdate;

end;

procedure TForm1.Show_Only_Dir(ParentNode: TTreeNode); var

srNode, srChild: TSearchRec; Node: TTreeNode;

path: string; searchMask: string;

672

Глава 6 Программирование приложений с графическим интерфейсом

____________________________________________________________________

begin

Node:= ParentNode; path:= '';

repeat

{$IFDEF WINDOWS}

path:= UTF8ToSys(Node.Text) + '\' + path; {$ELSE}

path:= '/' + Node.Text + '/' + path; {$ENDIF}

Node:= Node.Parent; until Node = nil;

if FindFirst(path + '*', faDirectory, srNode) = 0 then repeat

if (srNode.Attr and faDirectory <> 0) and Real_Directory(srNode.Name) then

begin

Node:= TreeView1.Items.AddChild(ParentNode,

SysToUTF8(srNode.Name));

Node.ImageIndex:= 0;

Node.SelectedIndex:= 0;

{$IFDEF WINDOWS}

searchMask:= path + srNode.Name + '\*'; {$ELSE}

searchMask:= path + srNode.Name + '/*'; {$ENDIF}

if FindFirst(searchMask, faDirectory, srChild) = 0 then

repeat

if (srChild.Attr and faDirectory <> 0) and

673

6.3 Визуальное программирование в среде Lazarus

____________________________________________________________________

Real_Directory(srChild.Name) then Node.HasChildren:= true;

until (FindNext(srChild) <> 0) or Node.HasChildren; SysUtils.FindClose(srChild);

end;

until FindNext(srNode) <> 0; SysUtils.FindClose(srNode);

end;

procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);

begin

if Node = nil then exit; TreeView1.BeginUpdate; Node.DeleteChildren; Show_Only_Dir(Node); Node.Expanded:= true; TreeView1.EndUpdate;

end;

procedure TForm1.TreeView1Expanding(Sender: TObject; Node: TTreeNode;

var AllowExpansion: Boolean); begin

TreeView1.BeginUpdate;

Node.DeleteChildren;

Show_Only_Dir(Node);

TreeView1.EndUpdate;

end; initialization

674

Глава 6 Программирование приложений с графическим интерфейсом

____________________________________________________________________

{$I unit1.lrs}

end.

Рассмотрим процедуру FormCreate. В ней, если это Windows, с помо-

щью функции Find_Logical_Disks() и процедуры

SetAllDirectories определяются имена разделов жестких дисков и выво-

дятся в TreeView1. Окно программы для Windows будет иметь вид, рис. 6.76:

Рис. 6.76. Вид окна программы в Windows

В Linux файловая система организована совсем по-другому. Поэтому мы оператором SetCurrentDir('/');

устанавливаем корневой каталог и программа сканирует каталоги только верх-

него уровня, рис. 6.77.

675

6.3 Визуальное программирование в среде Lazarus

____________________________________________________________________

Рис. 6.77. Вид окна программы в Linux

Таким образом, наша программа не сканирует все диски и каталоги. Про-

грамма вначале лишь определяет буквы дисков и разделов дисков (если это

Windows) или сканирует только каталоги самого верхнего уровня, расположен-

ные в корневом каталоге (если это Linux).

Лишь при нажатии пользователем на какой-либо узел или на кнопку рас-

крытия этого узла, программа начнет сканировать каталоги, расположенные на один уровень ниже и только для текущего каталога. Поясню примером. Пусть мы находимся в каталоге C:\lazarus\components\lazreport или

/usr/lib/lazarus/components/lazreport.

При нажатии на узел с именем 'lazreport' программа просканирует этот каталог и найдет пять подкаталогов doc, images, samples, source, tools.

При этом эти подкаталоги имеют в свою очередь еще вложенные подкаталоги,

но всех их программа в данный момент сканировать не будет! Для того чтобы определить, что, например, каталог samples имеет вложенные подкаталоги,

программе достаточно найти только один подкаталог (первый попавшийся!). В

нашем случае это будет каталог barcode.

Это позволяет значительно ускорить работу программы.

676

Глава 6 Программирование приложений с графическим интерфейсом

____________________________________________________________________

Рассмотрим процедуру Show_Only_Dir, которая и реализует изложен-

ный алгоритм. Процедура вызывается в обработчиках OnChange и OnExpanding. Вначале, процедура определяет полный путь к текущему ката-

логу, двигаясь снизу вверх от дочернего узла к родительскому и до корневого.

Затем запускается цикл поиска FindFirst – FindNext с помощью которо-

го находятся все подкаталоги текущего каталога. Вложенный цикл

FindFirst – FindNext позволяет определить, имеются ли у найденных подкаталогов вложенные подкаталоги. Этот внутренний цикл завершается, как только вложенный каталог найден, а его родитель помечается признаком

Node.HasChildren:= true.

Отметим еще, что перед вызовом процедуры Show_Only_Dir мы опера-

тором

Node.DeleteChildren

удаляем все потомки текущего узла, поскольку процедура заново формирует их.

Точно по такому же алгоритму сканируется корневой каталог в обработчике

OnCreate.

Вот, собственно и все! Осталось пояснить, для чего предназначена функция

Real_Directory().

Как известно, в каждом каталоге имеются две особые записи. Одна из них обозначается просто точкой и является ссылкой на текущий каталог, а вторая запись, обозначаемая двумя точками (по стандарту так и читается точка-точка)

является ссылкой на родительский каталог. Функции FindFirst–FindNext

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

677

6.3 Визуальное программирование в среде Lazarus

____________________________________________________________________

true, если это не так.

Компонент TListView

В отличие от TListBox компонент TListView позволяет отображать данные в разных стилях или режимах. Так, данные могут отображаться в виде списка, крупных или мелких пиктограмм и, наконец, в виде таблицы. Стиль отображения задается свойством ViewStyle, табл. 6.5.

Элементы списка содержатся в свойстве Items объекта TListItem.

Компонент можно заполнять как вручную, во время проектирования, так и про-

граммно. Для ручного заполнения имеется редактор, похожий на редактор

TTreeView. В нем точно так же задаются "Новый элемент" и "Новый подэле-

мент". В отличие от TTreeView в TListView допускается не более одного уровня вложенности подэлементов.

 

Таблица 6.5

Значение

Стиль отображения данных

 

 

vsIcon

Элементы списка появляются в виде больших знач-

 

ков с надписью под ними. Картинки для больших

 

значков хранятся в компоненте TImageList ука-

 

занном в свойстве LargeImages. Возможно их

 

перетаскивание.

 

 

vsSmallIcon

Элементы списка появляются в виде маленьких

 

значков с надписью справа. Картинки для малень-

 

ких значков хранятся в компоненте TImageList

 

указанном в свойстве SmallImages. Возможно их

 

перетаскивание

 

 

vsList

Элементы списка появляются в колонке один под

 

другим с надписью справа. Перетаскивание невоз-

 

можно

 

 

678

Глава 6 Программирование приложений с графическим интерфейсом

____________________________________________________________________

vsReport

Элементы списка появляются в нескольких колон-

 

ках один под другим. В первой содержится малень-

 

кий значок и надпись, в остальных — определенная

 

программистом информация. Если свойство Show-

 

ColumnHeaders установлено в значение true,

 

колонки снабжаются заголовками

 

 

Как и в TTreeView изображения необходимо предварительно занести в

TImageList, затем указывать индекс нужного изображения в свойстве

ImageIndex, рис. 6.78.

 

Рис. 6.78. Редактор элементов TListView

 

 

Но

подэлементы

будут

видны

только

в

режиме

vsReport. Для того чтобы информация, введенная на рис. 6.78. была видна,

необходимо создать четыре колонки (столбца). Для этого в Инспекторе объек-

тов нажмите кнопку с многоточием напротив свойства Columns, появится ре-

дактор колонок рис. 6.79. Чтобы добавить колонку нажмите кнопку "Добавить".

В Инспекторе объектов появятся свойства этой колонки, рис. 6.80. Свойст-

во Caption задает заголовок колонки, свойство Width ширину колонки. Ус-

679

6.3 Визуальное программирование в среде Lazarus

____________________________________________________________________

тановите необходимые свойства для каждого из четырех колонок и запустите программу, рис. 6.81.

Рис. 6.79. Редактор колонок Рис. 6.80. Свойства колонки

Рис. 6.81. Окно программы

Рассмотрим основные свойства компонента:

Columns – содержит объекты – колонки (столбцы). Колонки видны только для стиля отображения ViewStyle = vsReport. При этом должна быть оп-

ределена хотя бы одна колонка. Иначе элементы не будут видны;

Column[Index: integer] – открывает доступ к колонкам элементов по их индексам;

ColumnClick: boolean – разрешает или запрещает генерацию события

680