FunctionFindFirst(const Path: string; Attr: Integer;
var F: TSearchRec): Integer;
Находит имя первого файла с заданными атрибутами Attr в папке Path. Результат поиска выводит в переменную F. Если поиск успешен, то функция вернет 0, иначе вернет код ошибки Widows. К FindFirst можно обращаться не только как к функции, но и как к процедуре.
Атрибуты файла приведены в табл. 17.
Таблица 17
Атрибут | Описание файлов |
faReadOnly faHidden faSysFile faVolumeIDfaDirectory faArchivefaAnyFile | Файлы "Только для чтения"Скрытые файлыСистемные файлыФайл ID-значенийПапки (директории)Архивы (файлы)Все файлы |
Тип, характеризующий найденный файл, представляет запись вида :
type
TSearchRec = Record
Time: Integer; {время}
Size: Integer; {размер файла в байтах}
Attr: Integer; {атрибуты файла}
Name: TFileName; {DOS-путь файла}
ExcludeAttr: Integer;
FindHandle: THandle;
FindData: TWin32FindData; {дополнительная информация о файле}
end;
Пример:
Var
SR: TSearchRec;
S: String;
…
FindFirst('c:\Program Files\delphi4\bin\*.*', faAnyFile, SR);
if (SR.Attr = faArchive) then
S:= 'Файл ' + SR.Name + ' имеет размер ' + IntToStr(SR.Size) + ' байт';
В данном примере процедура FindFirst ищет первый файл по маске '*.*' (все файлы) в папке 'c:\Program Files\delphi4\bin'. Атрибут faAnyFile означает, что поиск производится по всем видам файлов, под которыми понимаются папки (директории), '.', '..' – ссылки на текущую и родительскую папку, внутренние папки и собственно файлы. Последние в терминологии файловой атрибутики называются архивами. Далее, если найденный файл есть архив, т е. файл в общепринятой терминологии, то в строку S будет помещено сообщение. Например, если найденный файл имеет имя Ig.ttg и его размер равен 15899, то S= 'Файл Ig.ttg имеет размер 15889 байтов'.
Function FindNext(var F: TSearchRec): Integer;
Находит следующий файл, атрибуты которого указаны в FindFirst.
Procedure FindClose(var F: TSearchRec);
Закрывает действие FindFirst/FindNext.
Function DeleteFile(const FileName: string): Boolean;
Удаляет файл по имени. Если файл не может быть удален или не существует – возвращает False.
Function CreateDir(const Dir: string): Boolean;
Создает новую папку.
FunctionGetCurrentDir: string;
Возвращает текущую папку.
Function GetCurrentDir: string;
Возвращает текущую папку.
Function SetCurrentDir(const Dir: string): Boolean;
Установка новой текущей папки.
Function RemoveDir(const Dir: string): Boolean;
Удаление папки. Перед удалением папка должна быть пустой.
Function ExtractFileDir(const FileName: string): string;
Выделяет из полного имени файла FileName папку, в которой содержится это файл.
Function ExtractFilePath(const FileName: string): string;
Выделяет из полного имени файла FileName путь до файла.
Function ExtractFileExt(const FileName: string): string;
Возвращает расширение файла FileName.
Function ExtractFileName(const FileName: string): string;
Возвращает имя файла FileName (без расширения).
Function DirectoryExists(Dir: string): boolean;
Проверяет существование директории. Пример:
if DirectoryExists('C:\APPS\SALES\LOCAL') then ;
Function FileExists(FileName: string): boolean;
Проверяет существование файла. Примеры:
B:= FileExists('C:\APPS\SALES\LOCAL\Fort.pas'); {полное имя}
B:= FileExists('Fort.pas'); {указано усеченное имя файла, проверка его существования только в текущей директории}
Procedure ForceDirectories(Dir: string);
Создает новую директорию.
Procedure ForceDirectories(C:\APPS\SALES\LOCAL).
П р и м е ч а н и е. К моменту обращения к процедуре директории APPS и SALES должны существовать.
Пример процедуры удаления данных из текущей директории, включая файлы и вложенные папки.
Procedure DelInsideDir(FullDir: tPathStr);
Var
L: Integer;
Sr: TSearchRec;
dr, q: tPathStr;
begin
if ExistDir(FullDir) then {такая директория есть}
begin
GetDir(0,dr); {запомнить текущую директорию}
ChDir(FullDir); {текущей становится удаляемая директория}
L:=FindFirst(Slash(FullDir)+'*.*',faAnyFile,Sr);{поиск первого файла}
try
While (L = 0) do begin {пока файлы находятся}
Case Sr.Attr of
faDirectory:{найденный файл – внутренняя директория}
if (Sr.Name<>'.') and (Sr.Name<>'..') then {это не ссылка, директория}
begin
{удаление внутреннего содержимого директории}
DelInsideDir(Slash(FullDir)+Sr.Name);
q:= Slash(FullDir)+Sr.Name;
ChDir(ExtractFilePath(q));
{удаление самой директории (можно, т. к. она теперь пуста)}
if NotEmpStr(ExtractFileName(q)) then RmDir(ExtractFileName(q));
end;
faArchive: DeleteFile(Sr.Name); {это файл, удаляется}
end; {Конец Case-оператора}
L:= FindNext(Sr); {следующий файл директории}
end; {цикла While}
finally
FindClose(Sr); {закрыть поиск файлов}
end; {try – finally – end}
ChDir(dr); {вернуться в текущую директорию}
end; {if}
end;{процедуры}
Например, если необходимо стереть данные с дискеты, то это можно сделать с помощью оператора: DelInsideDir('A:\');
18. Классы и объекты
В Object Pascal классами называются специальные типы, которые содержат поля, методы и свойства. Предшественником класса является устаревший ныне тип языка Turbo Pascal, называемый объектом. Объект был введен в Turbo Pascal до создания Delphi. С появлением Delphi в новой версии языка Object Pascal объекты, для совместимости со старым программным продуктом, сохранены. Однако ныне использование объектов не актуально.
Класс представляет собой указатель. Однако в отличие от традиционных указателей это указатель особого типа: в нем нельзя использовать символ "^" при обращении к классу.
18.1. Инкаспуляция, наследование и полиморфизм
Класс, объединяя в себе поля, методы и свойства в единое целое, является законченной структурной единицей, предназначенной для решения отдельной задачи. Обычно такой задачей является задача разрешения некоторого круга сопутствующих проблем. Так, класс TRichEdit представляет собой мощный текстовой редактор rtf-файлов (файлов в формате Rich Text Format), который предназначен для организации просмотра и редактирования файла, сохранения и изменения размеров и типов шрифтов, поиска строк символов и многого другого. Такое объединение полей, методов и свойств в единое целое называется инкаспуляцией.
В языке существует множество классов (около 300), которые созданы разработчиками языка Object Pascal – сотрудниками фирмы Inprise International – для программистов, использующих среду Delphi. Такие классы можно назвать фирменными.
Программист, составляя программу, всегда создает свои пользовательские классы. Эти классы создаются либо неявно, когда программист конструирует программу визуальными средствами Delphi, а текст классов при этом составляет сама Delphi, либо явно, когда программист пишет код класса средствами языка Object Pascal.
Новый класс строится на основе другого, более простого, класса. Для этого в заголовке класса указывается его класс-родитель. Синтаксис заголовка нового класса имеет вид
type className = class (ancestorClass)
Здесь className – имя нового класса; ancestorClass – имя класса-родителя. Новый класс автоматически наследует поля, методы и свойства своего родителя и может пополниться своими полями, методами и свойствами. Это свойство классов называется наследованием. Возможность наследования позволяет, следуя методу от простого к сложному, создавать классы какой угодно степени сложности. Простейшим классом является класс TObject, который не содержит полей и свойств, однако имеет некоторое множество методов, обеспечивающих создание, уничтожение и обслуживание этого класса и необходимых для нормального функционирования программы. Именно на основе этого общего для всех классов прародителя строится дерево наследования классов. Например:
type TPersistent = class (TObject),
type TComponent = class (TPersistent),
type TControl = class (TComponent).
Нередко методы, описанные в классе-родителе, оказываются по каким-либо причинам неудовлетворительными для класса-потомка. В этом случае в классе-потомке можно создать метод с тем же именем, что и в классе-родителе. При этом окажется, что в обоих классах будут действовать разные методы с одним и тем же именем. Полиморфизм и есть такое свойство родственных классов, которое состоит в допустимости объявления в них одноименных методов.
18.2. Синтаксис класса
Синтаксис всякого класса имеет вид
type className = class (ancestorClass)
memberList
end;
Здесь className – имя класса; class – ключевое слово; ancestorClass – тип класса-родителя; memberList – список полей, методов и свойств. Ниже приведен текст модуля main, содержащий класс TForm1.
unit main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms;
type
TForm1 = class(TForm) {объявление класса TForm1}
Button1: TButton; {поле}
L1: TLabel; {поле}
L2: TLabel; {поле}
Button2: TButton; {поле}
procedure Button1Click(Sender: TObject); {метод}
procedure FormActivate(Sender: TObject); {метод}
end;
Var i: Integer;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject); {описание метода}
begin
L1.Caption:= DateTimeToStr(Date);
L2.Caption:= TimeToStr(Time);
end;
procedure TForm1.FormActivate(Sender: TObject); {описание метода}
begin
i:=125;
end;
end.
18.3. Поля класса
Полем может быть любой инкаспулированный в класс тип или другой класс, например:
type
TKdnClass = class(TObject)
i, j: integer;
s: String;
TKdn1: TKdn0;
End;
Если потомком является TObject, то в заголовке его можно опустить.
Класс-потомок имеет доступ ко всем полям своих предков, но не может их переопределять, т. к. он станет недоступен. Пример:
type
TPredok = class {объявление класса-предка}
Value: Integer;
end;
TPotomok = class(TPredok) {объявление класса-потомка}
Value: string; {перекрытие наследуемого поля}
end;
var
My1: TPredok; {объявление переменной класса}
My2: TPotomok; {объявление переменной-класса}
begin
My1 := TPotomok.Create; {создает класс типа TPredok !}
My2 := TPotomok.Create; {создает класс типа TPotomok}
My1.Value := 'Hello!'; {ошибка, не тот тип поля TPredok}
My2.Value := 'Hello!'; {правильно, работает поле Value: String}
My2.Value := 8; {ошибка: поле Value: Integer перекрыто}
end;
В этом примере описано два класса: TPredok – предок и TPotomok – потомок. Каждый из классов содержит одноименные поля Value разных типов.
Далее в var-секции объявлены две различные переменные My1 и My2 типа class. На первый взгляд может показаться, что оператор-конструктор объекта My1:= TPotomok.Create создаст объект My1 (выделит под него память) типа TPotomok. Однако это не так, поскольку My1 имеет другой тип. По этой причине конструктор создаст объект родительского типа, т. е. объект типа TPredok. Теперь становится понятен источник ошибок, которые имеют место в нескольких операторах приведенного примера.
18.4. Методы класса
Методом класса является инкаспулированная процедура или функция. Эти подрограммы объявляются так же, как обычные подпрограммы. Метод должен быть объявлен в описании класса в виде отдельного заголовка, а код метода – описан в секции implementation с указанием через символ "." принадлежности метода к своему классу, например: