Реферат Курсовая Конспект
Дерево элементов TTreeView - раздел Образование, 11.19 Дерево Элементов (Ttreeview) .............
|
11.19 Дерево элементов (TTreeView) ................................................................................... 236
11.20 Список элементов (TListView) .................................................................................... 240
11.21 Простейший файловый менеджер. ............................................................................. 242
11.22 Улучшенный файловый менеджер (С возможностью запуска файлов) ................. 250
11.23 Подсказки для чайников (TStatusBar) ........................................................................ 252
11.24 Панель инструментов (TToolBar и TControlBar). ..................................................... 254
11.25 Перемещаемые панели и меню в стиле MS (Docking). ............................................ 258
11.19 Дерево элементов (TTreeView)
ейчас нам предстоит познакомиться с достаточно сложным, но мощным компонентом – дерево элементов (TreeView). Любая более менее большая программа обязательно использует этот компонент потому что он очень
удобен.
-TreeView
Давай сразу напишем пример и познакомимся с деревом на практике. Компонент TreeView достаточно сложный и с ним нужно знакомиться на практике, чтобы увидеть все прелести работы с ним.
Создай новый проект и брось на него два компонента: TreeView и ImageList. В список картинок ImageList засунь пару любых картинок, потом они пригодятся. А пока добавь ещё три кнопки (TButton):
1. 1. Добавить (в свойстве Name укажи AddButton).
2. 2. Добавить элемент (в свойстве Name укажи AddChildButton).
3. 3. Удалить (в свойстве Name укажи DelButton).
4. 4. Изменить заголовок (в свойстве Name укажи EditButton).
В результате у тебя должна быть форма приблизительно такого вида, как показано у меня на рисунке 11.19.1.
Теперь нужно указать у нашего дерева в свойстве Images установленный набор картинок. После этого можно переходить к кодингу.
По нажатию кнопки «Добавить» мы должны добавлять в дерево новый элемент. Для этого напишем следующий код:
Procedure TTreeViewForm.EditButtonClick(Sender: TObject); var
Begin
//Создаю списки маленьких и больших иконок. ListView1.LargeImages:=TImageList.Create(self); ListView1.SmallImages:=TImageList.Create(self);
Запрашиваю большие иконки SysImageList := SHGetFileInfo('', 0, SFI, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_LARGEICON); if SysImageList <> 0 then
Begin
//Присваиваю системные иконки в ListView1 ListView1.Largeimages.Handle := SysImageList; ListView1.Largeimages.ShareImages := TRUE;
End; //Запрашиваю маленькие иконки SysImageList := SHGetFileInfo('', 0, SFI, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_SMALLICON); if SysImageList <> 0 then
begin
ListView1.Smallimages.Handle := SysImageList;
ListView1.Smallimages.ShareImages := TRUE;
end; end;
В первых двух строчках я создаю списки маленьких и больших иконок. Свойства LargeImages и SmallImages имеют тип TImageList, но сразу после создания компонента они равны nil. Поэтому я создаю их присваивая результат вызова TImageList.Create(self). После этого они уже проинициализированы и необходимая память выделена.
Тут можно было поступить немного другим способом – поставить на форму два компонента TImageList и просто указать их в соответствующих свойствах. В этом случае не пришлось бы ничего инициализировать, потому что компоненты стоящие на форме инициализируются автоматически. Но я решил не делать этого, а показать тебе, что объектное свойство можно сразу заставить работать без использования дополнительных компонентов.
После этого я запрашиваю у системы список больших иконок. Для этого я использую функцию SHGetFileInfo, которая возвращает информацию о файле, директории или диске. Первый параметр -путь к файлу. Второй -атрибуты. Третий -указатель на ТSHFILEINFO. Четвертый -размер ТSHFILEINFO. Последний -флаги, указывающие на тип информации запрашиваемый у системы.
Теперь о том, как выглядит функция в моём примере. Первые два параметра пустые, это означает, что нам нужны глобальные данные, а не информация о конкретном файле. Если указать здесь реальные значения файла, то мы получим информацию о нём, а если указать нулевые значения, то мы получим системную информацию.
В качестве флагов я указываю SHGFI_SYSICONINDEX и SHGFI_LARGEICON. SHGFI_SYSICONINDEX означает, что я запрашиваю указатель на системный список иконок (ImageList). Второй флаг говорит, что мне нужны большие иконки.
При втором вызове этой функции (чуть ниже в коде) я запрашиваю маленькие иконки (SHGFI_SMALLICON). Функция возвращает мне указатель на соответствующий системе SysImageList, который я в последствии присваиваю в ListView1.LargeImages.Handle. После этого присваивания ListView1.LargeImages содержит все системные иконки размера 32х32.
Системный список иконок (ImageList) содержит все иконки, установленные в системе и ассоциированные с разными типами файлов. Эти иконки ты можешь видеть в Windows Explorer у вайлов doc, txt, ini, zip и др.
Теперь создадим обработчик события OnShow. В ней я вызываю другую процедуру AddFile, которая считывает все файлы из текущей директории.
procedure TForm1.FormShow(Sender: TObject);
begin
AddFile(Edit1.Text+'*.*',faAnyFile)
end;
Процедура AddFile объявлена в разделе privateнашей формы Form1следующим образом:
SHGFI_TYPENAME or SHGFI_SYSICONINDEX); Attributes := AttrStr(dwFileAttributes); //Добавляю новый элемент with ListView1.Items.Add do
Begin //Присваиваю его имя Caption := SearchRec.Name; //Присваиваю индекс из системного списка изображений ImageIndex := ShInfo.iIcon; //Присваиваю размер SubItems.Add(IntToStr(SearchRec.Size)); SubItems.Add((ShInfo.szTypeName)); SubItems.Add(FileTimeToDateTimeStr(ftLastWriteTime)); SubItems.Add(attributes); SubItems.Add(Edit1.Text + cFileName); if (FILE_ATTRIBUTE_DIRECTORY and dwFileAttributes) > 0 then
SubItems.Add('dir')
else
SubItems.Add('file');
end;
Result := True;
end;
until (FindNext(SearchRec) <> 0);
finally
FindClose(SearchRec);
end;
ListView1.Items.EndUpdate;
end;
Неплохая процедурка получилась и надо бы подробно её описать. Я буду делать это по кусочкам, чтобы было легче воспринимать:
function TForm1.AddFile(FileMask: string; FFileAttr:DWORD): Boolean;
var … …
function AttrStr(Attr: integer): string;
begin
Result := '';
if (FILE_ATTRIBUTE_DIRECTORY and Attr) > 0 then Result := Result + '';
if (FILE_ATTRIBUTE_ARCHIVE and Attr) > 0 then Result := Result + 'A'; if (FILE_ATTRIBUTE_READONLY and Attr) > 0 then Result := Result + 'R'; if (FILE_ATTRIBUTE_HIDDEN and Attr) > 0 then Result := Result + 'H'; if (FILE_ATTRIBUTE_SYSTEM and Attr) > 0 then Result := Result + 'S';
end;
После имени процедуры идёт объявление локальных переменных. Это всё понятно и мы не раз уже такое делали. Но после объявления переменных, вместо начала процедуры (begin) у меня стоит объявление другой локальной процедуры -function AttrStr(Attr: integer): string;. Да, и такое в Delphi тоже возможно. Конечно же эту процедуру можно написать как полноценную, но я решил показать тебе, что такое локальная процедура.
Если одна процедура/функция (внутренняя) объявлена внутри другой (внешней), то внутренняя процедура может быть вызвана только из внешней. Весь остальной код программы не будет знать о существовании где-то внутренней процедуры.
Лично я такие вещи стараюсь не использовать, потому что пока не встречался с ситуацией, когда внутренняя процедура необходима. Я всегда прекрасно обхожусь и без неё. Но всё же рассказать тебе о ней необходимо, потому что ты можешь встретить такую конструкцию в других программах.
После объявления и описания внутренней процедуры идёт начало (begin) внешней процедуры. Вот тут уже начинается самое интересное. В самом начале я вызываю два метода компонента ListView1:
ListView1.Items.BeginUpdate; ListView1.Items.Clear;
Первый метод BeginUpdate говорит о том, что начинается обновление элементов списка. После этого вызова никакие изменения вносимые в элементы не будут отражаться на экране, пока не будет вызван EndUpdate.
Когда ты хочешь произвести незначительное изменение, то не надо вызывать эти методы, но когда ты чувствуешь, что здесь элементы списка будут изменяться очень сильно, то лучше все изменения заключить между вызовами BeginUpdate и EndUpdate. Это связано с тем, что когда ты вносишь хоть какое-то изменение, оно сразу отображается на экране. Логично? Я тоже так думаю. А что если тебе нужно удалить все элементы и потом в цикле добавить в список 1000 новых элементов. В этом случае после удаления и каждого добавления нового элемента будет происходить прорисовка компонента. Вот тут и возникает вопрос: «Зачем после каждого добавления рисовать?». В этом случае намного эффективнее будет добавить все элементы, а только потом их прорисовать все сразу. Вот именно для этого и существуют своеобразные скобки BeginUpdate и EndUpdate:
ListView1.Items.BeginUpdate; // Запрещаем прорисовку
Делаем необходимые изменения
Отбрасывание имён с точкой и двумя точками
if (SearchRec.Name = '.') or (SearchRec.Name = '..') or (SearchRec.Name = '') then continue;
Далее идёт вызов функции SlashSep:
FileName := SlashSep(Edit1.Text, SearchRec.Name);
Эта функция и FileTimeToDateTimeStr написаны мной и объявлены в разделе varпосле объявления объекта:
Var
Form1: TForm1;
function SlashSep(Path, FName: string): string;
function FileTimeToDateTimeStr(FileTime: TFileTime): string;
Function SlashSep(Path, FName: string): string; begin
If Path[Length(Path)] <> '' then
Procedure TForm1.Button1Click(Sender: TObject); var
Var
R:TRect; begin if ToolBar1.HostDockSite<>ControlBar1 then
begin
GetWindowRect(ToolBar1.Handle, R);
Здесь надо сохранить в реестре R.Left и R.Top.
А также признак, что ToolBar1 не лежит на ControlBar1
End else begin
Здесь надо сохранить в реестре ToolBar1.Left и ToolBar1.Top. А также признак, что ToolBar1 лежит на ControlBar1
end; end;
На запуск программы ты должен написать примерно следующее:
Procedure TForm1.FormShow(Sender: TObject); begin
Прочитать положение ToolBar1. ControlBar1 то
Begin
ToolBar1.Left:=Сохранённая левая позиция
ToolBar1.Topt:=Сохранённая верхняя позиция
End;
Иначе
begin ToolBar1.ManualDock(nil,nil,alNone); ToolBar1.ManualFloat(Bounds(Сохранённая левая позиция,
Сохранённая правая позиция, ToolBar1.UndockWidth, ToolBar1.UndockHeight)); End; end;
Как видишь, подводные булыжники есть. Но всё же ничего сильно сложного нет.
Теперь мы сделаем менюшку в стиле M$. Для этого нужно поставить ещё один ToolBar и установим его свойство ShowCaption в true. Создадим на нём две кнопки и назовём их File и Edit . Теперь установим компонент MainMenu и сделаем его таким как на рисунке 11.25.2. Меню Not visible сделаем невидимым (Visible=false), в этом случае всё меню будет подключено к форме но будет не видно. Для чего я это делаю, ведь можно было использовать PopupMenu? А потому что при использовании PopupMenu приходится мучится с клавишами быстрого вызова, а в моём способе они подключаются автоматически вместе с главным меню.
Чтобы создать подменю для меню File, нужно щёлкнуть по нём правой кнопкой и выбрать Create Submenu или нажать CTRL+Стрелка в право
Теперь кнопке File в свойстве MenuItem ставим File1 (имя пункта меню), а кнопке Edit ставим Edit1. И на последок обеим кнопкам нужно установить свойство Grouped в true.
Напоследок у каждой кнопки панели инструментов надо установить в свойстве
Grouped – true.
Но это не единственный способ создания меню (это тот, что я чаще использую). Можно ещё просто создать полноценное главное меню. Потом просто убрать его из свойства главной формы Menu, а указать у созданной тобой пустой панели (без всяких кнопок) в таком же свойстве Menu.
На компакт диске, в директорииПримерыГлава 11Dockты можешь увидеть пример этой программы.
– Конец работы –
Используемые теги: Дерево, элементов, TTreeView0.065
Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: Дерево элементов TTreeView
Если этот материал оказался полезным для Вас, Вы можете сохранить его на свою страничку в социальных сетях:
Твитнуть |
Новости и инфо для студентов