Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование лекции.doc
Скачиваний:
49
Добавлен:
12.11.2019
Размер:
5.53 Mб
Скачать

18.4. Сканирование дисков и директорий

Что надо сделать, чтобы получить в программе красивое дерево директорий, как в Проводнике? Как получить список всех файлов, находящихся в указанном месте? Сделать это не очень просто, но вполне реально.

Для отображения файлов и директорий в Delphi есть старинные, еще для Windows 3.1, компоненты DriveComboBox, DirectoryListBox и FileListBox на закладке Win3.1 палитры компонентов. Использовать их не следует: они не только отпугивают пользователя древним внешним видом, но и не поддерживают отображение рабочего стола, сетевого окружения и других пунктов, появившихся в более новых версиях Windows. Поэтому есть два варианта: взяться за дело самому или встроить в свою программу настоящий Проводник. Сначала рассмотрим первый вариант.

Уже знакомая нам процедура FindFirst может использоваться для получения не только сведений об одном файле, но и о списке файлов и директорий. Для этого вместо имени в ней указывается маска поиска (скажем, для всех файлов - *.*, для документов Word - *.doc и т.д.)

Для начала напишем программку, которая выводит список всех файлов, находящихся в указанной директории, и список отходящих от нее поддиректорий. Список файлов будем выводить в компонент Memo1, а поддиректорий – в Memo1.

procedure TForm1.Button1Click(Sender: TObject);

var dir:string;

s:TSearchRec;

begin

if not(SelectDirectory('Выберите папку', '',dir)) then

exit;

memo1.Lines.Clear;

memo2.Lines.Clear;

FindFirst(dir+'\*.*',faAnyFile,s);

repeat

if s.name<>'.' then

if s.Attr=faDirectory then

memo2.Lines.Add(s.Name)

else

memo1.Lines.Add(s.Name);

until FindNext(s)<>0;

FindClose(s)

Строка ‘\*.*’ добавляется к выбранному пути для формирования маски поиска вида C:\Windows\*.*. В цикле информация о файлах считываются до тех пор, пока функция FindNext возвращает ненулевое значение. Процедура FindClose освобождает память, занятую в ходе выполнения сканирования каталога.

Внутри цикла пропускается бесполезное имя поддиректории ‘.’, соответствующее самой текущей директории. Далее проверяется, чем является только что считанный объект: файлом или директорией и в зависимости от этого название заносится в компоненты Memo1 или Memo2.

Чтобы построить настоящее дерево директорий, пригодится компонент TTreeView. Рассмотрим рекурсивную процедуру формирования дерева директорий на указанном диске. Ее параметрами являются ссылка на компонент типа TreeView и путь, начиная с которого будут сканироваться директории (например, ‘C:\’).

PROCEDURE FillTree(tree:TTreeView;dr:STRING);

PROCEDURE AddDir(h:TTreeNode);

VAR s:TSearchRec;

n:TTreeNode;

Path:STRING;

BEGIN

Path:=GetFullPath(h);

FindFirst(path+'*.*',faDirectory,s);

REPEAT

IF (s.Attr<>faDirectory) OR (s.Name='.') OR (s.Name='..') THEN

Continue;

n:=tree.Items.AddChild(h,S.Name);

Application.ProcessMessages;

AddDir(n)

UNTIL FindNext(s)<>0;

FindClose(s)

END;

BEGIN

WITH Form1 DO

BEGIN

tree.Items.Clear;

Screen.Cursor:=crHourGlass;

AddDir(tree.Items.Add(NIL,dr));

Screen.Cursor:=crDefault

END

END;

Рассмотрим работу программы. Процедуре AddDir на вход подается ссылка на узел дерева, начиная с которого будут добавляться ветки-директории. При первом выходе на вход подается вершина дерева, создающаяся командой tree.Items.Add(NIL,dr), где dr – имя начального каталога. Внутри процедуры AddDir вызывается функция GetFullPath, которая проходит по дереву от текущего уровня вверх до вершины и формирует полный путь к директории. Например, если в дереве есть ветки C:\, Windows, System32, то функция GetFullPath вернет полный путь вида 'C:\Windows\System32'. Затем выполняется цикл по поддиректориям, отходящим от текущей ветки дерева, и для каждой из них снова вызывается процедура AddDir, что обеспечивает сканирование всего диска. При этом пропускаются текущая директория и директория верхнего уровня, обозначаемые символам '.' и '..' соответственно. Результат работы такой программы показан на Рис. 18 .66.

