Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебник Емельянов.doc
Скачиваний:
12
Добавлен:
03.11.2018
Размер:
3.25 Mб
Скачать

Структура приложения

Выше было отмечено, что приложение - это "ловушка" событий плюс обработчики этих событий. Обработчик события реализует какие-либо дей­ствия. Самым простым событием является нажатие на клавишу клавиатуры

24

или кнопку мыши. Более сложные события формируются системой Windows или текущим приложением. Для того чтобы обеспечить требуемую реакцию на то или иное событие, необходимо разработать интерфейс пользователя. Пользовательский интерфейс - это некоторая графическая среда, через кото­рую передаются события внутрь приложения. Простейший интерфейс со­стоит из меню. Более сложные интерфейсы включают в себя различные кнопки, панели, диалоговые окна и т.п. Для разработки интерфейса служит палитра компонентов, которая содержит более 100 различных элементов. Внешний вид интерфейсных элементов может задаваться программно или с помощью инспектора объектов.

Приложение обеспечивает решение всей задачи и по мере необходимо­сти обращается к средствам модулей. Модули содержат отдельные элемен­ты - это типы данных, константы, переменные, подпрограммы и др., кото­рые необходимы для выполнения каких-либо операций. Модули фактически выступают в качестве библиотек этих элементов. В простейшем случае при­ложение может состоять из одной программы-проекта (используется очень редко). Приложение кроме модулей может иметь в своем составе динамиче­ские библиотеки (DLL). Программа-проект, модули и DLL называются про­граммными единицами. Рассмотрим, из каких основных частей состоит программная единица, т.е. какова структура различных программных еди­ниц.

СТРУКТУРА ПРОГРАММЫ-ПРОЕКТА

Программа-проект определяется заголовком. Заголовок состоит из заре­зервированного слова Program и имени программы, например

Program Project1;

Uses Forms,

Unit1 in 'Unit1.pas' {Form1};

{$R *.RES} begin

Application.Initialise;

Application.CreateForm{TForral, Form1);

Application.Run; end.

Имя программы совпадает с именем файла, в который она записывается. Непосредственно менять имя программы-проекта не следует - необходимо просто сохранить ее с другим именем. Текст программы-проекта очень ред­ко приходится корректировать - Delphi создает его автоматически.

Текст программы-проекта записывается в файл Project1.dpr. Данная программа использует встроенный модуль Forms и модуль Unit1, который Должен разработать программист. В фигурных скобках можно задавать ком­ментарии, или директивы. Признаком директивы является наличие

25

символа $. Используемая в данном случае директива SR читает файл ресур­сов и подключает их к проекту. Вместо символа * в данном случае будет подставлено имя Project 1. Программа-проект стандартно вызывает три мето­да класса TApplication: Initialize, CreateForm и Run.

Структура модуля

Модуль является программной единицей для хранения элементов про­граммирования. Модули бывают двух типов:

  • стандартные, заранее созданные разработчиками Delphi и включенные в среду программирования;

  • модули разработчика, создаваемые программистом. Модуль состоит из следующих частей:

  • заголовок (Unit);

  • интерфейс (interface);

  • исполнительная часть (Implementation);

  • секция инициализации (Initialization);

  • секция завершения (Finalization);

  • ключевое слово end с точкой.

Особенности этих частей заключаются в том, что каждая из них может присутствовать только один раз, их последовательность только такая, как указано выше. Секции инициализации и завершения могут отсутствовать.

Заголовок начинается с ключевого слова Unit, за которым следует имя. Имя модуля используется как имя файла, в который записывается текст программы. Delphi по умолчанию присваивает имя Unit1. В дальнейшем это имя можно изменить при сохранении файла.

Интерфейс модуля - часть модуля, доступная для других программных единиц. Интерфейс начинается с зарезервированного слова Interface. Закан­чивается интерфейсная секция началом исполнительной части.

Исполнительная часть модуля начинается с ключевого слова Imple­mentation, а завершается либо началом секции инициализации, если она есть, либо зарезервированным словом end. В этой секции определяются все процедуры и функции, методы классов и обработчики событий, объявлен­ные в интерфейсной секции. Дополнительно могут содержаться определения программных элементов, которые не объявлены в интерфейсной части. Эти процедуры и функции являются недоступными для других программных единиц и используются для выполнения каких-либо внутренних действий в данной секции.

