программирование :: delphi

От Delphi 4 к Delphi 5 часть 35



От Delphi 4 к Delphi 5 Файлы
Рассмотрим пример создания текстового файла.
1. Запустите Delphi.
2. Сохраните файл модуля под именем ReviewOfFiles_.pas, а файл проекта — под именем ReviewOfFiles.dpr.
3. Поместите на форму компонент OpenDialog со страницы Dialogs. Используя свойство Filter, введите значения, показанные ниже по тексту. Это свойство определяет маски ввода, доступные пользователю для определения того, какие файлы будут появляться в окне списка диалогового окна. Маска может состоять из одного или нескольких файловых фильтров, каждый из которых состоит из двух частей. Вертикальная линия разграничивает их. В первой части записывается осмысленный текст, который указывает тип файла. Вторая часть представляет собой шаблон универсального сопоставления файла (file wildcard). Можно соединить несколько файловых шаблонов вместе, используя символ точки с запятой как разделитель. Значение свойства Filter является строкой, которая может содержать 255 символов. Итак, введите для нашего случая следующие значения: для открытия паскалевских файлов в первой части введите (*.pas,*.dpr), во второй части введите *.pas,*.dpr. Для текстовых файлов в первую часть введите (*.txt), во вторую — *.txt. Для того чтобы открывать все файлы, в первую часть запишите (*.*), во вторую часть — *.*.
4. Поместите на форму компонент ListBox со страницы Standard. Установите свойство Align в значение AlClient, BorderStyle — в значение bsNone.
5. Активизируйте форму и, используя инспектор объекта, найдите свойство ActiveControl. Раскройте его, в предложенном списке выберите ListBox1.
6. Поместите на форму компонент MainMenu со страницы Standard. Произведите двойной щелчок по нему — откроется редактор меню. Определите первый элемент в виде заголовка, для этого введите в свойство Caption имя &File, нажмите клавишу Enter. Введите команды Open и Exit. Назначьте горячие клавиши для команды Open (Ctrl + A), для команды Exit (Ctrl + B).
7. Сделайте двойной щелчок по команде &Open и запишите следующий программный код:
1. procedure TForm1.Open1Click (Sender: TObject);
2. var
3. MyFile:System.Text;
4. MyText:String;
5. begin
6. if OpenDialog1.Execute then begin
7. ListBox1.Clear;
8. Caption :='Средство просмотра файлов:' + OpenDialog1.FileName;
9. System.Assign(MyFile, OpenDialog1.FileName);
10. Reset (MyFile);
11. while not Eof(MyFile) do begin
12. Readln(MyFile,MyText);
13. ListBox1.Items.Add(MyText);
14. end;
15. System.Close(MyFile);
16. end;
17. end;
18. procedure TForm1.Exit1Click (Sender: TObject);
19. begin
20. Close;
21. end;
22. end.
Проведем анализ программного кода.
В программном коде приведен текст обработчика события OnClick, который вызывается по команде Open в меню File. Метод обработки этого события заключает в себе основное содержимое программы просмотра файлов.
В строке 6 выполняется метод OpenDialog1.Execute. Работа данного компонента позволяет выбирать файл для просмотра, после чего имя выбранного файла передается через свойство FileName компонента OpenDialog1.
После выполнения данного метода может произойти два события: или вы щелкнете по кнопке OK, или по кнопке Cancel диалогового окна открытия файла. В этом случае оператор if проверяет, какое событие произошло. Если вы нажали кнопку Cancel, то метод OpenDialog1.Execute вернет значение False и программа ничего не будет делать, управление будет передано на строку 17 с командой end — она завершает работу обработчика события OnClick. Если вы произвели щелчок по кнопке OK, будут выполняться операторы внутри блока begin — end в строках с 6 по 17.
Оператор строки 7 очищает содержимое окна списка ListBox1. Оператор строки 8 добавляет надпись в заголовок формы с именем выбранного файла и пути к нему. Имя файла берется из свойства FileName компонента OpenDialog1 и добавляется к надписи 'Средство просмотра файлов:'.
В строках с 9 по 15 содержатся операторы, определяющие стандартный алгоритм чтения текстового файла. Команда Assign строка 9 и Reset строка 10 открывают внешний файл, заданный свойством FileName компонента OpenDialog1, связывая его с файловой переменной MyFile. Переменная MyFile определена в строке 3, где вместо обычного описания
MyFile:Text;
добавлено слово System, так как форма уже имеет свойство с названием Text. Из-за того, что обработчик события OnClick является методом формы, возникает конфликт между именем этого свойства и объявленным ранее именем типа Text. Для разрешения этого конфликта и введен оператор System.Text. Конечно, Вы этого можете не знать, но транслятор выдаст сообщение об ошибке, поэтому необходимо не забывать всегда использовать квалификатор System перед указанием типа Text при описании текстового файла. Это же правило применимо к оператору Close в методе OnClick для команды меню Exit, где под Close подразумевается соответствующий метод формы. Здесь же Close относится к файлу, а не к форме.
Файловая переменная, объявленная в строке 3, существует только в данной процедуре. Файл открывается, обрабатывается и закрывается внутри метода. После работы с ним его необходимо закрывать.
Операторы в строках с 11 по 14 содержат цикл while, который осуществляет чтение содержимого выбранного файла. В начале каждой итерации проверяется условие цикла — достижение конца файла. Если определен конец файла, то работа цикла прекращается. В противном случае очередная строка файла считывается в переменную MyText.
Оператор в строке 13 производит динамическое добавление содержимого к окну списка. Метод Add ожидает строку в качестве параметра, и MyText каждый раз передает ему новую строку текста, прочитанную из файла.
Теперь рассмотрим процесс записи текстовых файлов на диск. Этот процесс осуществляется похожим образом. Прежде, чем записывать что-либо в текстовый файл, его необходимо открыть. Для этого следует записать процедуру Assign и за ней процедуру Rewrite:
Assign(MyFile,'FileName.txt);
Rewrite(MyFile);
После открытия файла в него можно писать строку за строкой, используя стандартную процедуру Writeln. Продолжим работу над нашим приложением и проделаем следующие операции.
1. Добавьте на нашу форму компонент SaveDialog со страницы Standard. Найдите свойство Filter и введите те же значения, что и в компонент OpenDialog1. Чтобы сократить трудоемкую операцию, необходимо вначале выделить компонент OpenDialog1, нажать клавишу Shift, далее щелкнуть по компоненту SaveDialog1, щелкнуть по кнопке Filter и нажать клавишу Enter. Теперь компонент SaveDialog1 имеет такие же свойства, как и компонент OpenDialog1.
2. Добавьте команду Save As… в меню. Назначьте горячие клавиши для этой команды (Ctrl + C). Дважды щелкните по сформированной команде и в обработчике события запишите следующий программный код:
1. procedure TForm1.SaveAs1 Click(Sender: TObject);
2. var
3. MyLine: Integer;
4. MyFile: System.Text;
5. MyTextLine: String;
6. begin
7. if SaveDialog1.Execute then begin
8. System.Assign(MyFile,SaveDialog1.Filename);
9. Rewrite(MyFile);
10. for MyLine := 0 to ListBox1.Items.Count-1 do
11. begin
12. MyTextLine:=ListBox1.Items [MyLine];
13. Writeln(MyFile,MyTextLine);
14. end;
15. System.Close(MyFile);
16. end;
17. end;
18.
Проведем анализ программного кода. Оператор строки 7 открывает стандартное диалоговое окно Windows. В случае если результат выражения равен True, т.е. произошел щелчок по кнопке ОК, то выполнится команда внутри цикла.
Операторы в строках 8 и 9 открывают файл для записи. Если указанного файла не существует, то оператор Rewrite создает его. После открытия файла цикл for в строках с 10 по 14 записывает в него строки текста. Необходимо обратить внимание, что переменная цикла MyLine меняется от значения 0 до величины на единицу меньшей, чем число строк в текстовом окне. Использование нулевого значения счетчика необходимо, так как нумерация строк в текстовом окне начинается с нуля.
В операторе 12 у компонента ListBox1 есть свойство Items, которое является массивом строк. Ранее вы добавили эти строки, используя метод Add компонента ListBox1 при загрузке файла. Вы можете получить доступ к отдельному элементу этого массива, используя выражение для индекса массива, заключенное в квадратные скобки.
В строке 12 переменной MyTextLine присваивается значение элемента массива Items c номером [MyLine].
Цикл в строке 10 совершает ровно столько итераций, сколько требуется для записи всех строк текстового окна файла. Выражение ListBox1.Items.Count дает действительное количество строк в текстовом окне и предоставляет конечное значение для счетчика цикла, что гарантирует окончание работы цикла после выполнения ListBox1.Items.Count — 1 итераций.
После окончания работы цикла вызывается подпрограмма System.Close, закрывающая файл и гарантирующая физическую запись данных на диск.
Итак, давайте рассмотрим это подробнее.
Файл представляет собой набор данных, обычно расположенный на диске.
Понятие File — это тип данных языка Object Pascal, переменные которого могут быть связаны с внешним файлом. После установления связи и объявления файла открытым содержащиеся в нем данные обрабатываются в вашем приложении с помощью ссылок на файловую переменную.
Текстовый файл представляет собой особый вид файла, содержащий текстовую информацию, т.е. последовательности символов, разделенных на строки. Text — это тип данных, соответствующий текстовому файлу на диске. Для получения возможности производить чтение и записи текстовых файлов в приложениях необходимо связать их с переменными типа Text.
Любой текст программы на языке Object Pascal представляет собой текстовый файл.
Итак, чтобы получить доступ к текстовому файлу, необходимо проделать следующие действия.
Для доступа к файлам используется специальная файловая переменная. Она связывается с указанным файлом процедурой AssignFile.
procedure AssignFile(var F; FileName: string);
где F — файловая переменная любого типа, S — строка, содержащая имя файла.
Например
AssignFile(F1, 'MyFile.txt');
AssignFile(F2,OpenDialog1.FileName);
Происходит связь файловых переменных F1 с файлом MyFile.txt, F2 — с файлом, имя которого записано в свойстве FileName компонента OpenDialog1.
При вызове данной процедуры ей передается в качестве параметра переменная типа Text и имя нужного файла. Например, с внешним файлом 'MyFile.txt' связывается файловая переменная с именем F1. Вызов процедуры — это просто включение ее имени в блок выполняемых операторов. Передача параметров — это перечисление значений параметров внутри скобок, следующих за именем процедуры.
Следующий шаг зависит от того, что вы хотите делать с файлом.
Можно производить чтение из файла, записывать в файл, добавлять новую информацию к уже имеющейся. Вы должны определиться с этим к моменту открытия файла. После того, как файл будет открыт, можно будет выполнять одну из этих операций, и вы уже не сможете сменить вид операции во время выполнения программы. Поэтому вам необходимо открыть текстовый файл, затем после чтения закрыть файл, потом вновь его открыть для записи и добавления информации.
При открытии текстового файла для чтения вызывается процедура Reset.
procedure Reset(var F [: File; RecSize: Word ] );
Например,
Reset(F1);
открывает переменную F1 для чтения.
Существует понятие позиции внутри файла, с которой начинается чтение. По этой команде файловая переменная устанавливается на начало файла.
При открытии текстового файла для записи вы вызываете процедуру Rewrite.
procedure Rewrite(var F: File [; Recsize: Word ] );
например
Rewrite(F1);
готовит файл к операции записи.
Вызов этой команды может иметь разрушительный эффект: если файл, на который ссылается файловая переменная, существует, то его содержимое уничтожается. Полученный в результате этого файл имеет нулевую длину и готов к записи. Данная команда не предупреждает вас о том, что существует файл с таким именем.
При открытии текстового файла для добавления к нему записей вам необходимо вызвать стандартную процедуру
procedure Append(var F: Text); передавая ей файловую переменную, например
Append(F1);
готовит файл F1 к последующей записи таким образом, что новый текст будет добавляться после уже имеющихся в файле строк.
Добавим в наше приложения команду "Добавить запись". Запишите следующий программный код:
procedure TForm1.N2Click (Sender: TObject);
var
MyFile:System.Text;
begin
if OpenDialog1.Execute then
begin {открыть текстовый файл}
AssignFile(MyFile, OpenDialog1.FileName);
Append(MyFile);
Writeln(MyFile, 'Я добавляю некоторую информацию в конец файла');
{Вставьте код, который требует сброс перед закрытием файла}
Flush(MyFile); {Гарантирует, что текст был фактически дописан к файлу}
CloseFile(MyFile);
end;
end;
Приведенный код позволяет добавлять запись к концу файла. Вначале откройте файл для чтения, затем произведите добавление записи, и для просмотра введенной записи необходимо вновь открыть файл для чтения.
Процедура Append не имеет такого разрушительного действия, как Rewrite.
После того, как вы успешно открыли текстовый файл и поработали с ним, вам надо добавить оператор Close, для того чтобы закрыть его
procedure Close(var F);.
Например
Close (F1);
закрывает файл, связанный с переменной F1, который вы перед этим открыли с помощью операторов Assign — Reset, Assign — Rewrite, Assign — Append.
Правилом является выполнение операторов Close сразу после окончания работы с файлом. Необходимо открывать и закрывать внутри одного и того же блока begin — end, чтобы промежуток времени существования открытого файла был ясно виден в тексте программы на одной странице листинга.
Работая с файлами, осуществляя чтение и запись в данных, возможны ошибки. Чтобы их избежать, необходимо принять меры, так как ошибки могут привести к прерыванию программы. Предотвратить их можно двумя способами: использование исключения InOutError или применение опции {$I-}, которая отключает генерацию исключений ошибок ввода-вывода. После обработки операции ввода-вывода контроль ошибок можно снова включить опцией {$I+}.
Программный код с использованием данной опции показан ниже:
function FileExists(FileName: string): Boolean;
{Булева функция, которая возвращает True, если файл существует; иначе, возвращает False}
var
F: file;
begin
{$I-}
AssignFile(F, FileName);
FileMode := 0;{Доступ к файлу только для чтения}
Reset(F);
CloseFile(F);
{$I+}
FileExists := (IOResult = 0) and (FileName <> '');
end; {файл существует}
begin
if FileExists(ParamStr(1)) then {Получите имя файла от командной строки}
Canvas.TextOut(10, 10, 'Файл существует')
else
Canvas.TextOut(10, 10, 'Файл не найден');
end;
При операциях ввода-вывода проверка окончания файла производится функцией Eof(F:File), которая возвращает True при достижении конца файла.

Компонент TApplicationEvents
Приложения Windows содержат различные объекты, которые взаимодействуют друг с другом посредством сообщений, посылаемых в ответ на события. Кроме того, Windows и приложения взаимодействуют между собой и с внешними устройствами посредством сообщений.
Источниками сообщений могут быть:
события, которые происходят во время работы пользователя: ввод символов с клавиатуры, перемещение мыши по коврику, нажатие кнопок мыши;
приложения Windows производят вызов функций Windows, которые посылают сообщения от Windows к приложению;
внутренние сообщения приложений Windows, которые предназначены для определенных программных компонентов;
сама среда Windows посылает сообщения приложениям Windows;
два приложения Windows могут посылать друг другу сообщения динамического обмена данными (Dynamic Data Exchange, или DDE) для организации обмена данными.
Все классы в Delphi имеют встроенный механизм для обработки сообщений, называемый обработчиком сообщений, включающий методы или драйверы обработки сообщения. Основная идея относительно драйверов сообщения состоит в том, что класс получает сообщения некоторого вида и посылает их, вызывая один из набора указанных методов в зависимости от полученного сообщения. Если никакой определенный метод не существует для специфического сообщения, имеется заданный по умолчанию драйвер.
Delphi регистрирует метод по имени MainWndProc как оконную процедуру для каждого типа компонента в прикладной программе.
MainWndProc содержит блок обработки особых случаев, получая сообщение от Windows, он пропускает его к виртуальному методу по имени WndProc, который обрабатывает любые исключения, вызывая HandleException метод прикладного класса.
Итак, MainWndProc — не виртуальный метод, который не содержит никакую обработку для сообщений. Настройки имеют место в WndProc, так как каждый тип сообщения может потребовать свой метод обработки сообщения.
WndProc методы проверяют любые условия, которые затрагивают обработку сообщения. WndProc производит отправку значения, которое определяет, какой метод вызвать, чтобы обработать сообщение.
Отправка использует поле Msg структуры сообщения, чтобы определить метод обработки сообщения. Если компонент не определяет драйвер для этого сообщения, отправка вызывает DefaultHandler (обработка по умолчанию).
Visual Component Library формирует посылаемое в систему сообщение, которое транслирует все сообщения Windows (включая определяемые пользователем сообщения) и направляет к специфическому классу запросы для метода. Вы никогда не должны изменять этот механизм отправки сообщения. Все, что вы должны будете делать, — это создавать методы, обрабатывающие сообщение.

Объявление нового метода, обрабатывающего сообщения
Имеются два обстоятельства, которые требуют, чтобы вы объявили новые методы, обрабатывающие сообщение:
ваш компонент должен обработать сообщение Windows, которое не обработано стандартными компонентами.
вы определили ваше собственное сообщение для использования вашими компонентами.
Чтобы объявлять метод, обрабатывающий сообщение, проделайте следующее:
1. Объявите метод в защищенной части объявления класса компонента.
2. Сделайте метод процедурой.
3. Объявите метод после сообщения, которое он обрабатывает, но без символов подчеркивания.
4. Произведите передачу единственного параметра сообщения, типа записи сообщения.
5. В пределах выполнения метода сообщения запишите код для обработки сообщения, определенного к компоненту.
6. Вызовите унаследованный драйвер сообщения.
const
CM_CHANGECOLOR = WM_APP + 400;
type
TMyComponent = class(TControl)
...
protected
procedure CMChangeColor(var Message: TMessage); message CM_CHANGECOLOR;
end;
procedure TMyComponent.CM ChangeColor(var Message: TMessage);
begin
Color := Message.lParam;
inherited;
end;

Диспетчеризация сообщений.
Когда приложение создает окно, происходит регистрация оконной процедуры в ядре Windows. Оконная процедура — это подпрограмма, которая обрабатывает сообщения для окна. Традиционно, она содержит оператор выбора, имеющего входы для каждого сообщения, которое окно должно обработать. Имейте в виду, что "окно" в этом смысле означает, например, что-то имеющееся на экране: диалоговое окно, элемент управления и так далее. Каждый раз, когда вы создаете новый тип окна, вы должны создать законченную оконную процедуру.
Delphi упрощает диспетчеризацию сообщения несколькими способами:
1. каждый компонент наследует законченную систему формирования сообщения;
2. система отправки сообщения имеет заданную по умолчанию обработку. Вы определяете драйверы только для сообщений, на которые вы должны ответить специально;
3. вы можете изменять маленькие части обработки сообщения и полагаться на унаследованные методы для обработки большей части сообщений.
Вы можете безопасно посылать любое сообщение любому компоненту в любое время. Если компонент не определяет драйвер для сообщения, обработка значения по умолчанию позаботится об этом, обычно, игнорируя сообщение.
У вас есть возможность для обработки сообщений в приложении — это событие Application.OnMessage, оно видит все сообщения от всех окон приложения.
Каждое приложение имеет автоматически создаваемый объект Application. Данный компонент служит приемником многочисленных сообщений.
В Delphi 5 введен компонент ApplicationEvents. Он предназначен для приема многочисленных сообщений, которые Windows посылает работающей программе.
Рассмотрим пример с использованием этого компонента.
1. Запустите Delphi.
2. Сохраните файл модуля под именем Mess_.pas, а файл проекта под именем Mess.dpr.
3. Поместите на форму компонент ApplicationEvents и компонент Edit1.
4. Для события OnMessage компонента ApplicationEvents введите следующий метод обработки:
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
begin
Handled := Edit1.Focused and (Msg.Message=wm_Char)
and (Msg.wParam> =48) and (Msg.wParam<=57)
end;
end.
После запуска программы на компиляцию можете попробовать ввести в компонент Edit1 цифры. Вы увидите, что это сделать невозможно, таким способом можно ограничивать ввод любых символов в компонент.
type TMessageEvent = procedure (var Msg: TMsg; var Handled: Boolean) of object;
property OnMessage: TMessageEvent;
Это событие происходит, когда приложение получает сообщение Windows.
Используйте OnMessage, чтобы захватывать все сообщения Windows, зарегистрированные ко всем окнам в приложении.
Драйвер OnMessage позволяет прикладной программе отвечать не только на объявленные в TApplication сообщения. Если приложение не имеет определенного драйвера для входящего сообщения, сообщение посылается окну, для которого оно было предназначено, и Windows обрабатывает его.
Параметр Msg идентифицирует сообщение Windows, параметр Handled указывает, отвечал ли драйвер для данного случая на сообщение.
Форма может иметь большое количество компонентов ApplicationEvents. В этом случае одно и то же сообщение будет последовательно поступать в каждый из них, до тех пор, пока оно не будет обработано или пока не поступит всем.
При этом порядок поступления сообщения является обратным порядку размещения компонентов на форме. Изменение этого порядка возможно с помощью метода Activate.
Ниже приведены коды клавиш, которыми можно пользоваться при проверке параметра Key в обработчиках событий OnKeyDown и OnKeyUp. Символы кириллицы соответствуют тем клавишам с латинскими символами, на которых они размещены.
Соответствие приведено в виде "клавиша — десятичное число":
F1 — 112; F2 — 113; F3 — 114;F4 — 115; F5 — 116; F6 — 117; F7 — 118; F8 — 119; F9 — 120; F10 — 121; пробел — 32; BackSpace — 8; Tab — 9; Enter —13; Shift — 16; Ctrl — 17; Alt — 18; CapsLock — 20; Esc — 27; Insert — 45; PageUp — 33; PageDown — 34; End — 35; Home — 36; 37 — Left; 38 — Up; 39 — Right; 40 — Down; Delete — 46; PrintScreen — 44; ScrollLock — 145; Pause — 19; NumLock — 144; 0,) — 48; 1 ! — 49; 2 @ — 50; 3 # — 51; 4 $ — 52; 5 % — 53; 6 ^ — 54; 7 & — 55; 8 * — 56; 9 ( — 57; ` ~ — 192; — - 189; = + — 187; [ { — 219; ] } — 221; ; : — 186; ' " — 222; \ | — 220; , < — 188; .> — 190; / ? — 191; a,A — 65; b,B — 66; c,C — 67; d,D — 68; e,E — 69; f,F — 70; g,G — 71; h,H — 72; i,I — 73; j,J — 74; k,K — 75; l,L — 76; m,M — 77; n,N — 78; o,O — 79; p,P — 80; q,Q — 81; r,R — 82; s,S — 83; t,T — 84; u,U — 85; v,V — 86; w,W — 87; x,X — 88; y,Y — 89; z,Z — 90.
На правой клавиатуре при выключенной NumLock
0 — 96; 1 — 97; 2 — 98; 3 — 99; 4 — 100; 5 — 101; 6 — 102; 7 — 103; 8 — 104; 9 — 105; * — 106; + — 107; — - 109; . — 110; / — 111.

Владимир Скуратов

(c) компьютерная газета





© компьютерная газета