Понятие исключительной ситуации
Исключительная ситуация – это изменение условий работы приложения, которые могут быть причиной невозможности дальнейшего его выполнения. Любое взаимодействие с операционной системой на предмет получения ресурсов: места на диске, памяти, открытие файла – может завершиться неудачно. Любое вычисление может закончиться делением на нуль или переполнением. Платой за надежную работу программы в таких условиях служит введение многочисленных проверок, способных предотвратить некорректные действия в случае возникновения нештатной ситуации. Обычно для корректного выхода из ситуации нужно отменить целую последовательность действий, предшествующих неудачному действию. Выход из положения нештатной ситуации предложен разработчиками Windows - это структурированная обработка исключительных ситуаций, которая реализована и в Delphi.
Структурированная обработка исключительных ситуаций в Delphi реализована с помощью множества классов. Предком всех таких классов является объектный тип (класс) Exception. Чтобы выделить имена классов, связанных с исключительными ситуациями, первой буквой их имен является буква E. Имена других классов начинаются с буквы T.
В Delphi исключительные ситуации представлены в форме объектов. При возникновении исключительной ситуации в памяти создается объект обработки исключительной ситуации. Для удаления этого объекта должен быть создан обработчик исключительной ситуации. Для работы с такими объектами разработаны специальные конструкции языка, которые позволяют написать дополнительный код обработки возможных исключительных ситуаций.
В Delphi существует множество встроенных классов обработки исключительных ситуаций. Приложение обычно имеет один глобальный обработчик и несколько локальных специализированных процедур-обработчиков, реагирующих на соответствующие конкретные исключения. Для исключения, не имеющего своего локального обработчика, приложением вызывается глобальный обработчик.
ВВЕДЕНИЕ В OBJECT PASCAL
Благодаря языку Object Pascal Delphi стала системой быстрой разработки приложений. Разработчику приложений необходимо потрудиться, чтобы язык Object Pascal стал настоящим инструментом в его руках. Необходимо изучить способы организации данных, чтобы научиться создавать собственные типы данных, научиться объединять группы операторов в эффективные многократно используемые модули, научиться объединять наборы типов данных, процедур и функций, образуя внешние библиотеки, которые совместно используются различными программами.
СТРУКТУРА ПРИЛОЖЕНИЯ
Выше было отмечено, что приложение - это “ловушка” событий плюс обработчики этих событий. Обработчик события реализует какие-либо действия. Самым простым событием является нажатие на клавишу клавиатуры или кнопку мыши. Более сложные события формируются системой Windows или текущим приложением. Для того чтобы обеспечить требуемую реакцию на то или иное событие, необходимо разработать интерфейс пользователя. Пользовательский интерфейс – это некоторая графическая среда, через которую передаются события внутрь приложения. Простейший интерфейс состоит из меню. Более сложные интерфейсы включают в себя различные кнопки, панели, диалоговые окна и т.п. Для разработки интерфейса служит палитра компонентов, которая содержит более 100 различных элементов. Внешний вид интерфейсных элементов может задаваться программно или с помощью инспектора объектов.
Приложение обеспечивает решение всей задачи и по мере необходимости обращается к средствам модулей. Модули содержат отдельные элементы – это типы данных, константы, переменные, подпрограммы и др., - которые необходимы для выполнения каких-либо операций. Модули фактически выступают в качестве библиотек этих элементов. В простейшем случае приложение может состоять из одной программы-проекта (используется очень редко). Приложение кроме модулей может иметь в своем составе динамические библиотеки (DLL). Программа-проект, модули и DLL называются программными единицами. Рассмотрим, из каких основных частей соотоит программная единица, т.е., какова структура различных программных единиц.
СТРУКТУРА ПРОГРАММЫ-ПРОЕКТА
Программа-проект определяется заголовком. Заголовок состоит из зарезервированного слова Program и имени программы, например
Program Project1;
Uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
Begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Имя программы совпадает с именем файла, в который она записывается. Непосредственно менять имя программы-проекта не следует – необходимо просто сохранить ее с другим именем. Текст программы-проекта очень редко приходится корректировать – Delphi создает его автоматически.
Текст программы-проекта записывается в файл Project1.dpr. Данная программа использует встроенный модуль Forms и модуль Unit1, который должен разработать программист. В фигурных скобках можно задавать комментарии или директивы. Признаком директивы является наличие символа $. Используемая в данном случае директива $R читает файл ресурсов и подключает их к проекту. Вместо символа * в данном случае будет подставлено имя Project1. Программа-проект стандартно вызывает три метода класса TApplication: методы Initialize, CreateForm и Run.
СТРУКТУРА МОДУЛЯ
Модуль является программной единицей для хранения элементов программирования. Модули бывают двух типов:
- стандартные, заранее созданные разработчиками Delphi и включенные в среду программирования;
- модули разработчика, создаваемые программистом.
Модуль состоит из следующих частей:
o заголовок (Unit);
o интерфейс (nterface);
o исполнительная часть (Implementation);
o секция инициализации (Initialization);
o секция завершения (Finalization);
o ключевое слово end с точкой.
Особенности этих частей заключаются в том, что каждая из них может присутствовать только один раз, их последовательность только такая, как указано выше. Секции инициализации и завершения могут отсутствовать.
Заголовок начинается с ключевого слова Unit, за которым следует имя. Имя модуля используется как имя файла, в который записывается текст программы. Delphi по умолчанию присваивает имя Unit1 - в дальнейшем это имя можно изменить при сохранении файла.
Интерфейс модуля – часть модуля доступная для других программных единиц. Интерфейс начинается с зарезервированного слова Interface.Заканчивается интерфейсная секция началом исполнительной части.
Исполнительная часть модуля начинается с ключевого слова Implementation, а завершается либо началом секции инициализации, если она есть, либо зарезервированным словом end. В этой секции определяются все процедуры и функции, методы классов и обработчики событий, объявленные в интерфейсной секции. Дополнительно могут содержаться определения программных элементов, которые не объявлены в интерфейсной части. Эти процедуры и функции являются недоступными для других программных единиц и используются для выполнения каких-либо внутренних действий в данной секции.
Секция инициализации содержит операторы, которые выполняют при запуске программной единицы какие-либо вспомогательные действия: открываются файлы, инициализируются переменные и т. д. Выполняются эти операторы только один раз. Начинается эта секция ключевым словом Initialization. Эта секция необязательна.
Секция завершения содержит операторы, которые выполняются при завершении приложения. Они исполняются один раз. Обычно в этой секции удаляются какие-либо временные файлы, записывается какая либо информация и т.п. Начинается эта секция с ключевого слова Finalization. Эта секция необязательна, однако, она должна присутствовать, хотя бы пустая, если есть секция инициализации.
Примером встроенного библиотечного модуля является модуль Forms, который содержит методы, позволяющие построить форму. Ниже приводится пример модуля:
Unit Unit1;
Interface
Uses {Подключаемые модули}
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs, StdCtrls;
Type {Объявления типов используемых переменных}
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
end;
var { Объявления переменных}
Form1: TForm1;
F: TextFile;
S: String;
Implementation
{$R *.DFM} {Загрузка файла ресурсов формы}
Procedure
TForm1.Button1Click(Sender: TObject);
Begin
S:=Edit1.Text; {Чтение строки S}
Edit1.Text:='';
end;
Procedure
TForm1.Button2Click(Sender: TObject);
Begin
Close;
end;
Initialization
AssignFile(F,’Myfile.txt’);
Rewrite(F); {Открытие файла }
Finalization
WriteLn(F,S); {Запись в файл строки S}
CloseFile(F); {Закрытие файла }
End.
Текст этой программы записывается в файл Unit1.pas, автоматически создается файл ресурсов для формы, который будет иметь имя Unit1.dfm.
Данная программа открывает файл Myfile.txt и записывает туда строку S, которая вводится с клавиатуры, используя объект Edit1.
Структура DLL будет описана далее.
При запуске приложения на выполнение сначала формируется выполняемый файл. Этот процесс делится на две стадии. Во-первых, компилятор транслирует исходный текст кода программы и формирует двоичный объектный код (в частности, создается файл Unit1.dcuдля откомпилированных файлов Unit1.pas и Unit1.dfm в данном случае). Во-вторых, компоновщик связывает полученный объектный код со встроенными библиотечными объектными кодами модулей. В результате создается исполняемый файл, в данном случае, Project1.exe.
ПРИМЕР 1
Создадим приложение, выполняющее какие-либо “полезные” действия. Для этого продолжим работу над проектом, форма которого представлена на рис.11. Пусть приложение будет выполнять сложение двух чисел s = a + b. Создадим форму, приведенную на рис.13.
Рис. 13. Форма к примеру 1.
В данном проекте использовались два новых компонента TLabel и TEdit (по сравнению с рис. 11). Компонент TLabel позволяет отобразить статический, нередактируемый текст. Используя этот компонент, задаются заголовки для других интерфейсных элементов. Текст заголовка вводится с помощью инспектора объектов (свойство Caption). Если свойство AutoSize равно “True”, то размер компонента динамически изменяется в зависимости от размера текста. Для того чтобы текст располагался в нескольких строчках, нужно свойству WordWrap задать True.
Компонент TEdit понадобился для создания полей ввода. С помощью этого компонента строятся строки редактирования – прямоугольные окна, в которых возможен ввод и редактирование текста. TEdit – однострочный редактор. Этот редактор содержит свойство Text, с помощью которого можно передавать данные внутрь приложения. Числа вводятся в виде текста, полученный текст программно преобразуется в числа с помощью функций преобразования. Окончание ввода осуществляется путем передачи фокуса другому компоненту, используя нажатие клавиши Tab. Если свойству ReadOnly задать значение True, то можно запретить ввод данных в данное поле ввода и использовать компонент TEdit для вывода результатов расчетов.
В качестве события, инициализирующего выполнение сложения, выберем нажатие на первую кнопку Button1 (кнопка “Расчет”). Выберем подходящее встроенное для кнопки Button1 событие - событие OnClick.
В рассматриваемом примере используются Label1, Label2, Label3, Edit1, Edit2, Edit3, Button1, Button2. Так как вводятся числа, то первоначально в свойстве Text интерфейсных элементов Edit1 и Edit2 нужно удалить с помощью инспектора объектов имеющийся текст. Далее необходимо задать свойство TabOrder для всех элементов – оно задает порядок “обегания” всех объектов на форме с помощью клавиши Tab. После запуска приложения фокус должен быть на Edit1. Поэтому необходимо задать свойство TabOrder для элемента Edit1 равным 0. Для Edit2 свойство TabOrder необходимо задать равным 1, Button1 - 2, Button2 – 3.
Далее запрограммируем обработчик события на нажатие кнопки “ Расчет”. Для этого в редакторе кода необходимо “вызвать” заготовку требуемого обработчика. Заготовку события OnClick в редакторе кода будет сгенерирована, если выполнить двойной щелчок с помощью левой клавиши мыши на элементе Button1. Между begin и end нужно написать код обработки события, выполняющий следующее:
- взять строку Edit1.Text и преобразовать ее в число;
- взять строку Edit2.Text и преобразовать ее в число;
- выполнить сложение этих чисел;
- полученный числовой результат преобразовать в текст и этот текст поместить в свойство Edit3.Text для отображения на экране дисплея.
Примем, что в данном случае будем работать с целыми числами. Решим проблему ограничения ввода только цифр. Этого можно достичь, если задать обработчик событий OnKeyPress – этот обработчик обрабатывает каждое нажатие клавиши на клавиатуре при вводе текста (в данном случае чисел). Таких обработчиков нужно два: для Edit1 и Edit2.
Вначале сформируем обработчик OnKeyPress для Edit1. Для этого необходимо выполнить следующее: мышью выбрать Edit1 на форме, в инспекторе объектов перейти на страницу событий (Events), выбрать OnKeyPress и выполнить двойное нажатие левой кнопкой мыши в поле справа от названия события. Появится редактор кода, в котором будет заготовка нужного обработчика. Введем текст:
If not (key in [‘0’..’9’]) then Key:=#0;
Этот оператор “отсеет” все символы, кроме цифр. Фактически этот обработчик исполняет роль фильтра, заменяя введенные нецифровые символы на самый первый символ (#0) из таблицы ASCII, который не имеет графического начертания.
Теперь сформируем обработчик OnKeyPress для Edit2. Так как он будет таким же, что и для Edit1, поступим следующим образом. Выберем Edit2, перейдем на страницу событий в инспекторе объектов, мышью выберем OnKeyPress - справа в этой строчке будет стрелка. Мышью нажмем на стрелку - появится в окошке строка Edit1KeyPress. Выберем мышью эту строку – один обработчик события OnKeyPress будет работать на два элемента Edit1 и Edit2.
Ниже приводится полный текст модуля Unit1.
unit Unit1;
Interface
Uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
Type
TForm1 = class(TForm)
{Список используемых интерфейсных элементов}
Label1: TLabel;
Edit1: TEdit;
Label2: TLabel;
Edit2: TEdit;
Label3: TLabel;
Edit3: TEdit;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Edit1KeyPress(Sender: TObject;
var Key: Char);
end;
var Form1: TForm1;
Implementation
{$R *.dfm}
{Программные коды используемых обработчиков событий}
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit3.Text:=IntToStr(StrToInt(Edit1.Text)+
StrToInt(Edit2.Text));
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Close;
end;
procedure TForm1.Edit1KeyPress(Sender: TObject;
var Key: Char);
begin
if not (key in ['0'..'9','-',#8,#13]) then key:=#0;
end;
End.
В обработчике OnKeyPress фильтр был расширен, чтобы появилась возможность ввода следующих дополнительных символов: ‘-‘, #8 – Backspace, #13 – Enter.
Самым замечательным в приведенной выше программе является то, что разработчик должен набрать всего три строки – это строки между begin и end в трех обработчиках событий.