Секция инициализации содержит операторы, которые выполняют при запуске программной единицы какие-либо вспомогательные действия: от­крываются файлы, инициализируются переменные и т. д. Выполняются эти

26

операторы только один раз. Начинается эта секция ключевым словом Ini­tialization. Эта секция необязательна.

Секция завершения содержит операторы, которые выполняются при завершении приложения. Они исполняются один раз. Обычно в этой секции удаляются какие-либо временные файлы, записывается какая-либо инфор­мация и т.п. Начинается эта секция с ключевого слова 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 Button1Cliclc(Sender: TObject) ;

procedure Button2Click(Sender: TObject);

end;

var {Объявления переменных}

Form1: TForm1; F: TextFile; S: String;

Implementation

{$R *.DFM} {Загрузка файла ресурсов формы}

procedure

ТForm1.Button1Click(Sender: TObject);

begin

S:=Edit1.Text; {Чтение строки S}

Edit1.Text:='';

end;

procedure

TForm1.Button2Click(Sender: TObject); begin

Close; end;

Initialization

AssignFilefF,'Myfile.txt'); Rewrite (F) ; {Открытие файла}

Finalization

WriteLn(F,S) ; {Запись в файл строки S}

27

{Закрытие файла}

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

В данном проекте использовались два новых компонента TLabel и TEdit (по сравнению с рис. 11). Компонент TLabel позволяет отобразить статиче­ский, нередактируемый текст. Используя этот компонент, задают заголовки для других интерфейсных элементов. Текст заголовка вводится с помощью инспектора объектов (свойство Caption). Если свойство AutoSize равно "True", то размер компонента динамически изменяется в зависимости от размера текста. Дня того чтобы текст располагался в нескольких строчках, нужно свойству Wordwrap задать True.

Компонент TEdit понадобился для создания полей ввода. С помощью этого компонента строятся строки редактирования - прямоугольные окна, в

которых возможен ввод и редактирование текста. TEdit - однострочный редактор. Этот редактор содержит свойство Text, с помощью которого можно передавать данные внутрь приложения. Числа вводятся в виде текста, полученный текст программно преобразуется в числа с помощью функций преобразования. Окончание ввода осуществляется путем передачи фокуса другому компоненту, используя нажатие клавиши Tab. Если свойству ReadOnly задать значение True, то можно запретить ввод данных в данное по­ле ввода и использовать компонент TEdit для вывода результатов расчетов.

В качестве события, инициализирующего выполнение сложения, выбе­рем нажатие на первую кнопку Button1 (кнопка "Расчет"). Выберем подхо­дящее встроенное для кнопки Button1 событие - событие OnCIick.

В рассматриваемом примере используются Label1, Label2, LabeI3, Edit1, Edit2, Edit3, Button1, Button2. Так как вводятся числа, то первона­чально в свойстве Text интерфейсных элементов Edit1 и Edit2 нужно удалить с помощью инспектора объектов имеющийся текст. Далее необходимо за­дать свойство TabOrder для всех элементов - оно задает порядок "обега-ния" всех объектов на форме с помощью клавиши Tab. После запуска при­ложения фокус должен быть на Edit1. Поэтому необходимо задать свойство TabOrder для элемента Edit1 равным 0. Для Edit2 свойство TabOrder необхо­димо задать равным 1, Button1 - 2, Button2 - 3.

Далее запрограммируем обработчик события на нажатие кнопки " Рас­чет". Для этого в редакторе кода необходимо "вызвать" заготовку требуемо­го обработчика. Заготовка события OnCIick в редакторе кода будет сгенери­рована, если выполнить двойной щелчок с помощью левой клавиши мыши на элементе Button1. Между begin и end нужно написать код обработки со­бытия, выполняющий следующее:

  • взять строку Edit1. Text и преобразовать ее в число;

  • взять строку Edit2 . Text и преобразовать ее в число;

  • выполнить сложение этих чисел;

  • полученный числовой результат преобразовать в текст и этот текст по­ местить в свойство Edit3. Text для отображения на экране дисплея.

Примем, что в данном случае будем работать с целыми числами. Решим проблему ограничения ввода только цифр. Этого можно достичь, если задать обработчик событий OnKeyPress. Этот обработчик обрабатывает каждое нажатие клавиши на клавиатуре при вводе текста (в данном случае чисел). Таких обработчиков нужно два: для Edit1 и Edit2.