Рис. 18.66 Результат построения дерева директорий.

Для использования тех же окон отображения файлов и директорий, что и в Проводнике, предусмотрен модуль shellctrls, который надо подключить к программе. В этом модуле описаны компоненты типа ShellTreeView (отображение дерева директорий – то, что мы видим на левой панели Проводника) и ShellListView (отображение списка поддиректорий и файлов – то, что мы видим на правой панели проводника). Фокус заключается в том, что данные компоненты по умолчанию отсутствуют на палитре компонентов, поэтому их надо создавать вручную. Что же, научимся и этому!

Последовательно поместим на форму следующие компоненты: панель инструментов ToolBar1 (закладка Win32), панель Panel1 с выравниванием влево (Align=alLeft), разделитель Splitter1 с закладки Additional также с выравниванием влево и еще одну панель с выравниванием alClient (Рис. 18 .67).

Рис. 18.67 Размещение компонентов на форме.

В дальнейшем левую панель займет компонент-дерево, а правую – список файлов и поддиректорий,

Объявим две глобальные переменные, которые будут представлять эти компоненты в программе:

var s:TShellTreeView;

l:TShellListView;

Напишем следующие обработчики событий формы OnCreate и OnDestroy:

procedure TForm1.FormCreate(Sender: TObject);

begin

s:=TShellTreeView.Create(Self);

l:=TShellListView.Create(Self);

s.Parent:=Panel1;

l.Parent:=Panel2;

S.Align:=alClient;

L.Align:=alClient;

l.ShellTreeView:=s

end;

procedure TForm1.FormDestroy(Sender: TObject);

begin

l.Free;

s.Free

end;

В обработчике события создания формы создаются два новых компонента, и указывается, что их родительскими компонентами являются соответственно левая и правая панели. К тому же устанавливается выравнивание alClient – по размеру родителя. Поэтому два новых компонента автоматически будут принимать размеры панелей, что избавляет от необходимости вычислять экранные координаты. Строчка l.ShellTreeView:=s связывает два компонента так, что при переходе в дереве на левой панели будет автоматически меняться список на правой панели – все, как в Проводнике. Запустим программу и убедимся, что мы написали свой Проводник!

Для изменения способа отображения файлов и поддиректорий на правой панели (в виде больших значков, маленьких значков, списка или таблицы) предназначено свойство ViewStyle компонента типа TShellListView. Разместим на компоненте ToolBar1 компонент TRadioGroup, установив его свойство Columns=4, Rows=1, а в свойство Items записав четыре строки – названия режимов отображения: "Большие значки", "Малые значки", "Список", "Таблица". Пишем следующий обработчик события OnClick компонента RadioGroup1:

procedure TForm1.RadioGroup1Click(Sender: TObject);

begin

WITH l DO

CASE RadioGroup1.ItemIndex OF

0: ViewStyle:=vsIcon;

1: ViewStyle:=vsSmallIcon;

2: ViewStyle:=vsList;

3: ViewStyle:=vsReport

END;

end;

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

Последнее, что осталось сделать – заставить программу реагировать на факт выбора файла. Для этого необходимо написать свою процедуру – обработчик события OnChange. Причем это должна быть не обычная процедура, а метод объекта. Удобнее всего сделать ее методом формы. Для этого в описании формы добавляем строчку:

type

TForm1 = class(TForm)

Panel1: TPanel;

Panel2: TPanel;

Splitter1: TSplitter;

ToolBar1: TToolBar;

RadioGroup1: TRadioGroup;

ToolButton1: TToolButton;

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure RadioGroup1Click(Sender: TObject);

procedure ChangerFile(Sender: TObject; Item: TListItem; Change: TItemChange);

private

{ Private declarations }

public

{ Public declarations }

end;

Рис. 18.68 Самодельный Проводник.

А в тексте модуля после оператора Implementation пишем:

procedure TForm1.ChangerFile(Sender: TObject; Item: TListItem; Change: TItemChange);

begin

if l.SelectedFolder<>nil then

Form1.Caption:=l.SelectedFolder.pathname

end;

Здесь в заголовок формы будет выводиться полный путь и название выбранного файла/директории. Перед этим проверяется, что объект действительно выбран (свойство SelectedFolder не равно Nil). В обработчик события OnCreate добавим строчку

l.OnChange:=ChangerFile

которая связывает выполнение процедуры ChangerFile с наступлением события OnChange. Окончательный вид приложения показан на Рис. 18 .68.