Не так уж и часто, но бывает надо в программе получить список файлов или
поддиректорий в каталоге. Для тех, кто использует 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 Кб (без сжатия и
замены модулей).
|