Вначале сформируем обработчик OnKeyPress для Edit1. Для этого необ­ходимо выполнить следующее: мышью выбрать Edit1 на форме, в инспекто­ре объектов перейти на страницу событий (Events), выбрать OnKeyPress и выполнить двойное нажатие левой кнопкой мыши в поле справа от названия события. Появится редактор кода, в котором будет заготовка нужного обра­ботчика. Введем текст:

28

29

If not (key in [‘O'..'9']) then Key:=#0;.

Этот оператор "отсеет" все символы, кроме цифр. Фактически этот об­работчик исполняет роль фильтра, заменяя введенные нецифровые символы на самый первый символ (#0) из таблицы ASCII, который не имеет графиче­ского начертания.

Теперь сформируем обработчик OnKeyPress для Edit2. Так как он будет таким же, что и для Edit 1, поступим следующим образом. Выберем Edit2, перейдем на страницу событий в инспекторе объектов, мышью выберем OnKeyPress (справа в этой строчке будет стрелка). Мышью нажмем на стрелку - появится в окошке строка Edit1KeyPress. Выберем мышью эту строку - один обработчик события OnKeyPress будет работать на два эле­мента Edit1 HEdit2.

Ниже приведен полный текст модуля 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;

30

end;

procedure TForm1.Edit1KeyPress(Sender: TObject;

var Key: Char);

begin

if not (key in [‘O'..'9', '-',#8]) thenkey:=#0;

end; end.

В обработчике OnKeyPress фильтр был расширен, чтобы появилась воз­можность ввода следующих дополнительных символов: '-', #8 (Backspace).

Самым замечательным в приведенной выше программе является то, что разработчик должен набрать всего три строки - это строки между begin и end в трех обработчиках событий.

ОПИСАНИЯ ПРОГРАММНЫХ ЭЛЕМЕНТОВ

Любая программа состоит из программных элементов и операторов управления этими элементами. К программным элементам относятся кон­станты, типы, переменные, процедуры, функции, объекты и некоторые дру­гие. К операторам управления относятся следующие операторы: присваи­вания, построения разветвлений в расчетах, построения циклических вычис­лений и др.

С помощью объявления в программу вводится какой-либо программ­ный элемент. Ему присваивается имя и, возможно, начальное значение. Ob­ject Pascal является строго типизированным языком. Это означает, что каж­дому программному элементу до первого применения необходимо задать его тип, чтобы сообщить компилятору, к какого вида сущностям относится объ­явленный программный элемент. Эта сущность определяет, какие операции можно применить и как эти операции должны интерпретироваться.

ПРОГРАММНЫЕ ЭЛЕМЕНТЫ И АДРЕСА ПАМЯТИ

Каждый программный элемент занимает какую-либо область памяти. Компилятор неявно заменяет каждое имя определенным адресом в памяти. Иногда имя определяет не сам элемент, а "нечто в памяти". В этом случае имя представляет собой явно указываемый адрес размещения некоторого программного элемента. Такой программный элемент называется ссылкой, или указателем. Таким образом, имена могут представлять или программ­ные элементы или адреса размещения этих элементов.

ОБЛАСТИ ВИДИМОСТИ

Объявление вводит имя в области видимости, т. е. имя может исполь­зоваться только в определенной части программы. Для имени, описанного,

31

например, в процедуре кого-либо обработчика событий (такое имя часто называют локальным - Sender в примере 1), область видимости простира­ется только в блоке процедуры. Имя, описанное, например, в интерфейсной секции модуля (такое имя называют глобальным - TForm, Form1 в примере 1, имена в подключаемых модулях, например в Forms), имеет область види­мости, простирающуюся на весь модуль. Области видимости иногда задают с помощью ключевых слов Private, Public, Protected.

ПРАВИЛА ЗАПИСИ ИМЕН

Имя (идентификатор) состоит из последовательности букв и цифр. Первый символ должен быть буквой. Символ подчеркивания "__" считается буквой. Количество символов в имени может быть достаточно большим, но значимыми являются первые 63 символа. Буквы в верхнем и нижнем регист­ре неразличимы в имени, однако, для удобочитаемости программ следует использовать прописные и строчные буквы.

ВРЕМЯ ЖИЗНИ ИДЕНТИФИКАТОРОВ

Если программист не указал иного, то программный элемент, например локальный, создается, когда встречается его объявление, и уничтожается, когда его имя выходит из области видимости. Элементы с глобальными именами создаются и инициализируются автоматически при объявлении или с помощью инспектора объектов. Иногда они создаются не автоматически, а явно в программе (очень часто один раз) и "живут" до завершения програм­мы. Если элемент создан явно программистом, то при выходе из области видимости его явно необходимо уничтожить, иначе можно непроизводи­тельно занять всю память.

ИСПОЛЬЗОВАНИЕ ЛОКАЛЬНЫХ ПЕРЕМЕННЫХ В ПРИМЕРЕ 1

Рассмотрим другие варианты решения примера 1. Вначале исследуем понятие "локальных переменных", введенное выше. Использование ло­кальных переменных, в данном случае, повышает "'наглядность" программ­ного кода. Для реализации этой идеи достаточно изменить один обработчик -нажатие на кнопку Button1 (рис. 13):

procedure TForm1.Button1Click(Sender: TObject); {объявление локальных переменных)

var а,Ь,s:integer; begin

а:=StrToInt(Edit1.Text);

Ь:=StrToInt(Edit2.Text);

s:=a+b;

Edit3.Text:=IntToStr(s); end;

ИСПОЛЬЗОВАНИЕ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ В ПРИМЕРЕ 1

Как можно заметить из сравнения двух приведенных выше вариантов решения примера 1, применение локальных переменных привело к неболь­шому изменениию программного кода. Еще один вариант решения можно получить, используя глобальные переменные. Их применение изменяет структуру приложения - добавляются новые обработчики событий.

Глобальные переменные (var a,b,s:integer;) объявляются в интер­фейсной секции модуля Unit1 (пример 1). Значения глобальным переменным а и Ь присваиваются на уровне работы соответствующих компонентов, в данном случае Edit1 и Edit2. Это означает, что при выходе, например, из элемента Edit1 (при потере фокуса элементом Edit1) необходимо присвоить значение соответствующей числовой переменной. Такое присваивание мож­но выполнить с помощью обработчика OnExit Таким образом, структурно приложение дополняется двумя обработчиками Edit1 Exit и Edit2Exit. Ниже представлены программные коды этих обработчиков:

procedure TForm1.EdxtlExit(Sender: TObject) ;

TObject) ;

begin

a:=StrToInt(Edit1.Text);

end;

procedure TForm1.Edit2Exit(Sender: TObject);

TObject);

begin

b:=StrToInt(Edit2.Text);

end;.

Соответственно в обработчике Buttoniciick необходимо убрать строчки вычисления значений переменных а и Ь. Учитывая еще, что пере­менная s объявлена глобально, перепишем код рассматриваемого обработ­чика событий:

procedure TForm1.Button1Click(Sender: TObject); begin s:=a+b;

Edit3.Text:=IntToStr(s); end;

ТИПЫ

Тип в простейшем случае определяет вид конкретно представляемой в памяти информации, например переменных, констант. В более широком смысле тип есть конкретное представление некоторой концепции (понятия),

32

3-- 4758

33

применяемой к тем или иным данным. Например, имеющийся тип double с его операциями +, -, *, / и встроенными математическими функциями вы­числения логарифма, синуса и т. д. обеспечивает ограниченную, но конкрет­ную версию математического понятия действительного числа. Язык про­граммирования имеет множество встроенных типов, а также предоставляет инструменты построения собственных типов. Собственный тип создается для того, чтобы дать специальное и конкретное определение понятия, кото­рому среди встроенных типов ничто не отвечает, например, построить от­сутствующий в Object Pascal тип, позволяющий работать с комплексными числами. Хорошо выбранные типы делают программу более четкой и корот­кой.

Итак, каждое имя в программе имеет ассоциированный с ним тип. Этот тип определяет:

  • структуру программного элемента, т. е. ту или иную интерпретацию памяти;

  • множество допустимых значений;

  • совокупность возможных операций с ним.

В Object Pascal можно выделить следующие типы:

  • простые;

  • структурированные;

  • указатели;

  • классы;

  • вариантный тип.

Самую обширную группу представляют структурированные типы. Структурированные типы данных определяют наборы однотипных или раз­нотипных компонентов. Типы компонентов образуются из других типов данных. Можно выделить следующие структурированные типы:

  • массивы;

  • строки;

  • записи;

  • множества;

  • файлы.

Задание типа тому или иному элементу в программе необходимо для то­го, чтобы компилятор мог выделить соответствующую память и установить механизм доступа к самому элементу и его компонентам.