скрыть

скрыть

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

Урок 12 - Cоздание списка файлов



Ведущий раздела KOL и MCK: Анатолий aka XVeL
Автор: Борис Моренко
WEB-сайт: http://kolmck.net/

Не так уж и часто, но бывает надо в программе получить список файлов или поддиректорий в каталоге. Для тех, кто использует KOL и MCK открываются аж 3 способа решения этой проблемы. Правда нормальный, по моему мнению, все-таки только один :) Рассмотрим все.

1-й способ. " Традиционный ."

Традиционно пользуются 3-мя API функциями: FindFirstFile (ищет первый файл из списка файлов), FindNextFile (ищет следующий файл) , FindClose (прекращение поиска). Обычно первые 2-е функции заменются их VCL-суррогатами FindFirst, FindNext. Для нас, они не совсем приемлемы, так как для того чтобы воспользоваться этими функциями, надо подключить библиотеку Sysutils. А это как известно добавляет лишний жирок в наши атлетически сложенные программы :-). Пример на чистом API с примесью KOL.

program Primer12;

uses
  Windows,
  Messages,
  Kol;

  {$R *.RES}
var
  Form: Pcontrol;
  // ----- элементы интерфейса ----- 
  List: PControl;
  // -----------------------------
  FindHandle : THandle;
  FindData : TWin32FindData;
  b: boolean;
  s: string;
begin
  Applet := NewApplet( 'Список файлов' );
  form:=NewForm(Applet, 'Список файлов' ).SetSize(300, 400);
  form.CenterOnParent;
  List := NewListBox(form, []).SetAlign(caClient);

  // устанавливаем атрибуты файла 
  FindData.dwFileAttributes := FILE_ATTRIBUTE_NORMAL;
  // ищем первый файл в каталоге C:\
  FindHandle := FindFirstFile('C:\*.*', FindData);
  // если все Ok, тогда продолжаем 
  if FindHandle <> INVALID_HANDLE_VALUE then
  begin
     b := true;
     while b do
     begin
       s := FindData.cFileName;
       // всякие точки и двоеточия нам не нужны 
       if (s<>'..') and (s<>'.') then
         List.Add(s);
       b := FindNextFile(FindHandle, FindData);
     end;
  end;
  FindClose(FindHandle);

  run(Applet);
end.

Пояснения на счет атрибутов для искомых файлов:

  • FILE_ATTRIBUTE_ARCHIVE - архивный файл.
  • FILE_ATTRIBUTE_COMPRESSED - сжатый файл или папка.
  • FILE_ATTRIBUTE_HIDDEN - скрытый файл.
  • FILE_ATTRIBUTE_NORMAL - обычный файл.
  • FILE_ATTRIBUTE_OFFLINE - данные файла недоступны. Указывает, что данные файлы были физически перемещены.
  • FILE_ATTRIBUTE_READONLY - файл только для чтения.
  • FILE_ATTRIBUTE_SYSTEM - системный файл.
  • FILE_ATTRIBUTE_TEMPORARY - временный файл.
  • FILE_ATTRIBUTE_DIRECTORY - директория

2-й способ. "В лоб."

Несмотря на простоту представленного кода эту операцию можно сделать еще проще т.к. ListBox сам может показать файлы в определенной директории. Для этого надо обратится к свойству AddDirList. Пример еще меньше.

program Primer12_2; 
 
uses 
  Windows, 
  Messages, 
  Kol; 
 
{$R *.RES} 
var 
  Form: Pcontrol; 
  // ----- элементы интерфейса ----- 
  List: PControl; 
  // ------------------------------ 
begin 
  Applet := NewApplet('Список файлов'); 
  form := NewForm(Applet, 'Список файлов').SetSize(300, 400); 
  form.CenterOnParent; 
  List := NewListbox(form, []).SetAlign(caClient); 
  List.AddDirList('C:\*.*', FILE_ATTRIBUTE_NORMAL); 
  run(Applet); 
end. 

Это конечно интересный способ получать список файлов, но не функциональный :) Не создавать ведь на окне каждый раз ListBox или СomboBox (он тоже имеет это же свойство), чтобы получить список файлов. Да и почему-то выводимый список файлов в виде " коротких имен " (т.е. как будто в DOS). Скорее всего Владимир Кладов добавил это свойство как интересную фичу и не более.

3-й способ. " Как положено "

Ну и самое интересное :) В KOL есть объект предназначенный для создания списка фалов. Это PDirList. Вот его конструктор:

function NewDirList( const DirPath, Filter: String; Attr: DWORD ): PDirList;

DirPath - сканируемая директория
Filter - фильтр для файлов или каталогов
Attr - атрибуты

Список методов и свойств для работы с этим обьектом:

Метод
Описание
procedure Clear; Очищает текущий список с файлами.
procedure ScanDirectory( const DirPath, Filter: String; Attr: DWord ); Сканирует директорию DirPath. Все передаваемые значения идентичны конструктору.
procedure Sort( Rules: array of TSortDirRules );

Сортировка списка файлов. Rules (условие сортировки) может быть следующим :

  • sdrNone - обойдемся без сортировки
  • sdrFoldersFirst - сначала идет каталог, а только затем файл.
  • sdrCaseSensitive
  • sdrByName - по имени
  • sdrByExt - по расширению
  • sdrBySize - по размеру
  • sdrBySizeDescending
  • drByDateCreate - по дате создания
  • sdrByDateChanged - по дате изменения
  • sdrByDateAccessed -по дате доступа
Свойство
Описание
property Items[ Idx: Integer ]: PWin32FindData Получить доступ к структуре PWin32FindData для файла идущего под номером Idx. Подробности об PWin32FindData смотрите в Win32.hlp и в примере " стандартного " создания списка фалов
property IsDirectory[ Idx: Integer ]: Boolean; Возвращает true если запись под номером Idx в списке не является файлом.
property Count: Integer;

Возвращает количество пунктов в списке

property Names[ Idx: Integer ]: string; Возвращает полное имя файла (или каталога) находящимся в списке под номером Idx.
property Path: string; Путь текущей просканированной директории.

Пример. Наверху в окне находится список дисков. Ниже находится список файлов и подкаталогов, находящихся в центральных каталогах этих дисков.

program Primer12_3;

uses
  windows,
  messages,
  kol;

{$R *.RES}
var
  form: Pcontrol;
 // ----- элементы интерфейса -----
  ListFile, ListDrv: PControl;
 // ------------------------------
  FileL: pDirList;

  i, j: integer;

  DriveBits: set of 0..25;
  DriveNum: integer;
  DriveChar: char;

///////////////////////////////////////////////////////////////////////////

procedure SelDrv(Dummy: Pointer; Sender: PControl);
var
  s: string;
begin
  s := ListDrv.Text;

  if FileL = nil then
    FileL := NewDirList(s, '*.*', FILE_ATTRIBUTE_NORMAL)
  else
  begin
    FileL.Clear;
    FileL.ScanDirectory(s, '*.*', FILE_ATTRIBUTE_NORMAL);
  end;
  FileL.Sort([sdrByName]);

  ListFile.Clear;
  if FileL.Count > 0 then
    for i := 0 to FileL.Count - 1 do
      ListFile.add(FileL.Names[i]);
end;
///////////////////////////////////////////////////////////////////////////
begin
  Applet := NewApplet('Список файлов');
  form := NewForm(Applet, 'Список файлов').SetSize(250, 300);
  form.CenterOnParent;
  Form.Font.FontName := 'MS Sans Serif';
  Form.Font.FontHeight := 9;

 //----------- "рисуем" интерфейс -----------------------
  ListDrv := NewComboBox(form, []).SetAlign(caTop);
  ListFile := NewListbox(form, []).SetAlign(caClient);
 //------------------------------------------------------

  Integer(DriveBits) := GetLogicalDrives; // получаем номера дисков
  i := 0;
  j := 0;

 // узнаем список дисков
  for DriveNum := 0 to 25 do
    if DriveNum in DriveBits then
    begin
      DriveChar := Char(DriveNum + Ord('a'));
      DriveChar := UpCase(DriveChar);
      ListDrv.Add(DriveChar + ':\');
      if DriveChar = 'C' then j := ListDrv.Count - 1; // узнаем каким в очереди идет диск С:\
    end;

  ListDrv.CurIndex := j;
  ListDrv.OnChange := TOnEvent(MakeMethod(nil, @SelDrv));
  SelDrv(nil, nil); // показываем файлы на текущем диске
  run(Applet);
end.

Размер кода 1,8 Кб. Размер программы 34,5 Кб (без сжатия и замены модулей). На экране увидите Вы примерно следующее:






Copyright © 2004-2016 "Delphi Sources". Delphi World FAQ




Группа ВКонтакте   Ссылка на Twitter   Группа на Facebook