112
DELPHI • 2008

ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

  • Upload
    others

  • View
    28

  • Download
    1

Embed Size (px)

Citation preview

Page 1: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

7~УКk DELPHI ПРОГРАММИРОВАНИЕ С НУЛЯ

Илья БЕСКОРОВАЙНЫЙ

VсиБИРСКОЕ УНИВЕРСИТЕТСКОЕ ИЗДАТЕльство НОВОСИБИРСК • 2008

Page 2: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

УДК 681.3.06 ББК 32.973.26-018.2

Б53

Бескоровайuый, И. В.

Б53 Азбука Delphi: программирование с нуля [Текст]/ И. В. Беско-ровайный. Новосибирск: Сиб. унив. изд-во, 2008. 112 с.

ISBN 978-5-379-00279-4

В книге кратко излагаются теоретические основы программирования и ООП, а работа с базовыми компонентами Delphi дается на примерах. Это позволяет за несколько дней научиться создавать несложные приложения под

Windows. В книге содержатся рекомендации как, используя Delphi, превратить ком­

пьютер в эффективный инструмент решения повседневных задач. А приве­денный иллюстративный материал может быть использован как основа для любого учебного Rypca по Delphi.

Отдельная глава полностью посвящена работе с файлами. В справочном приложении дается краткое описание специализированных компонентов и биб­

лиотек.

Книга написана простым и понятным языком и будет полезна студентам

вузов и старшеклассникам в качестве учебного пособия по Delphi.

ISBN 978-5-379-00279-4

УДК 681.3.06 ББК 32.973.26w018.2

© Бескоровайный И. В., 2008 © Сибирское университетское

издательство, оформление, 2008

Page 3: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

СОДЕРЖАНИЕ

Введение" ..... "" ............. " ..... "." .. """."" ...... "" ... " ....... " .. """ .... "." ..... " .. 5

Глава 1. Знакомство со средой программирования " .. " ..... "" ... " .... 8

Глава 2. Object Pascal ..... ""."." ... " ............... "" .... " .... " ... "" .... " ...... " ... 17

Глава З. Учимся программировать .............. "." ... " .......... """."" "" ... 25

3.1. Типы данных" .............. "." .... " ... " .......... " .. " ...... " .. ""." .. " ..... "."." 27 Целочисленные типы .............. " ....... " ......................... " ................... 27 Вещественные, или дробные, типы ........... " .......... " ................ " .. ". 28 Символьные переменные ............ " ......... "."." .. " ...................... " ... " 29 Логический, или Булев, тип " ............ " ........ " ..... """ .... " .................. 30 Тип список ......................... " ..... " ................... "" ........... " ............ -" .. ".31 Тип диапазон .. " ...... " .. "." .... " .. "." ".". " ............ " ......... "" ... " .. " ""." .. 31 (/:>'}IHKLJ,l'IИ пpeo6pfJ.:ЗOEJaHl'tfl тl'tпов ...................................................... 32

3.2. Выражения, операторы и операнды ... "" .............. "." ... " .. " .. "." 33 3.3. Процедуры и функции ... "." ... " ... " .. "" .. ""."" ... " .... " ... " ..... " .. " ... 34 3.4. Массивы"" ...... " .. ".:'" .... " ......... " .... " ... """ ... " .............. ""."" .. """. 36 3.5. Циклы .. "" ........ " .... " .. """"." .. " ......... "" ....... "" .. """ " ... """"" " ..... 38 3.6. Условный оператор ....... " .................... "."."" .. " ........... "." ........ ".41 3.7. Функции для работы с текстом ........... "." .. "" ... " ... "." .... " ...... " ... 45

Глава 4. Объектно-ориентированное программирование"" ........ 50

Глава 5. Работа с файлами в Delphi . " .. "". "". """ .. "" ..... "" " ... " ....... 57

Глава 6. Примеры взаимодействия объектов разных классов." ... " ...... " .... " ....... " .. " ... " ........... " ............. " .. 70

6.1. Приложение «Кнопки» ....... " ..... " .... " .... " ..... """" ................. " ...... 70 6.2. Фильтр ввода .......... """ .. " ......... " ... "." .... "."" .... " ..... " ... " ........... " 73 6.3. Контекстные меню ............ """" ... "." ... "" ........... " ..... """ ... " .. """ 74

Глава 7. Процесс отладки проrраммь1."""""."" .......... " .... " .. """"" 77

-3-

Page 4: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение) ....................... " ........................ " 84

8.1 . Меню .. ". ".""""""" " ...... " .. " ....... ""." "" ." ... "." .......... ".""." .. " ..... 90 8.2. Работа с текстом .. " .... " ...... """"." .. " ....... " ....... "" ..... " .......... "" ... 93 8.3. Кнопки".""."" .. """."." .. " .. "" .. """" ... "" ... "." .... " .. " ........... "" ...... 99 8.4. Списки."." .. """."." ..... """." .. " .... """."""."."" .. "" .... " ... """ .... " 103 8.5. Остальные компоненты ... " ............... " .......................... "."" ....... 105

Scrolf Bar ........... " " .....•....... " ... " ..... " .. " .... " .. " ... " .. " .. " ....................... 105 lmage ..... " ...... " ....... " ...................... "." ... " .. "." .. "" .............. "."." ..... 106

Shape ... """"" ... ".".""" ..... """.""" .. """".""" ..... "" .. :".""."." .. """ 107 Bevel ."."." ........ """"."" .. "." ...... " ..... " ..... " ....... " .. " ................. " ...... 107 Scrol/Box " ... " .. " .. "" .. " ..... " "." " .. " " .. " ". " .. "." .............. "" ..... "" .... ". 107 Splitter .... "."""" " ..... " ... " ........ "" "" " . "" ... "."." ...... ".""." ......... "" ... 1 08 ControlBar." .. " .. "" .. ". " .. " " ... """""" ... " ... ". ".":" .. " ""." .... "."" .... ". 108 Chart"." .... " ..... " .. """" ... " .. """" ... " .. "."." .. ""." .. "" .. "." ...... """"" .. 109

Page 5: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

ВВЕПЕНИЕ

Книги по программированию можно разделить на три большие

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

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

ся в реальной практике программирования. Эти книги, как правило,

довольно объемны.

Таким образом, несложно по весу этой книги догадаться, в какую

группу ее постарались отнести те, благодаря кому книга появилась в ваших руках.

Книга окажется полезной тем, кто достаточно хорошо знаком

с операционной системой Windows, чтобы у него не вызывали затруд­нений такие термины, как Окно, Инструментальная панель, Встроен­

ная подсказка, Файл и т. д., и кто хочет научиться разрабатывать приложения под Windows. Если читатель имеет определенный опыт программирования на таких языках, как Pascal или С, то это, несом­ненно, послужит неплохим подспорьем. Полезным также окажется

знание основ объектно-ориентированного программирования, но если

таковое отсутствует, это не страшно, поскольку новые понятия пос­

тепенно усваиваются по ходу чтения книги. В главе 4 кратко описаны некоторые аспекты объектно-ориентированного программирования, однако для лучшего усвоения материала целесообразнее будет про·

двигаться по книге по порядку, за исключением последней главы,

которая, являясь справочной, может оказаться полезной при работе

с примерами, разборе возникших вопросов или написании собствен­ных приложений.

Вы не найдете в книге исчерпывающих описаний меню, системы

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

пользователь работал какое-то время в одном приложении, то ему не составит труда запустить другое и начать работать в нем. Естествен-

-5-

Page 6: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

но, это утверждение касается только интерфейсной части и совсем не относится к области решаемых приложением задач. Если вы два года работали в текстовом процессоре наподобие MS Word, едва ли это даст вам знание того, как эффективно работать в системе трех­мерного проектирования, хотя, запустив эту систему и некоторое

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

работы. При изложении материала, по возможности, мы старались избе­

жать смысловых повторов. Это значит, что если какое-либо действие

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

снова.

Основная сложность в процессе программирования - не в том,

чтобы запомнить, что означает какая-то команда или сколько байт в оперативной памяти занимает та или иная переменная, хотя без этого

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

ты и составлять алгоритмы решения поставленных задач. У читывая,

что алгоритм решения по большей части содержится в постановке

задачи, важно уметь формулировать для себя задачи таким образом, чтобы они могли быть разбиты на простейrµие действия, доступные

компьютеру. Не стоит требовать от компьют~ра слишком многого. Как ни бьются специалисты по искусственному интеллекту, компьютер

по-прежнему не может заменить человека в творческой части работы,

однако он способен очень быстро делать рутинную ее часть. Как пра­

вило, именно это от него и требуется в реальных условиях.

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

да разработки (IDE) позволяет в кратчайшие сроки создавать дейст­вующие приложения, на ходу проектируя и видоизменяя их пользо­

вательский интерфейс. Delphi - одна из первых систем, использую­щих технологию быстрой разработки приложений (Rapid Application Development-RAD). Эта технология является довольно распростра­ненной и невероятно гибкой. Первый факт позволяет общаться с другими разработчиками, обмениваясь опытом и постоянно совер­

шенствуясь, а второй факт говорит о том, что, используя Delphi, вы можете спроектировать практически все что угодно: от простейшего

калькулятора или будильника до системы управления базами данных

или WеЬ-серверов. В то же время Delphi обладает достаточно широ­кими возможностями по защите операционной системы и компьюте-

-6-

Page 7: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Введение

ра от неосторожных действий начинающего разработчика. Эти фак­

торы делают Delphi уникальной средой программирования для тех, кто решил научиться разрабатывать приложения под Windows. Являясь отличной средой для самостоятельного изучения, Delphi при этом практически не ограничивает фантазию разработчика. Если со вре­м~нем вам станет не хватать возможностей Delphi, вы сможете по­добрать для себя среду программирования, более подходящую харак­

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

лучше всего именно с Delphi, причем не откладывая это дело в долгий ящик.

Page 8: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 1. Знакомство со средой проrраммирования

Интегрированная среда разработки (lntegrated Development Environment, IDE) - это среда, в которой разработчику предостав­ляется все необходимое для написания, отладки, запуска и тестироw вания приложений. Создатели Delphi сделали очень многое, чтобы облегчить процесс создания эффективных приложений. В состав IDE входит несколько элементов:

• редактор кода;

•отладчик;

• набор панелей инструментов;

• обширная библиотека компонентов;

• редактор изображений;

• инструментарий баз данных.

Запустите Delphi. Предполагается, что установка не вызвала проблем, с которыми вы

не смоп1и справиться. После завершения процесса загрузки экран вы­

глядит, как показано на рис. 1.1. Вообще вид первоначального экрана зависит от того, какая версия Delphi используется. В данном случае -Delphi 6.0, и все примеры, приведенные в книге, разрабатывались и тес­тировались именно в этой версии. Однако едва ли при переходе к более ранним или более поздним версиям возникнут какие~либо трудности.

Некоторые элементы основного окна практически такие. же, как и в

других Windоws-приложениях, поэтому не будем останавливаться на разборе меню или основных кнопок панели инструментов. Упомянем только несколько основных команд и их последовательностей, исполь­

зуемых при разработке приложений. Создание нового проекта приложе­ния - последовательность File ~ New ~ Application, приводящая к появлению новой пустой формы и Окна редактора кода, таких, как вы

можете видеть на рис. 1.1. При сохранении проекта или его заготовки по команде Save All предлагается ввести имя проекта и имя каждого из модулей, включенных в проект. Для запуска приложения служит коман­да Run ~ Run или кнопка с зеленой стрелкой на панели инструментов.

Справа сверху на панели инструментов расположена палитра биб­лиотеки визуальных компонентов ( Visual Component Library, VCL ). Ближе к истине будет называть ее просто библиотекой, поскольку на вкладках содержатся как визуальные компоненты, например поля

ввода текста и кнопки, так и невизуальные, например таймер.

-8-

Page 9: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 1. Знакомство со средой проrраммирования

Рис. 1.1. Экран Delphi 6.0 сразу после загрузки

Слева в основном поле окна расположен Инспектор объектов Object lnspector (см. рис. 1.1 ), с его помощью задаются свойства ком­понентов и назначаются обработчики событий. Над Инспектором объ­ектов отображается Структура дерева объектов~ окно Object TreeView, в котором показана иерархия объектов, задействованных в приложе­

нии. Полезность Object TreeView ограничена, и многие программисты предпочитают закрывать его вовсе, используя освободившееся место

для разворачивания Инспектора объектов.

Правее расположена пустая форма, готовая для размещения на ней компонентов VCL. Для того чтобы поместить нужный компонент на форму, нужно открыть соответствующую страницу палитры VCL, щелкнуть по компоненту, а затем щелкнуть на том месте формы, где должен располагаться компонент.

Форма, на которой размещаются компоненты, является основой большинства приложений Delphi. Она представляет собой окно со­здаваемого приложения. В данном случае удобство IDE заключается в том, что программист уже в процессе создания приложения может

видеть, каким будет у его приложения интерфейс для общения с поль­зователем и непосредственно редактировать взаимное расположение

и свойства (цвет, размер) элементов интерфейса для придания ему большей эргономичности.

-9-

Page 10: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Еще одной частью IDE является Окно редактора кода (рис. 1.2). При запуске это окно практически полностью скрыто за формой и

лишь немного выглядывает из-за нее снизу и справа; изменить это

положение можно, изменив размеры формы или окна редактора. На работу с редактором кода уходит, как правило, больше всего времени при разработке приложения. Ведь если шаблонные опер~ции, такие как создание и удаление заголовков процедур, описание типов, опре­

деление подключаемых модулей и некоторые другие, среда програм­

мирования выполняет за программиста, то определение конкретных

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

Слева находится встроенное окно Code Explorer (см. рис. 1.2). Это окно рассматриваться не будет, его вполне можно закрыть.

В редакторе кода применяется выдеJ1ение цветом синтаксических элементов. Ключевые слова в Object Pascal выделяются жирным шрифтом, а комментарии - синим курсивом. Комментарием считает­ся весь текст, заключенный в фигурные скобки { } , скобки со звездоч­кой(**) или расположенный между двойной косой чертой// и концом строки.

,--- TFOfm1 ф fiiJ VariaЫes/Constants tE··G]) Uses

Code Ех larer

Mesэages, SysUtilэ, Variants,

TForml = c1ass(TForm) privat.e

{ P.civate decla.cations } рм1iс

{ РиЫiс declarations } end;

TForml;

Рис. 1.2. Окно редактора кода

- 10 -

Page 11: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 1. Знакомство со средой программирования

Delphi содержит достаточно много настроек, но все их знать на начальном этапе вовсе не обязательно, большинство вполне можно оставить по умолчанию. Для изменения настроек среды нужно вы­брать пункт меню Tools ~ Environment Options ...

В открывшемся Окне настроек среды (рис. 1.3) рассмотрим на­стройки, находящиеся на странице Preferences (Предпочтения).

Самым ценным пунктом, пожалуй, здесь являются настройки автоматич~ского сохранения Autosave options. Установка галочки Editor frles соответствует сохранению всех модифицированных фай­лов, а установка галочки Project desktop - сохранению расположения

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

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

ку снять. Как обычно, не существует таких установок, которые были бы оптимальны в каждом конкретном случае.

Рис. 1.3. Диалог Environment Options

- 11 -

Page 12: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Рассмотрим теперь раздел настроек процесса компиляции и за­

пуска готовой программы Compiling and running. Здесь доступны сле­дующие пункты:

• Показывать окно процесса компиляции (Show compiler progress ). Здесь галочку лучше убрать, ведь вся информация, которая вы­водится в окне процесса компиляции, дублируется в дополни­

тельном окне, появляющемся внизу редактора кода (рис. 1.4), на которое, кстати, стоит обращать пристальное внимание. В нем отображаются ошибки, возникшие при компиляции, а так­же советы (Hints) по оптимизации отдельных участков кода или предупреждения (Warnings) о возможности возникновения оши­бок периода выполнения приложения.

• Предупреждать, когда необходима перекомпиляция пакета (Warn on package rebuild). Пока вы только начинаете работать с Delphi, лучше активизировать эту опцию, позже вы сможете сами ре­

шить, нужна она вам или просто отнимает лишнее время.

• Минимизировать оболочку, когда запущена редактируемая в IDE программа (Miпimize оп run).

• Прятать окна Инспектора объектов и визуальной формы при запуске программы (Hide designers on run).

Последние две опции не влияют на работу приложения, но, буду­

чи отключенными, экономят время процессора на сворачивание

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

На других страницах Окна настроек среды находится еще неко­

торое количество полезных опций, таких как настройка отображения сетки на форме (вкладка Designer, раздел Grid options) или настройки состава Палитры компонентов (Palette ). Все они, впрочем, обладают условной полезностью, и для большинства задач программирования их можно оставить такими, какими они выставляются при установке

Delphi.

Рис. 1. 4. Список ошибок периода компиляции

- 12 -

Page 13: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Гnава 1. Знакомство со средой программирования

Диалог, вызываемый пунктом меню Project-+ Options"., включа­ет в себя несколько страниц опций, позволяющих изменять парамет­

ры компиляции проекта. Все настройки после компиляции сохраняют­

ся в файле с расширением .opt. Рассмотрим некоторые из страниц этого диалога:

•Закладка Forms. Здесь перечI:Iслены все формы, включенные в проект; можно указать, какие из них должны появляться на

экране при запуске приложения, какая форма будет основной.

•на странице Application задаются название приложения (оно будет отображаться на панели Windows при запуске), файл по­мощи и иконка приложения.

• Страница Compiler содержит установки компилятора. В разделе Создание кода (Code generation) можно задать или запретить возможность оптимизации итогового кода, создание стэка вызо­

вов процедур и функций, возможность отслеживать возникно­вение деления числа на нуль, а также увеличение размера, зани­

маемого элементами структур до числа байт, которым проще оперировать процессору. Первая опция, будучи установленной,

ускоряет работу приложения. Увеличение числа в списке Record field alignment (выравнивание полей записи) немного ускоряет работу программы за счет незначительного увеличения потреб­

ляемой памяти, вторая и третья опции замедляют работу прило­

жений. В разделе Настройки синтаксиса (Syntax options) в ос­новном расположены настройки работы с динамической памя­тью. Раздел Ошибки периода выполцения (Runtime errors) содержит опции, контрол11рующие выход индексов массивов и

строк за объявленные пределы, правильность работы операций ввода и вывода, а также появление ситуации переполнения при

работе с целочисленными величинами. Опции раздела Отладка (Oebugging) в основном добавляют вспомогательную информа­цию в различные файлы проекта. На этой же вкладке в разделе Сообщения (Messages) можно отключить вывод предупреждений Warnings и советов Hints в дополнительное окно редактора кода (в некоторых версиях раздел Сообщений компилятора-Compiler Messages ~может быть вынесен на отдельную вкладку).

Рассмотрение остальных вкладок диалога не входит в задачи этой

книги.

Следующим шагом в изучении Delphi будет написание простого приложения. Если вы успели закрыть Delphi, то запустите его снова. Создастся новое приложение. Разместите на форме компоненты Label

- 13 -

Page 14: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

и Button. Разместить их можно как угодно. Если они будут находить­ся непосредственно на форме, то программа будет работать. Щелк­ните один раз по объекту Label на форме в Инспекторе объектов отобразятся свойства этого объекта (рис. 1.5).

Примечание

Для того чтобы бьшо легче найти нужный элемент в библиотеке, все они снабжены всплывающими подсказками: если курсор навести на пикто­

грамму и задержать на пару секунд, появится всплывающая подсказка

{Hint), в которой отображено название соответствующего компонента.

Как видно на рисунке, основное поле Инспектора объектов представ-

ляет собой таблицу из двух столбцов. В левом столбце находятся названия свойств, а в правом - их значения. Убедитесь, что в поле значения свойст­ва Name объекта Label находится надпись Label 1 (см. рис. 1.5). Если нет добавьте ее. Сотрите надпись в поле значения свойства Caption (заголовок). На этом работа с данным объектом временно завершена. Впоследствии вы сможете изменить шрифт и содержание надписи, а также еще некоторые свойства. (Основные свойства наиболее часто ис­пользуемых компонентов рассматриваются в последней главе.)

Рис. 1.5. Вид Инспектора объектов при выделении объекта Label

Щелкните на любом месте фор­мы - содержимое Инспектора объ­

ектов изменится. Теперь он будет показывать свойства самой формы.

Щелкните на кнопке, которую вы

разместили на форме. С помощью Инспектора объектов измените зна­

чение свойства Caption на что-либо осмысленное, например, «Пуск!».

В начальный момент там должно бы­ло находиться значение Buttonl.

Примечание

При задании имен элементов (N ame) недопустимо использовать ключевые

слова Object Pascal, однако при зада­нии заголовков (Caption) вы можете писать все что угодно.

Наверняка вы заметили, что в ок­

не Инспектора объектов расположе­

ны две страницы: Properties ( Свойст­ва) и Events (События). До сих пор работа шла с первой страницей: вы определяли свойства объектов. Убе­дитесь, что в Инспекторе отображают-

- 14 -

Page 15: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 1. Знакомство со средой программирования

ся свойства кнопки Buttonl и переключитесь на страницу Events (см. рис. 1.5). Она выглядит практически так же, как и страница Properties, за исключением того, что в левом столбце находятся на­звания возможных событий, а в правом - названия назначенных обработчиков. Проектируемое приложение должно реагировать на нажатие кнопки: событие OnClick.

Дважды щелкните в поле справа от этого события. Открылся ре­дактор кода. В коде произошли некоторые изменения по сравнению с тем, как он вьШIЯДел в момент создания нового приложения (см. рис. 1.2). Изменилось описание типа TF опn 1 ~ в нем добавилось объявление процедуры обработки нажатия кнопки:

procedure ButtonlClick(Sender: TObject);

В разделе implementation появился шаблон определения этой про­цедуры:

procedure TForml.ButtonlClick(Sender: TObject); beqin

end;

Курсор установлен в этом шаблоне, и сразу после перt·хf\Да в Ок­но редактора кода можно начинать писать текст обработчика. Помес­тите в шаблон следующую строку:

Labell.Caption :~ 'Hello World!';

Изначально поле Caption могло содержать какую-либо строку, например «Press the button!». Тогда эта строка находилась бы на фор­ме до нажатия кнопки.

Если, поставив точку после Label 1, вы ненадолго остановитесь, то появится подсказка, в которой будут перечислены все методы и

свойства объекта Labell. Если подсказка не появилась, например, курсор был перемещен от надписи и потом возвращен на нее, то на­

жатие Ctrl +Пробел вызовет эту же подсказку. Далее можно просто выбрать из списка нужный пункт. Напечатав две-три первые буквы нужного свойства или метода, можно ощутимо сократить количество пунктов в подсказке и, как следствие, время поиска нужного. С по­

мощью стрелок t и i выделите нужный пункт и нажмите Enter. Вы­бранный пункт автоматически будет записан после точки.

Запустите программу на выполнение, выбрав пункт меню Run ~ Run либо нажав быструю кнопку с зеленой стрелкой или F9. Если вы все сделали правильно, то на экране появится окно вашего приложения

(рис. 1.6 а), выглядящее практически так же, как и форма (отличить их проще всего по наличию сетки на форме и отсутствию ее в окне

- 15 -

Page 16: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

а б

Рис. 1.6. Окно программы «Hello World!»: а - до нажатия, б - после нажатия кнопки

работающей программы). Нажмите кнопку. На месте, где вы распо­ложили объект Labell, появилась надпись «Hello World!» без кавычек (рис. 1.6 б).

Закройте окно приложения, нажав крестик в углу либо выбрав пункт Run ~ Reset в меню. Второй способ очень полезен, если про­грамма зациклилась и нет возможности закрыть ее непосредственно

с формы. В остальных случаях к этому методу лучше не прибегать. Сохраните проект в отдельной папке.

В этой главе в общих чертах была рассмотрена среда программи­

рования Delphi. Это очень важный раздел, поскольку разработчик приложений в Delphi сталкивается с ней постоянно в ходе работы. Если сохранять каждый проект в отдельной папке, ваше приложение · можно будет легко переносить на другой компьютер, также будет

проще его удалить, если оно вам больше не нужно.

Контрольные упражнения

1. Допишите рассмотренную программу так, чтобы заголовок кнопки «Пуск!» по щелчку на ней заменялся на «Нажми еще!».

2. Измените настройки приложения таким образом, чтобы при его запуске на форме отображалась надпись «Привет!».

3. Поместите на форму еще несколько объектов. Сделайте так, чтобы все их заголовки изменялись при нажатии кнопки «Пуск!».

Page 17: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

rпава 2. Object Pascal

В предыдущей главе вами было написано приложение, выводящее одну надпись в диалоговом окне. При всей своей видимой простоте оно

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

ектов кнопки (Button) и метки (Label), отслеживание положения курсо­ра мыши, определение координат курсора, динамическое изменение

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

время работы программы. Применительно к данному приложению вся

работа программиста состояла в том, чтобы разместить два экземпляра компонентов из библиотеки VCL на форме и написать строку кода в ав­томатически созданной процедуре обработки события.

Рассмотрим теперь более подробно, как выглядят тексты кода созданного приложения. В общем случае проект состоит из несколь­ких файлов, которые, по умолчанию, имеют следующие имена:

Projectl .dpr - главный файл проекта.

Unitl .pas - файл, автоматически появляющийся в начале работы. Такой файл называется модулем и по умолчанию имеет имя Unit* .pas, где вместо звездочки ставится номер модуля в проекте. В модулях со­

храняется написанный программистом код, первоначальный вид кото­

рого можно увидеть на рис. 1.2. В примере приложения из предыдущей главы в модуль дописывался обработчик события. Таким образом, каж­

дой форме в приложении соответствует свой модуль с обработчиками событий, специфическими типами, переменными и подпрограммами. Однако могут существовать и модули, не привязанные к какой-либо

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

возможности математического аппарата Object Pascal (относительно скудные), поместить их в отдельный модуль (к примеру, math.pas) и использовать в других модулях по мере необходимости.

Unitl .dfm- файл, в который сохраняется информация о внешнем виде главной формы.

Projectl.res -· файл, содержащий иконку для проекта, тоже со­здается автоматически.

Projectl .opt (или Projectl .cfg в зависимости от версии Delphi) является текстовым файлом для сохранения установок, связанных

- 17 -

Page 18: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

с данным проектом. Например, в нем хранятся установленные вами директивы компилятора.

Все эти имена задаются автоматически для вновь создаваемого

проекта. Их можно и нужно изменить на что-то осмысленное в про­цессе работы над приложением и при его сохранении на диск.

После компиляции проекта появляются файлы с расширениями: .dcu- скомпилированные модули; .ехе - собственно исполняемый файл. Непосредственно код программы расположен в двух файлах: голов­

ном файле программы (расширение .dpr) и файле модуля (расшире­ние .pas). Головной файл проекта стоит полностью оставить на совести Delphi, так же как и файл с параметрами формы: если что-то надо будет в ней изменить, то лучше это сделать непосредственно из IDE.

Программист, как правило, участвует только в написании модулей проекта. Delphi создает заготовку модуля, включает в нее описание формы и всех объектов, на ней размещенных, обеспечивает связь с библиотеками и стандартными модулями. Программист в основном пишет обработчики событий компонентов и, при необходимости, объявляет различные переменные, задает значение констант, создает описание типов, вспомогательных функций и процедур.

Ниже приведен текст модуля нашего проекта. В комментариях указано, что и куда в этот текст может добавить программист.

unit Unitl; interf ace {список подключаемых модулей}

uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type TForml ~ class(TForm) //класс формы

Buttonl: TButton; Labell: TLabel; procedure ButtonlClick(Sender: TObject); private { Private declarations } {Объявление переменных и методов, включаемых в класс формы,

но недоступных напрямую для других классов, описанных вне

данного модуля проекта.}

puЬlic

{ PuЬlic declarations } {Объявление переменных и методов, включаемых в класс формы,

и доступных для других классов.}

end; - 18 -

Page 19: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 2. Object Pascal

var Forщl: TForrnl; // объект класса TForm - ваша форма

{Объявление типов, констант, переменных, функций и процедур,

доступных из других модулей проекта, но не включенных

в класс формы. } implementation //реализация модуля {$R *.dfrn} //ключи компилятора

{Предложения uses, объявления типов, констант, переменных,

к которым не будет доступа из других модулей. Тут же должны быть

реализации всех объявленных в разделе interf ace функций и процедур, а также могут быть реализации любых вспомогательных,

не объявленных ранее функций и процедур.}

procedure TForrnl.ButtonlClick(Sender: TObject); //обработчик нажатия кнопки

Ьegin

Labell.Caption .- 'Hello World!'; end; end.

Модуль начинается со слова unit, после которого пишется имя модуля, совпадающее с именем файла, в ко:rором был сохранен модуль, в данном случае: Unit1. Текст модуля состоит из двух разделов: interface -ин­терфейс модуля и implementation - реализация модуля. Все, что вы и Delphi поместите в первый раздел, может быть с учетом атрибутов видимости использовано другими модулями проекта. Размещенное в разделе implementation недоступно другим модулям проекта.

Зарезервированные слова private и puЫic определяют область ви­димости глобальнЬ1х переменных и подпрограмм. Подробнее о дирек­тивах puЫic, private и protected можно будет прочесть в главе 4.

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

Как видите, в текст модуля включены пояснения - комментарии.

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

Для того чтобы понять, как работает ваше приложение, рассмот­рим текст головного файла проекта Projectl .dpr:

proqram Projectl; uses

Forms, U n i t 1 i n 'U n i t 1 . р а s ' { F о rm 1 } ; {$R *.res}

- 19 -

Page 20: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

begin Application.Initialize; Application.CreateForm(TForrnl, Forml); Application.Run;

end.

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

Все. На этом линейная определенность в работе приложения за­канчивается. Что будет происходить дальше, решается на этапе рабо­ты программы, а не на этапе разработки. Эта особенность является

одной из характерных черт, присущих всем Windоws-приложениям: последовательность работы приложений в гораздо большей степени зависит от действий пользователя, нежели в программах, написанных

дляМS-DОS.

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

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

санньiх ему разработчиком, но это определенно будут уже не те же

· операции, что выполнялись при наборе текста. Таким образом, пользователь определяет, чем в данный момент

должна заниматься программа, и задает основные направления дей­

ствий. Каждое нажатие на клавиши клавиатуры, кнопки мыши, пере­

мещение мыши является системным событием, которое интерпрети­руется ядром Windows и превращается в сообщение, которое посту­пает к соответствующим объектам действующих проrрамм. Например,

щелчок левой кнопки мыши на кнопке Save в панели управления текстового редактора Превращается в сообщение, поступающее про­грамме Текстовый редактор. Там оно в свою очередь вызывает запуск определенной последовательности действий - процедуры (procedure ). И именно эта процедура содержит инструкции, которые будут выпол­няться программой.

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

- 20 -

Page 21: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Гnава 2. Objett Pascal

Рис. 2.1. Вид окна приложения «Две кнопки» сразу после запуска

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

Сложно? Запутанно? Только на первый взгляд, даже если вы име­ете опыт программирования на языках структурного программиро­

вания, таких как Pascal или С. На самом деле все довольно очевидно и прозрачно, и вы быстро освоитесь с такой особенностью програм­мирования под Windows. Важным здесь является то, что программы под Windows выполняются в последовательности, в общем случае не определенной на этапе разработки. Иногда такую программу назы­вают событийно~управляемой, а программирование, соответственно,

событийно-ориентированным. Рассмотрим еще один пример: окно приложения содержит две

кнопки (Buttonl, Button2) и метку (Labell) (рис. 2.1). Метка содержит число, которое увеличивается на 1 каждый раз, когда по:Льзователь нажимает одну кнопку, и обнуляется каждый раз, как пользователь нажимает вторую кнопку.

Для создания этого приложения нужно поместить на форму два объекта Button и объект Label, дать кнопкам осмысленные заголовки (Caption), а заголовку метки задать значение «0» (нуль). Затем нужно создать обработчики событий OnClick. Это можно сделать так же, как и в предыдущем примере, или просто двойным щелчком по самой

кнопке.

Примечание Двойной щелчок по объекту, расположенному на форме, вызывает диа­

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

событие OnClick.

- 21 -

Page 22: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

В шаблон обработчика нажатия первой кнопки нужно поместить строчку:

Labell.Caption := IntToStr(StrToint(Labell.Caption) + 1);

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

числом, нужно произвести преобразование текста в целое число. Этим

и занимается функция StrTolnt(). В качестве аргумента она принима­ет строку текста, которую затем анализирует на предмет возможнос­

ти интерпретации как числа, и, если строка содержит только разре­

шенные символы, сама функция приобретает значение, записанное

в этой строке, но уже как число, а не как текст. С результатом можно

выполнить арифметические операции (прибавить единицу). Функция lntToStr() производит обратное преобразование. Оно более простое, так как любое число может быть интерпретировано как текст, но, тем не менее, необходимое, поскольку свойству строкового типа может быть присвоено только строковое значение. О преобразовании типов будет подробнее рассказано в главе 3.

Теперь вы можете запустить приложение и опробовать кнопки

в работе. Если вы все правильно сделали, первая кнопка увеличива­

ет число на единицу, но вторая пока просто нажимается, не приводя

к каким-либо видимым изменениям. Завершите работу программы.

В шаблон обработчика нажатия второй кнопки нужно поместить строку:

Labell.Caption := '0';

Нуль здесь взят в апострофы, чтобы указать компилятору, что эту ве.Ji(ичину нужно рассматривать как строковые данные, а не как чис­

ло. Эта же строка без апострофов вызвала бы ошибку периода ком­пиляции с сообщением о несовместимости типов.

Мы рассмотрели довольно простую программу, отражающую, тем

не менее, принцип, о котором шла речь выше. Модуль проекта содержит

две процедуры: TForm1 .Button1 Click и TForm1 .Button2Click. Содержи­мое головного файла проекта с точностью до имен модуля и проекта такое же, как в предыдущем примере, т. е. определенность последова­

тельности действий заканчивается сразу после команды Application. Run. И до стадии функционирования проекта неизвестно, в каком по­рядке будут выполняться эти процедуры и будут ли выполнятся вооб­ще, ведь пользователю ничего не мешает просто закрыть приложение

сразу после запуска. Закрытие приложения, кстати, тоже событие, на которое программа может реагировать предопределенным образом.

- 22 -

Page 23: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 2. Object Pascal

Итак, механизм следующий: в приложение поступает сообщение

о возникновении определенного события с параметрами (где конк­

ретно, на каком объекте какого именно окна приложения произошло

это самое событие). По умолчанию вызывается стандартный систем­

ный обработчик этого события. Однако, если действий, выполняемых системным обработчиком события, недостаточно, а обычно так и

бывает, то разработчик определяет свою процедуру, вызываемую при возникновении конкретного события, - собственный обработчик.

Остановимся чуть подробнее на событиях. Код в рассмотренных

примерах довольно прост, и часто даже нет необходимости задумы­ваться о том, что написанная процедура обработчика является ответом

на сообщение о событии, посланное операционной системой. Но зачастую это знание оказывается весьма полезным. В сообщении помимо собственно уведомления о событиц передается и некоторая связанная с ним информация. Например, при возникновении события

«Нажата кнопка мыши» приложение получает координаты точки, в которой это произошло. Эти координаты могут быть использованы в обработчике события OnM01JseDown:

procedure TForml.FormMouseDown(Sender: TObject;

beqin

Button: TMouseButton; Shift: TShiftState; Х, У: Integer);

Canvas.TextOut(X, У, IntToStr(X) + ',' + IntToStr(Y)); end;

Результат работы такой программы может выглядеть, например,

так, как показано на рис. 2.2. Примечание

Для работы этого и следующего примера нужно создать новое при­

ложение и задать обработчики событий OnMouseDown и OnKeyDown формы.

Также можно создать обработчик для события OnKeyDown (на­жата клавиша клавиатуры), который будет реагировать на вводимую с клавиатуры информацию.

procedure TForml.FormKeyDown(Sender: TObject; var Кеу: Word; Shift: TShiftState);

begin ShowMessage(Chr(Key)); //вывод окна сообщения

end;

Пример работы этой программы показан на рис. 2.3.

- 23 -

Page 24: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Рис. 2.2. Результат работы процедуры OnMouseDown

Рис. 2.3. Результат нажатия кнопки G

Приведенные здесь примеры имели целью лишь продемонстри­

ровать особенности событийно-ориенгированного программирования и раскрыть суть понятия «событие». Сам процесс написания кода

обработчиков событий подробнее рассмотрен в следующих главах.

:Контрольное упражнение

Модифицируйте код второго приложения таким образом, чтобы при нажатии кнопки мыши выводилось сообщение, показывающее, в какой четверти окна приложения оно было произведено. Для опре­деления размеров окна приложения во время работы программы вос­пользуйтесь свойствами Width и Height формы.

Page 25: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

rпава 3. Уч1мс1 nроrрамм1ровать

В настоящей главе более подробно рассмотрены базовые понятия язык~.программирования, используемого в Delphi: Object Pascal. Тем, кто занимался программированием на Pascal, можно эту главу пропус­тить. Тем, кто программировал на каких-либо других языках, стоит бегло ее просмотреть, обращая внимание на примеры, для того чтобы освоить синтаксис языка. В основном же эта глава для тех, кто не име­

ет или почти не имеет опыта написания собственных программ.

Как и любой язык, язык программирования начинать изучать луч­ше с алфавита. Алфавит языка Pascal включает буквы, цифры, специ­альные символы и пробелы. Буквы языка- латинские буквы от 'а' до 'z' и от 'А' до 'Z ', сюда же относят и знак подчеркивания _. Различий между прописными и строчными буквами нет (MyVar, МYVAR и даже m Yv AR компилятор воспримет как имя одного и того же объекта, однако первый вариант читается лучше, и использование подобного

шаблона говорит о более высоком профессионализме разработчика). Специальные символы языка следующие:

t-*/=, .' ':;<>[]{}()А@$#

К специальным символам относят также некоторые пары символов,

а именно:

<> <= >= := (~ *)

При компиляции проекта эти пары символов воспринимаются как

одно целое, если они не разделены пробелами. Переменная~ одно из базовых понятий языка программирования.

Под переменной понимают ячейку памяти, соответствующую опре­

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

мера в доступном сегменте и поставить имя переменной в соответст­

вие данной области. В дальнейшем с переменной в зависимости от

ее типа можно выполнять те или иные операции (математические, логические и т. д. ). Например, строка кода

а := 4;

поместит в переменную а число 4 (символ := является командой при­сваивания, т. е. переменной, стоящей в левой части выражения, будет

присвоен результат выражения, расположенного справа от знака при­

сваивания). Именно так и следует воспринимать работу с перемен-

- 25 -

Page 26: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

ными. Программисту, как правило, нет необходимости помнить

о структуре памяти и способе хранения переменных в ней. Наряду с переменными существует еще один способ хранения, при­

меняемый для констант - данных, которые не должны быть изменены

в ходе работы программы. Описываются они следующим образом:

const <Name> = <Value>;

Значение константы может быть задано либо непосредственно, либо

как выражение с участием других констант, значение которых известно

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

ласть их видимости ограничивается данным модулем проекта:

type TForml = class(TForm) {описание свойств и методов класса}

private {Private declarations)

puЬlic

{PuЬlic declarations} end; const

Minimum = О; Maximum = 100; Middle = (Maximurn - Minirnum) div 2; CharsCount = Ord('Z') - Ord('A') + 1;

var

В приведенном примере показано, что в выражениях, описывающих константы, могут применяться операторы и функции языка.

Тип константы подбирается автоматически. Если выражение пред­ставляет собой строку символов, то принимается строковый тип

String, если длина строки при этом равна 1, то принимается символь­ный тип Char. Если переменная представляет собой дробное число, то тип интерпретируется как Extended. Если же значение представ­лено целым числом, то принимается один из целочисленных типов,

минимальный из возможных по размеру занимаемой памяти. (Под­

робности можно посмотреть в Help на закладке, посвященной настоя­щим константам: true constants.)

Ввиду того что существуют «настоящие константы» (true constants ), должны существовать и «не настоящие». Однако бесполезно искать в справке материалы по false constant, поскольку вторым видом констант являются типизированные константы (typed constants ). Отличаются

- 26 -

Page 27: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 3. Учимся программировать

они тем, что могут, в отличие от настоящих, содержать массивы, запи­

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

щих значение других констант. Другой их особенностью является то,

что при установке ключа компилятора {$J+} они начинают вести себя как обычные переменные с начальным значением. По умолчанию задан ключ компилятора { $J-}, при котором типизированные константы ведут себя как переменные, доступные только для чтения. Ключи компиля­

тора записываются сразу после зарезервированного слова implementation или в файле конфигурации проекта (см. начало главы 2).

Задается типизированная константа практически так же, как настоя­

щая, но с указанием типа:

const <Name>: <Туре> = <Value>;

Например, конструкция

const Min = 2; Мах: Integer = Min + 2;

окажется верной, а вот такая:

const Мах: Integer = 2; Middle: Integer = Мах - 6;

вызовет ошибку.

Переменная и константа могут содержать целые числа, дробные числа, строку текста или отдельный символ, могут даже принимать зна­

чение true или false для логических переменных. Однако вся информация хранится в памяти компьютера только как последовательность нулей и

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

тип переменной. Также тип переменной определяет ра3мер ячейки па­

мяти (в байтах или битах), в которой расположено значение переменной. Рассмотрим наиболее часто используемые типы.

3.1. Типы данных Целочисленные типы переменных предназначены для хранения

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

та (сложение, умножение, вычитание, взятие остатка от деления,

частного от такого деления и т. д.). Существует около 10 цело­численных типов. Наиболее часто применяемые приведены в табл. 3 .1.

- 27 -

Page 28: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Таблица 3.1

Тип Диапазон значений Размер, байт Наличие знака

lnteger -2 147 483 648 ... 2 147 483 647 4 Знаковый

lnt64 -2вз."26з -1 в Знаковый

Byte 0 ... 255 1 Беззнаковый

Word 0."65 535 2 Беззнаковый

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

Объем памяти, отводимый под хранение данных, определяет мак­

симальное по модулю число, которое можно записать в эту перемен­

ную.

Целочисленным переменным можно присваивать как десятичные,

так и шестнадцатеричные числа. Для этого перед шестнадцатеричным

числом нужно поставить$. Например:

var i, j: Integer; beqin

1 :"'° 125; j := $70; {В шестнадцатеричном представлении это число

эквивалентно 125 в десятичном.}

end;

В примере сначала в переменную i помещается десятичное число 125, а потом в переменную j помещается то же самое число, но в шестнадцатеричном представлении. Так как компьютеру все равно,

в какой системе счисления (десятичной или шестнадцатеричной)

записана константа в выражении, то содержимое переменных по

завершении программы будет одинаково.

Вещественные, или дробные, типы данных предназначены для

хранения чисел с плавающей точкой. Они используются в математиче­

ских оnераЦиях. В .каждом конкретном случае программист опреде­ляет, каким типом переменных пользоваться. Целочисленные пере­

менные отнимают у процессора меньше времени и требуют меньше памяти, чем вещественные. Поэтому использовать вещественные пе­

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

они только размером в байтах. Все типы знаковые, в табл. 3 .2 приве­дены наиболее распространенные из них.

- 28 -

Page 29: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 3. Учимся проrраммировать

Таблица 3.2

Тип Диапазон значений Максимальное количество

Размер, байт цифр в числе

Real 5,0· 1о-324 ••. 1,7-10308 15-16 8 Single 1,5· 10-45 •.• 3,4-1038 7-8 4

DouЫe 5,О· 10-324 .•• 1, 7.1 озоs 15-16 8

Extended з,5.1 о-4951 ... 1, 1.1 о4эз2 19-20 10

Принципиально, что дробные и целые числа, равные по величине, не эквивалентны.

var i: Integer; j: Real;

beqin i := 10; ] := 10;

end;

Несмотря на то, что в переменные i и j помещается одно и то же значение, переменная i содержит чис_ло 1 О, а переменная j - число 10,0. Чтобы сделать эти переменные эквивалентными, нужно округ­лить значение J.

Символьные переменные интерпретируют содержимое памяти

как текст. Символьные данные - это цепочка чисел, каждое из ко­

торых представляет собой порядковый номер символа в специальной

таблице. -В Windows используется таблица ANSI. Delphi берет эту таблицу прямо из операционной системы, так что количество симво­лов и их расположение зависит от ОС. В таблице ANSI хранятся, наряду со спецсимволами, только русский и английский алфавиты. Однако алфавитов, как и языков на Земле, куда больше двух. Из этих

соображений ввели поддержку UNICODE (16-битная таблица). В ней первые 256 значений совпадают с таблицей ANSI, а остальные явля­ются специфичными. Для поддержки lТNICODE в Delphi введен тип

· WideString. Используемые в Delphi основные строковые типы представлены

в табл. 3.3. Таблица 3.3

Тип Максимальная длина Примечание

ShortString 255 символов -AnsiString 231 символов ANSI

WideString 230 символов UNICODE

- 29 -

Page 30: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Также, для обеспечения совместимости с более ранними версия­ми, существует тип String. Именно он используется в примерах кни­ги, где необходимы переменные строкового типа:

va:r

Str: String;

beqin Str . - 'Hello ! ' ;

end;

Возможно также указание длины строки при объявлении пере­

менной:

va:r

S: String[100];

Число 100 в квадратных скобках после типа String показывает мак­симальное количество символов в строке. Строку можно рассматри­вать как последовательность переменных символьного типа, работать можно либо со строкой целиком, либо с конкретным символом, для этого нужно указать номер символа, к которому необходимо обра­титься:

S : = 'Hello ! ! ! ' ; S[l] :== 'S';

Теперь в переменной S содержится строка «Hello! ! 1>> без кавычек. Нумерация элементов в строке начинается с единицы. Существу­

ет и нулевой символ, но к нему не рекомендуется обращаться напря­мую. Он содержит в себе длину строки, и для того, чтобы прочесть или записать его значение, существуют функция Length и процедура SetLength соответственно.

Логический, или Булев, тип (по аналогии с булевой алгеброй, оперирующей логическими выражениями). Физически переменные

этого типа занимают один бит и, как следствие, могут принимать

лишь два значения: О или 1. Для удобства программирования эти значения заменены на false (Ложь) и true (Истина), соответственно. Переменные логического типа применяются при составлении логи­

ческих выражений, которые подробно будут рассмотрены ниже, здесь приводится лишь краткий пример:

var bull: Boolean; // Объявить логическую переменную bull i: Integer; //и целочисленную переменную -

- 30 -

Page 31: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

begin bull .- true; i : = 5;

if bull = true then i := 1

else i . - о;

end;

Глава 3. Учимся программировать

При выполнении программы в переменную i сначала будет помеще­но число 5, а затем, поскольку выполнено условие равенства логи­ческой переменной bull значению true, - число 1.

Такая формулировка условного оператора ifнe единственная и не

самая лаконичная, зато самая очевидная, подробнее этот вопрос будет

рассмотрен ниже в настоящей главе.

Тип список создается программистом. Переменная этого типа

может принимать только одно из оговоренных значений. В чем-то это

похоже на логический тип, переменные которого принимают только

два значения. Описание типа происходит следующим образом:

type typeName = (vall, ... , valn);

Например:

type TSound = (Click, Clack, Clock);

Переменная задается так же, как и переменная любого другого

типа:

var FirstSound:TSound;

Тип диапазон является усечением какого-либо существующего

простого типа, кроме вещественного. Диапазон задается указанием

нижней и верхней границ:

type <TypeName> = Low .. Hi;

Например:

type SomeNumbers = -128 .. 127; Caps = 'А' .. 'Z';

Переменные типа «диапазон» можно создавать в разделе объяв­ления переменных без предварительного создания самого типа.

var SomeNum: 1 .. 500;

- 31 -

Page 32: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: проrраммирование с нуля

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

type Percentile ~ 0 .. 99; var i: Percentile;

i 100;

приведет к ошибке совместимости типов.

Функции преобразования типов

Часто при использовании данных возникает необходимость из­менить их тип: округлить, изменить основание системы счисления,

перевести данные из строкового типа в вещественный, из логичес­

кого в строковый.

Такая необходимость возникает из-за того, что типы отличаются друг от друга объемом занимаемой памяти, а большинство команд принимают в качестве параметров только значения вполне опреде­

ленного типа. В случае несоответствия типов формальных и факти­ческих параметров подпрограмм компилятор выдает сообщение об ошибке. Как правило, этого можно избежать, если использовать ко­манды преобразования типов. В Delphi их содержится несколько десятков. Наиболее часто применяемые приведены ниже.

function StrToint(const S: Strinq): r;

преобразует строку S, в которую записано целое число, в целочис­ленный тип.

function StrToBool(const S: String): Boolean;

возвращает true, если в S содержится число не равное нулю или слово 'TRUE'; false возвращается, если в S содержится 'О' или 'FALSE'. Во всех остальных случаях функция возвращает сообщение об ошибке.

function St~ToFloat(const S: Strinq): Extended;

преобразует строку S в вещественное число. Строка должна содер­жать знак, цифры и десятичный разделитель в порядке, характерном для записи десятичных дробей. Также строка может содержать ман­

тиссу, состоящую из знака, буквы е (Е) и целого числа. Пробелы в начале и в конце строки игнорируются. Если S имеет другой формат, функция возвращает сообщение об ошибке.

- 32 -

Page 33: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава З. Учимся программировать

Наравне с этими функциями существуют функции обратного пре­

образования:

function IntToStr(Value: Integer): Strin9; function BoolToStr(B: Boolean): String; function FloatToStr(Value: Extended): String;

3.2. Выражения, операторы и операнды После рассмотрения типов переменных, наиболее часто исполь­

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

торую и предстоит писать программисту (остальное пока стоит пре­доставить выполнять IDE).

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

купность данных (операндов) и символов действий, которые предпи­

сывается с этими данными выполнить (сложить, вычесть, умножить

и т. д. ), - операторов. Например, выражение

ь + с

предписывает сложить переменные Ь и с. В данном случае Ь и с явля­

ются операндами, а знак«+» является оператором. Результат работы этого выражения может быть включен в качестве операнда в другое

выражение, например в выражение с оператором присваивания:

а := Ь + с

Порядок выполнения операций в подобных выражениях аналоги­

чен принятому в математике. Например, в выражениях с операторами

присваивания сама операция присваивания выполняется последней

после того, как выполнены все остальные операции, находящиеся

справа от оператора :=. Слева от этого оператора должна находиться переменная соответствующего типа, в которую помещается результат

вычислений.

Еще одним показ,ательным примером операторов является услов­

ный оператор, примеры которого встречались выше. Если перевести

его составляющие дословно, получится следующая конструкция:

ЕСЛИ (выражение) ТО (действия)

IF (expression) THEN (statements)

- 33 -

Page 34: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi:· программирование с нуля

Подробное описание условного оператора приведено ниже в этой же главе.

3.3. 11роцедуры и функции Важным в программировании является понятие подпрограммы.

Подпрограммы используются в языках программирования с целью

уменьшения трудоемкости написания программ путем многократно­

го использования одного и того же фрагмента кода с возможностью передачи в него перед выполнением различных значений исходных

данных. Подпрограммы в Object Pascal делятся на две группы: функ­ции и процедуры.

Функции (function) выполняют предписанные им действия по пре­образованию исходных данных и изменению параметров работы при­ложения и принимают некое значение в результате своей работы ·таким

образом, что функции можно применять в математических выражениях, логических операторах илй в качестве аргументов при вызове других

подпрограмм. Говорят, что функция «возвращаеп> некое значение.

Процедуры (procedure) отличаются от функций только тем, что не могут принимать значения.

Все обработчики событий в Delphi представляют собой процеду­ры. Программист пишет в основном именно их, поэтому под термином

«подпрограмма» будем понимать именно процедуру или функцию,

которую программист пишет в модуле (unit) проекта. Так как, собст­венно говоря, код самого приложения находится в головном файле

проекта и «пишется» IDE. При описании заголовки процедур и функций выглядят следую­

щим образом:

procedure <РrосNаmе>(<список формальных параметров>); function <FuncName>(<cпиcoк формальных параметров>):

<тип возвращаемого результата>;

При вызове подпрограммы записывается только ее имя и список

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

Формальными называются параметры, которые заданы при опи­

сании подпрограммы, они не имеют конкретного значения, но при­

надлежат к определенному типу. В процессе описания подпрограммы

они могут быть использованы в выражениях в качестве имен перемен­

ных. Сами же значения переменных будут подставлены на их место

при вызове подпрограммы, когда список формальных параметров

будет заменен списком фактических параметров.

- 34 -

Page 35: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 3. Учимся nроrраммировать

Список формальных параметров может содержать зарезервиро­ванные слова const и var. Например:

procedure MyProc(Vall: Real; var Val2: Real; ValЗ: Boolean; const Val4: I r; Val5:Real);

В этом примере Val 1, ValЗ и Val5 обычные переменные. Изме-нение их в пределах процедуры MyProc не вызовет изменений пере­менных, которые были использованы в качестве фактических пара­метров при вызове, поскольку при вызове в подпрограмму передается

копия значения. Val2 - изменяемая переменная, при таком определе­нии в подпрограмму передается не значение параметра, а адрес его

расположения в памяти. Как следствие, любые изменения с формаль­ным параметром в процедуре MyProc сказываются на переменной, использованной в качестве фактического параметра при вызове. Val4 -константа. Механизм передачи значения здесь тот же, что и в преды­

дущем случае, однако попытка изменить значение формального пара­метра вызовет ошибку.

Второй вариант отличается от первого тем, что передача адреса

происходит быстрее, чем передача самого значения, если речь идет

не о простой переменной, а, например, о массиве.

Несколько слов об области видимости переменных. Переменные в Delphi могут быть локальными или· глобальными. Глобальные пере­менные объявляются после слова var в разделе interface. Они доступ­ны во всех процедурах и функциях модуля, а видимость их в других модулях зависит от того, в каком разделе (private или puЫic) они объ­явлены. Локальные переменные объявляются после слова var в под­программе. Такие переменные видимы только в пределах данной под­

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

и ;_это не вызовет проблем в работе. Например, для счетчика циклов

в примерах данной книги используется, как правило, переменная i: Integer. Такая переменная может быть объявлена в нескольких подпро­граммах (локальная) и в разделе interface (глобальная). В тех подпро­граммах, где нет собственного описания переменной i, при ее упоми­нании будет подразумеваться глобальная переменная, а в тех, где такое

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

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

этого порядка исполнения создаются циклами и условными операто­

рами с участием операторных скобок. Простой оператор представля­

ет собой вызов подпрограммы, написанной самим разработчиком

35 -

Page 36: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphl: nроrраммирование с нуля

приложения или входящей в стандартные модули поставки Borland Delphi, либо математический оператор:

а : 1; / / математический оператор

Ь :=а + 6; // математический оператор Pow(z, а, 3); //вызов процедуры с участием параметров z 1 а, 3 с Sqrt(4); {Взятие квадратного корня из четырех и помещение

результата в переменную с.}

Последовательность операторов может расцениваться как один составной оператор, если они взяты в так называемые операторные

скобки:

begin

end;

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

Object Pascal поддерживает основные математические операции. Это реализовано в виде операторов (в математическом смысле) и функций, возвращающих вычисленцое значение. Операторы:

а + Ь 11 Сложение, а - ь 11 вычитание, а * ь 11 умножение, а / ь 11 деление,

а mod Ь 11 взятие остатка от деления а на Ь,

а div Ь //целая часть частного от деления а на Ь.

Функций куда больше, вот лишь некоторые из них:

Sqrt(a} //Взятие квадратного корня из а,

Sqr(a) // возведение а в квадрат,

Abs(a) //модуль а,

Ехр(а) // экспонента а,

Ln(a) //натуральный логарифм а.

Набор функций, поддерживаемых математическим аппаратсiм Delphi, можно найти в Help.

3.4. Масс1вы До сих пор рассматривались переменные, содержащие в каждый

момент времени только одно значение, это не всегда удобно. Для

- 36 -

Page 37: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 3. Учимся nроrраммировать

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

<Имя массива>: аrrау[<нижний индекс> .. <верхний индекс>] of <тип данных>;

Например:

MyArray: array[l .. 1001 of Integer;

Описывать можно не только одномерные массивы. Существует возможность также задавать многомерные массивы (массивы из мас­

сивов):

MyArrayl: array[б .. 12, 1 .. 8] of Real;

Использование многомерных массивов очень удобно при работе с матрицами. Обращение происходит к каждому элементу в отде­льности по его индексу в массиве, например:

MyArray[l] := 4; MyArray[15) :"' 8; MyArray1[7,8] := MyArray{7];

Можно также присваивать один массив другому, если они экви­

валентны по размеру и типу элементов. Например:

procedure TForml.FormActivate{Sender: TObject); var А, В: array[l .. 10] of Integer;

Bl: array[l .. 11] of Integer; С: array[l .. 2, 1"10] of Integer; i: Integer;

be9in for i := 1 to 10 do

A[i] :"" i; В :=А; //корректно

Bl :=А; //не корректно

С[2] :~В; //не корректно

end;

При задании индексов во время обращения к элементам массива нужно следить за тем, чтобы значение индекса находилось в заданных цределах. Выход за пределы вызовет ошибку периода выполнения. Впрочем, если установлена опция Range checking на странице Compiler диалога Project Options, то за соблюдением этого условия будет следить компилятор.

- 37 -

Page 38: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

3.5. ЦllКJIЫ Работа с массивами немыслима без циклов. Если представить,

что в массиве несколько сотен элементов и обращение к каждому из

них придется описывать вручную (как правило, такие обращения

в программах происходят по много раз по мере изменения данных в

массиве), то сразу возникают сомнения в необходимости написания приложения. Цикл, как следует из его названия, - это способ орга­низации повторного использования одного и того же участка кода.

Повторяться этот участок может заданное число раз или до выпол­

нения поставленного условия.

Существует несколько вариантов цикла. Цикл for предназначен для выполнения оператора (простого или составного) заданное чис­

ло раз. Фактически этот цикл является счетным механизмом. Он изменяет переменную-счетчик от нижнего значения до верхнего с

шагом в единицу и, когда переменная достигнет верхнего предела,

заканчивает выполнение оператора и передает управление следующе­

му за ним участку кода.

for i := 1 to 20 do MyArray(i] ::= 1;

Такой цикл запишет единицы в первые 20 элементов массива MyArray.

Циклы также полезны при выполнении любых повторяющихся операций, например, вычисления факториала числа или суммы всех чисел от одного значения до другого:

var , i, sum: Integer;

begin fact : == 1; sum : О;

for i := 1 to 7 do beqin

surn end;

end;

:= fact * i; sum + i;

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

- 38 -

Page 39: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 3. Учимся программировать

рации. Вот только изменять ее в теле цикла нужно осторожно. Если

ошибиться в преобразованиях переменной-счетчика, то цикл может

выполняться не предусмотренное количество раз. Например, может

выполниться только один раз, в ходе которого переменная-счетчик

выйдет за пределы установленного диапазона. Другой вариант~ вы­

полнение цикла бесконечное число раз - возникает в ситуации, ког­

да переменная-счетчик изменяется в теле цикла таким образом, что

постоянно остается в заданном диапазоне, несмотря на ее изменение

самим циклом.

В приведенном выше примере цикл увеличивает значение пере­

менной-счетчика. Возможен вариант, когда цикл уменьшает это зна­

чение с каждой итерацией. Описывается он следующим образом:

for i := 20 downto 1 do beqin

end;

Иногда, чаще всего при работе с файлами, возникает ситуация,

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

решении математических задач методом последовательного прибли­

жения с заранее заданной погрешностью. В таком случае, как прави­

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

с пост- и предусловием.

Цикл с предусловием вида

while i > О do beqin

end;

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

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

встрече цикла Delphi проверяет условие и, если оно истинно, исполня­ет последуК?щие операторы. Затем снова возвращается к предусловию, и история повторяется. Если же условие ложно в самый первый раз, то

возникает ситуация, когда цикл не выполнится ни разу. Этот вариант

имеет право на существование, поскольку возможно, что алгоритм тре­

бует такого положения вещей. Рассмотрим пример:

- 39 -

Page 40: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

while not EoF(pf) do beqin

end;

Данный цикл производит некие действия до тех пор, пока не будет

достигнут указатель на конец файла, связанного с переменной pf. Это может быть чтение строк и помещение их в массив, могут быть ма­тематические операции и т. д.

Иногда более удобной формой является цикл с постусловием. Он записывается следующим образом:

repeat

until eps < 0,001;

Такой цикл будет исполняться до тех пор, пока не выполнится ус­

ловие, стоящее после слова until. Если перевести операторы этих циклов с английского на русский, то будет гораздо проще запомнить,

какой из них как работает. Так, цикл с предусловием в переведенном варианте выглядит как:

ПОКА [выполняется условие] ДЕЛАТЬ

НАЧАЛО

КОНЕЦ;

А цикл с постусловием:

ПОВТОРЯТЬ

ДО ТЕХ ПОР ПОКА [не выполняется условие];

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

входящих в условие завершения выполнения цикла, цикл выполнит­

ся хотя бы один раз. Это происходит потому, что Delphi сначала вы­полняет все операторы, находящиеся между repeat и until, а затем проверяет условие завершения. Если оно не выполняется, то проис­

ходит возврат к первому после repeat оператору и все повторяется еще раз. Как правило, каждая следующая итерация приводит к изме­

нению переменных, входящих в условие завершения работы цикла.

Если этого не происходит, то последовательность операторов между

repeat и until будет повторяться до тех пор, пока не будет остановле­на каким-либо еще образом.

- 40 -

Page 41: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 3. Учимс.я nроrраммировать

Однако и здесь Delphi предоставляет программисту дополнитель­ную степень свободы в виде команд управления ходом выполнения цикла.

Вот основные из них:

• Continue - вызывает прекращение данной итерации цикла и пе­

реход к началу выполнения следующей итерации.

• Break вызывает прекращение работы цикла и передачу уп-равления к следующим за ним операторам.

• Exit - выход из текущей процедуры.

Зачастую можно видеть в программах бесконечные циклы с пост­или предусловием, которые завершаются именно по оператору break. Такой вариант поведения программы полезен, когда условие прекраще~ ния цикла относительно сложное или когда выход из цикла возможен

в нескольких точках его выполнения. Примеры бесконечного цикла:

while 4 > 3 do beqin

end; repeat

until 4 3;

В теле таких циклов должна находиться хотя бы одна конструкция

вида

if <условие> then beqin

break; end;

3.6. Vсповныi оператор Условиые операторы используются для выбора исполнения од­

ного из возможных действий в завщ:;имости от некоторого условия.

В общем виде условный оператор выглядит так:

if <логическое выражение> then begin

end;

- 41 -

Page 42: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Например:

if j > 13 then beqin

] :=о 12;

х := 0.8;

end;

В данном примере операторы, заключенные в скобки begin ... end, выполнятся только в том случае, если выполнено условие j > 13. Если условие не выполняется, то оператор пропускается, и управление

передается следующим после него операторам.

Возможен более сложный вариант условного оператора:

if <логическое выражение> then begin

{операторы 1} end

else begin

{операторы 2} end;

В этом примере если условие выполняется, то исполняются {опера­

торы 1}, а {операторы 2} пропускаются. Если условие не выполняет­ся, то наоборот, исполняются только {операторы 2}.

Затронем вопрос, относящийся к выполнению или невыполнению

логических условий. Логическое выражение может принимать толь­

ко два значения: true или false. Здесь действуют правила булевой. алгебры. Если приведенное в выражении условие выполняется, то

выражение в целом получает значение true. В случае

if tr.ue then ...

условный оператор будет всегда выполняться вне зависимости от

внешних условий. Соответственно в случае

if f alse then ...

условный оператор не будет выполнен ни при каких значениях пере­менных программы.

Можно вычислить значение логического выражения заранее и в ус­

ловие подставить только одну переменную, например:

var IsOK: Boolean; i: Integer;

- 42 -

Page 43: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

beqin

IsOK : == i > 1;

if IsOK then ShowMessage('true');

end;

Глава 3. Учимся проrраммировать

Логическая переменная IsOK примет выражение true или false в за­висимости от истинности логического выражения в правой части

оператора присваивания, и сообщение будет выдано или нет в соот­ветствии со значением этой переменной.

До сих пор в примерах приводились только простые условия.

Возможно также задание комплексных условий. Например, истин­ность выражения

IsIN := (а > 0) and (а < 10);

покажет, что значение переменной а больше О и меньше 1 О одновре­менно.

В табл. 3 .4 приведены логические операторы Delphi и их значения в зависимости от значений операндов. Все эти логические операторы

могут комбинироваться в соответствии с правилами булевой алгебры. Например, вполне имеет право на существование следующая кон­

~трукция:

IsOK := ((а> 1) and (Ь < 3)) or ((с> 3) xor (d > 6) xor (f < 0)) or ((t < z) and {not IsEmpty));

Таблица 3.4

Оператор Логическаsч операция х у Результат Пример

notX НЕ

XandY и false

true

true

false

XorY или false

true

true

false

XxorY Исключающее ИЛИ false

true

true

- 43 -

false

true

false

true

false

true

false

true

false

true

false

true

true

false

false

false

false

true

false

true

false

true

true

false

notC

(а>2) and (Ь<с)

{а>2) or

(Ь<с)

(а>2) xor (Ь<с)

Page 44: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Разумеется, все эти переменные и условия составлены случайным

образом, но в целом пример демонстрирует возможную комбинацию.

Нужно очень внимательно следить за правильностью составления

таких выражений, обращая внимание на значение выражения в целом. Если будут нарушены правила синтаксиса Object Pascal, то' компиля­тор выдаст предупреждение или ошибку, а вот если где-то будет пос­

тавлен неверный знак или логический оператор, то приложение на­

чнет работу, но делать будет совсем не то, что ожидает программист.

Если выражение скомбинировано из трех и более условий, то, воз­можно, стоит составить таблицу истинности, где будут просмотрены

все возможные варианты состояния переменных, входящих в условия,

и соответствующее этим параметрам значение выражения.

К условным операторам относится и оператор выбора. Он запи­сывается следующим образом:

Case <имя переменной> of <1-е значени'е>: <выполняемые действия>

<2-е значение>: <выполняемые действия>

<n-e значение>: <выполняемые действия> else <выполняемые действия>

end;

Выполняется только тот оператор (или группа, заключенная в опе­

раторные скобки), который стоит после значения, совпадающего с

текущим значением указанной после слова Case переменной. Если текущего значения переменной нет в списке, то будет выполнена по­следовательность действий, расположенная после слова else. Блок else может отсутствовать, тогда никаких действий выполнено не будет, и работа программы продолжится со следующей после окончания опе­

ратора выбора строки. Если необходимо, чтобы выполнялось несколь­ко операторов, используются операторные скобки begin ... end.

В качестве переменной выбора может выступать переменная лю­бого из следующих типов (в подсказке Delphi они носят название ordinal types): Integer, Char, Boolean, - а также списков и диапазонов.

Например:

Case s of 1: begin

ShowMessage('Яблoкo');

ShowMessage(' Зеленое'); end;

- 44 -

Page 45: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

2 .. 4: ShowMessage('Гpyшa');

5: ShowMessage{'Aneльcин');

6, 7: ShowMessage('Дыня'); else · Ьegin

ShowMessage('Coчный');

ShowMessage (' Арбуз'); end;

end;

Глава 3. Учимся программировать

В этом примере текст вьщаваемого сообщения будет зависеть от того,

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

3.7. Фун1q11 дnи раliоты с текстом В заключение рассмотрим некоторые функции для работы со стро­

ками. В стандартной поставке Borland Delphi 6.0 содержится около 70 функций для работы со строками, поэтому здесь рассмотрим толь­ко несколько наиболее полезных и часто используемых. Информацию об остальных, если они понадобятся, можно почерпнуть во встроен­ной справке.

Как правило~ работа со строками заключается в преобразовании содержимого строки или преобразовании ее типа. Первая часть со­стоит в поиске каких-либо символов или их последовательностей в строке, их замене или удалении, в объединении или сравнении двух строк. Вторая часть сводится к преобразованию вводимой пользова­телем текстовой информации в данные того типа, который соответст­вует поставленной задаче (см. раздел 3 .1 ).

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

однако стоит это сделать пару раз с целью накопления опыта напи­

сания программ на Delphi. Ниже рассматриваются некоторые простые примеры работы со строками в Delphi.

function CompareStr(const Sl, S2: String): Integer; function CompareText(const Sl, S2: Stringi: Integer;

Эти функции сравнивают строки S 1 и S2. Первая функция обращает внимание на регистр букв, а вторая - нет. Сравнение происходит

- 45 -

Page 46: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

посимвольно: берется первый символ из каждой строки. Если сим­

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

лы одинаковые, то берется следующий символ из каждой строки, и

операция повторяется. Таким образом, если функция вернула отри­цательное значение, то первая строка считается «меньше» второй.

А точнее, в первой различающейся символьной паре символ первой

строки имеет код меньший, чем код соответствующего символа вто­

рой строки, на модуль значения функции. Аналогичная ситуация,

если функция вернула поло~ительное значение. Рассмотрим следующий пример:

procedure TForml.?ormActivate(Sender: TObject); var Sl, S2: String; beqin

Sl : 'abcdefgh'; 82 : = ' fh, ;

ShowMes (IntToStr (CompareStr {Sl, S2))); end;

В данном случае сразу после запуска будет выдано сообщение «-1». Поэкспериментируйте со значениями Sl и S2, чтобы лучше понять

работу данных функций. Попробуйте заменить какую-нибудь малень­кую букву большой, использовать регистронезависимый вариант функции.

function Length(S): Integer;

возвращает количество символов в строке. Например, при описании

строкового типа с указанием максимальной длины результатом дан­

ной функции будет именно число символов.

Подпрограмма

procedure TForml.ForrnActivate(Sender: TObject); var Sl: String[20]; beqin

Sl := 'abcdefgh'; ShowMessage(IntT tr(Length(Sl)));

end;

выдаст сообщение «8», а не «20». Функция

function Copy(S: String; Index, Count: Integer): String;

- 46 -

Page 47: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 3. Учимся программировать

возвращает в качестве своего значения фрагмент строки S длиной Count, начиная с символа S[Index]. Например:

procedure TForml.FormActivate(Sender: TObject)i var Sl: String[20]; beqin

Sl := 'abcdefgh'; ShowMessage(Copy(sl, 3, 3));

end;

вернет в сообщении «cde». Если Index больше, чем длина строки, то функция возвращает пустую строку.

procedure Delete(var S: String; Index, Count: IntegerJ;

удаляет подстроку из Count символов в строке S, начиная с символа S[Index]. Delete - процедура, соответственно результат не может быть возвращен в виде значения самой Delete. В данном случае из­меняется содержимое переменной S. В этом можно убедиться на примере:

procedure TForrnl.FormActivate(Sender: TObject); var Sl: String[20]; begin

Sl := 'abcdefgh'; Delete(sl, 2, 2); ShowMessage(Sl);

end;

Очевидно, что если в данном случае Index больше количества сим­волов в строке, то никаких изменений со строкой. не произойдет.

procedure Insert(Source: String; var S: String; Index: Integer);

вставляет строку Source в строку S между символами S[lndex-1] и S[Index]. Если lndex меньше 1, то он принимается равным 1. (Вы, конечно, помните, что нумерация символов в строке начинается с 1 ?)

procedure TForml.FormActivate(Sender: TObject); var Sl, S2: String[20]; begin

Sl :== 'abcdefgh'; S2 :== 'xyz'; Insert(S2, Sl, 3); ShowMessage(Sl);

end;

- 47 -

Page 48: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: nроrраммирование с нуля

В этом примере можно вставить пустую строку (S2 := '' ;), тогда про­цедура Insert не сделает ничего и в сообщении будет только первона­чальный вариант строки S 1.

function IsDelimi ter (const Del' , S: String; Index: Integer) : Boolean;

Эта функция используется для определения того, является ли символ S[Index] равным одному из символов строки Delimiters. Как следует из названия функции, предполагалось, что она будет использоваться для поиска разделителей: запятых, пробелов, точек и т. д. Но из при­мера, приведенного ниже, видно, что с тем же успехом эту функцию можно использовать для поиска любых других символов:

procedure TForml.Form.Activate(Sender: TObj ); var Sl, 52: String[20J; begin

Sl : 'abcdefgh'; ShowMessage(BoolToStr (IsDelimiter('d', Sl, 4)));

end;

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

function LastDelimi r (const Delirniters, S: ring): Integer;

Она возвращает в качестве значения индекс последнего встречающе­гося символа или набора символов из строки Delimiters.

Есть еще несколько редко встречающихся, ввиду своей специфич­

ности, команд.

function Concat(Sl(, S2, ... , Sn]: String): String;

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

правило для записи параметров подпрограмм в таком виде, когда

указываются только внутренние имена параметров (так называемые

формальные параметры) и их типы. В свою очередь, параметры, передающиеся в подпрограммы при их вызове, носят название фак­

тических параметров.

Функция Concat производит конкатенацию, или «склеивание», любого количества строк и возвращает результирующую строку в

качестве своего значения. Оператор «+» производит ту же операцию для двух строк. Причем оператор «+» работает быстрее функции.

function DupeString(const AText: String; ACount: Int r): Str~

- 48 -

Page 49: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 3. Учимся программировать

Результирующая строка составляется путем приклеивания строки

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

щим примером. Для того чтобы использовать функции работы со

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

procedure TForml.FormActivate(Sender: TObject); var Sl, S2: String[20]; begin

Sl := 'abcdefgh'; S2 := 'xyz'; ShowMessage(Concat(Sl, ' ' S2, '', Sl)); ShowMessage(DupeString('xyz', 5));

end;

Как видите, ничего головоломного. В С, например, первоначально

в официальную поставку вообще не входил модуль работы со стро­ками. Такие функции писались программистами самостоятельно, и

только позже модули работы со строками были включены в состав среды программирования.

В данной главе рассмотрены основные правила программирова­

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

Контрольные упражнения

1. Напишите алгоритм программы, которая будет заполнять двух­мерный массив логического типа следующим образом: в первом и втором столбце будут представлены четыре варианта сочетания двух

операндов, а в последующих столбцах - результаты выполнения

логических операций И, ИЛИ, исключающее ИЛИ.

2. Напишите программу, запрашивающую у пользователя одно число за другим и суммирующую их друг с другом.

3. Напишите программу, заполняющую главную диагональ двух­мерной матрицы единицами, а остальные элементы - нулями.

4. Решите предыдущую задачу с заполнением второй диагонали. 5. Заполните массив из центральной ячейки по спирали к краям

" увеличивающимися числами.

Page 50: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Гпава 4. Оliьектно-ориент11рованное проrрамм11рован11е

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

рые представляются многим теперешним программистам архаичным

кошмаром, до визуального программирования в IDE и движутся даль­ше. Куда приведет это развитие, покажет время. В данной главе да­ется описание основ объектно-ориентированного программирования (ООП) и поясняется общая суть этого явления.

В Delphi разработчик приложения оперирует объектами. В каче­стве примера объектов можно привести элементы, которые вы раз­мещаете на форме, выбрав из палитры. Такое представление наиболее удобно при редактировании внешнего вида форм. Однако объект не ограничивается своим визуальным представлением, к тому же у не­

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

Сами объекты называются экземплярами класса. Например, кнопки Button 1 и Button2 - экземпляры класса TButton.

Основной особенностью ООП является то, что под объектом по­нимают набор переменных (свойств) и подпрограмм (методо~), объ­единенных (инкапсулированных) в одну структуру (рис. 4.1). Так до­стигается возможность максимально реалистичного описания объ­ектов окружающей среды и процесса их взаимодействия.

Иногда в структуре объекта проводится разделение подпрограмм на методы работы с переменными объекта и на обработчики событий, написанные программистом. В данной книге такого разделения не делается, поскольку качественно они ничем не отличаются. Различие

состоит лишь в том, что обработчики событий начинают свою рабо­ту вследствие каких-либо внешних по отношению к приложению

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

из методов этого же объекта. Мы уже использовали свойства объекта Label 1 в примерах пер­

вых двух глав. В тот раз было использовано свойство Caption (за­головок) данного объекта. Однако если рассмотреть свойства объ­ектов класса TLabel, то становится понятно, что их гораздо больше,

- 50 -

Page 51: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 4. Объектно-ориентированное программирование

г ~ 1 • Своиства !

~···

Объект

Рис. 4.1. Блок-схема объекта, состоящего из методов и свойств

чем отображенных и доступных для изменения в Инспекторе объектов.

В версии Borland Delphi 6.0 та.ких свойств у него 36, причем часть из них еще дробится на более мелкие свойства и методы, например

свойство Canvas (холст). Все свойства наиболее часто используемых объектов можно найти в главе 8.

Использовались и методы объекта Buttonl и Button2 в примерах из главы 2. В Инспекторе объектов на вкладке Events вы найдете обработчики выделенного в данный момент объекта. Также сущест­вует довольно большой набор методов, не входящих в число обра­ботчиков событий. Чтобы увидеть все свойства и методы, достаточ­но поставить точку после имени соответствующего объекта или вос­пользоваться справкой.

О точках

Так как объект Buttonl является структурой, то нужно каким-то образом обращаться к элементам этой структуры, иначе полезность ее будет существенно ограничена. Свойства объектов, как перемен­

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

новые значения, либо используя методы объекта, которые изменяют

его свойства тем или иным заранее предусмотренным образом. До­пустим, вам нужно, чтобы в процессе работы приложения в случае возникновения того или иного события изменялся размер кнопки Button 1, например, при наведении на нее мыши.

Для этого можно использовать событие OnMouseMove, которое происходит, когда курсор мыши оказывается наведен на кнопку. Вы­

зовите шаблон обработчика этого события. Напишите в нем следую­щие две строчки:

Buttonl.Height := 35; Buttonl.Width := 85;

Числа взяты на 10 больше тех, что устанавливаются по умолчанию. Запустите приложение. В результате ваша кнопка реагирует на наве-

- 51 -

Page 52: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

А36ука Delphi: проrрамммрованме с нуля

дение на нее мыши: если мышь навести на кнопку, кнопка становится

больше размером, но обратно свой исходный размер уже не обретает. Рассмотрим другой вариант развития событий, уже вполне при­

менимый в конкретной работе. Разместите на форме несколько кно­пок, например, пять. Для каждой кнопки используйте два события:

OnEnter и OnExit. Напишите в первом для каждой кнопки увеличение ширины и высоты до одних и тех же размеров, а во втором ~ умень­

шение до первоначальных размеров. Запустите приложение, пример­

ный результат его работы показан на рис. 4.2. Не очень интересно создавать пять обработчиков, отличающихся

только двумя цифрами друг от друга. Этого можно избежать, если использовать дополнительную информацию от сообщения.

Параметром, передаваемым в процедуры OnEnter и OnExit, явля­ется переменная Sender типа TObject (дословно - отправитель). Используя это, можно составить условие вида

if Sender = Buttonl then ."

и написать одну процедуру, обрабатывающую сообщение OnEnter или OnExit от какого угодно количества кнопок. Делается это следую­щим образом: пишется процедура обработки события для первой кнопки, но в самой процедуре учитывается возможность вызова ее событиями других кнопок:

if Sender = Buttonl then Big(Buttonl); if Sender = Button2 then Big(Button2); if Sender = ButtonЗ then Big(ButtonЗ); if Sender = Button4 then Big(Button4); if Sender "" Button5 then Big(Button5);

Затем для всех остальных кнопок обработчик события не создает­

ся заново, а выбирается из выпадающего списка (в Инспекторе объ­ектов это маленький треугольник справа от полей OnEnter и OnExit). Теперь, если событие OnEnter произошло с любой из обработанных таким образом кнопок, процедура, написанная один раз, обработает их все - без захламления кода модуля лишними заголовками. Про­цедура, использованная в примере, описывается перед всеми обра­. ботчиками событий в разделе implementation и выглядит следующим образом:

procedure big(Number:TButton); Ьeqin

NumЬer.Height := 35; Number.Width :"" 85;

end; - 52 -

Page 53: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 4. Объе1С'fио-ориентированиое nроrраммирование

Рис 4.2. Внешний вид приложения «Пять кнопок»

Поступив аналогично с обработчиками события OnExit, вы полу­чите довольно лаконичную по сравнению с первым вариантом про­

грамму.

В рассмотренном примере вы изменяли свойства Height (высота) и Width (ширина) объектов типа TButton, непосредственно присваивая им новые значения. Вы поняли,' что сделать это довольно просто. До­статочно после имени (Name) объекта поставить точку, и Delphi сам предложит вам вариантъ1 продолжения выражения. Стро:ка вида

Forml.Buttonl.Caption := 'Пуск!';

означает, что приложение должно найти на форме с именем F orm 1 данного проекта объект с именем Button 1 и его свойству Caption присвоить значение «Пуск!». В предыдущих примерах указание на

форму опускалось. Это допустимо, потому что объекты находились в пределах одной формы. Если же объекты находятся на разных фор­мах, то необходимо указывать, какой именно объект вы имеете в виду, поскольку в пределах нескольких форм могут встретиться объекты с одинаковыми именами.

Вернемся теперь к атрибутам видимости, с которыми мы уже стал­кивались в главе 2. Переменные и подпрограммы, описанные в раз­деле private, невидимы извне данного модуля или программы. Дру­гими словами, подпрограммы этого раздела не могут быть напрямую вызваны из другого модуля, а переменные не могут быть непосредст· венно изменены из другого модуля. Если описание нескольких клас­

сов ( class) разместить в пределах одного модуля, то они могут ис· пользовать переменные и подпрограммы из разделов private друг друга, обращаясь к ним по именам с указанием класса.

Переменные и подпрограммы из раздела puЫic видны и могут

быть использованы из любого другого класса, расположенного в лю­бом модуле проекта.

В описании может присугствовать раздел protected. Переменные и подпрограммы из этого раздела доступны к использованию только

для классов, описанных в данном модуле и являющихся потомками

данного класса (о наследовании см. ниже).

- 53 -

Page 54: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Однако переменные и методы разделов private и protected могут быть вызваны из других модулей посредством методов из раздела puЫic этого же класса. Это сделано для того, ·чтобы не допустить

некорректного изменения тех или иных свойств объекта, описывае­мого классом. Например, объект - стена, свойство - высота. Вы­сота физически не может быть отрицательной или нулевой, и для того, чтобы предотвратить присвоение ей такого значения (что, в

свою очередь, может привести к ошибкам других вычислений или сбою в программе), нужно описать это свойство в разделе private, а в разделе puЫic описать два метода: GetHeight и SetHeight. Первый будет возвращать высоту стены, а второй задавать высоту согласно переданным параметрам и с учетом физических условий. В данном

случае он должен будет отслеживать положительность вводимого значения.

Помимо инкапсуляции, технология ООП позволяет воспользовать­

ся еще одним немаловажным механизмом - наследованием. Под наследованием понимают передачу свойств и методов одно­

го объекта (предка) другому (потомку). Это позволяет избежать пов­

торного описания похожих свойств и методов. Можно объявить от­

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

кладной ценности сам по себе, но позволяет экономично создать целую линейку объектов-потомков.

Последним важным механизмом ООП, который полезно будет

рассмотреть в этой главе, является полиморфизм. Допустим, что в наследующем объекте один или несколько обработ­

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

нежели объект-предок. Для реализации такого подхода в объекте-пред­ке эти методы должны быть описаны как виртуальные (virtual). Полез­ность виртуальных методов переоценить трудно, поскольку в новых,

более сложных объектах переопределяемые методы, как правило, рас­

ширяются с точки зрения функциональности, берут на себя дополни­тельные задачи наряду с решаемыми в них у объекта-предка.

В качестве примера наследования и полиморфизма обычно бе­

рутся геометрические фигуры. Допустим, есть некий объект Figure (геометрическая фигура).

У него есть свойства Color (цвет) и Style (стиль штриховки), коорди­наты некой ключевой точки (Х, У), относительно которой может за-

- 54 -

Page 55: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 4. ОбъеКП10-ориентированное программирование

даваться форма объекта, и методы Draw и Erase: первый рисует объ­ект, а второй стирает его. Метод Draw у каждого класса собственный, хотя и носит одно и то же название у всех классов. Такое возможно

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

ренней заливки.

Класс-потомок TCircle (окружность) включает в свое описание свойство, соответствующее радиусу. Метод Draw, являясь абстракт­ным методом в классе-предке~ должен быть детально описан в кл.ас­

се-потомке, исходя из специфики поставленной задачи.

Описание класса предка может выглядеть следующим образом:

type TFigure = class

procedure Draw; virtual; procedure Erase; Color: Integer; //Цвет. Style: Integer; //Стиль заливки. Х,У: Integer; //Координаты ключевой точки.

end;

При описании классов-потомков имя класса-предка указывается

в скобках после зарезервированного слова class. Если же в скобках после слова class не указан класс-предок, то предком такого класса считается класс TObject, который содержит только команды выделе­ния и освобождения памяти для объектов.

Для переопределения виртуального метода используется зарезер­

вированное слово override. Только виртуальные методы могут быть переписаны.

type TCircle = class(TFigure) // Указание на класс-предок.

procedure Draw; override; procedure Erase; Radius: Integer; // Радиус.

end;

Аналогично создаются другие классы-потомки класса TFigure. Такой подход позволяет использовать существующие на данный

момент объекты в качестве шаблонов для вновь создаваемых. Эта особенность ООП использована и в самой библиотеке компонентов Delphi. Например, кнопка с картинкой (BitBtn) является потомком

- 55 -

Page 56: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

обычной кнопки (Button). Естественно, что потомок одного объекта вполне может быть предком для другого. Если вернуться от любого объекта к его самому первому предку, то можно обнаружить, что все объекты, используемые в Delphi, произошли от одного типа объектов TObject. В этом легко убедиться, открыв справку по любому объекту и нажав сверху слева ссылку Hierarchy.

В данной главе рассмотрена структура объектов и способ работы с их методами и свойствами. Мы еще будем возвращаться к этой теме,

поскольку именно в моделировании взаимодействия объектов друг с

другом и с окружением состоит идея реализованной в Delphi техно­логии программирования. ООП - наиболее естественный способ описания окружающего мира, следовательно, ООП имеет преимуще­ства при написании приложений, в которых моделируются свойства

реальных объектов. Этой особенностью, а также применением тех­нологии быстрой разработки приложений обусловлена простота по­нимания основных принципов программирования в Delphi.

Контрольные упражнения

1. Видоизмените приведенную выше программу таким образом, чтобы изменялись координаты активной кнопки.

2. Напишите приложение, которое по щелчку на форме выдает сообщение с координатами курсора мыши на момент щелчка. Для

вывода сообщения используйте процедуру ShowMessage.

Page 57: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

rпава 6. Palioтa с файпами в Delphi

Файл - область памяти на диске, имеющая уникальное имя.

Другими словами, это некий набор данных, имеющий заголовок.

Очевидно, что операции с файлом могут влиять или на всю область целиком, используя только ее заголовок, или на отдельные данные,

содержащиеся в этой области. В Delphi предусмотрены оба варианта работы с файлами.

В Delphi встроено несколько общих файловых операций. Эти процедуры и функции для работы с файлами оперируют ими целиком, поэтому в большинстве случаев программисту достаточно указать

только имя файла. Функция

f unction (const leName: String): Boolean;

удаляет файл с диска. Не существует соответствующей операции для восстановления удаленного файла, поэтому программист должен проследить, чтобы приложение запросило у польЗователя подтверж­дение на удаление. DeleteFile (FileName) - функция логического

типа. Она возвращает true, если файл был удален, и false в противном случае, например, если файл не существует или у него установлен атрибут Read-Only.

Следующие три команды используются при поиске файлов:

function FindFirst(const Path: S:ring; Attr: Integer; var F: TSearchRec): Integer;

function FindNext(var F: TSearchRec): Integer; procedure FindClose(var F: TSearchRec);

FindFirst ищет первый файл с именем, удовлетворяющим заданнЬ1м атрибутам поиска в заданной директории (Attr и Path). FindNext нахо­дит следующий файл, удовлетворяющий заданным условиям; работа­

ет ориентируясь на вызов команды FindFirst. FindClose освобождает память, занятую для работы предыдущих двух команд. Всегда следу­ет вызвать FindClose после того, как результаты поиска были должным образом обработаны и к ним уже не нужно будет обращаться.

Эти команды принимают TSearchRec в качестве одного из пара­метров. Если файл найден, то поля TSearchRec модифицируются в соответствии с информацией о найденном файле, если не найден, то возвращается нулевое значение. Описание этой записи выглядит сле­дующим образом:

- 57 -

Page 58: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

type TFileName = String; TSearchRec = record

Time: Integer; //Время последнего изменения файла. Size: Integer; //Размер файла в байтах.

Attr: Integer; //Атрибуты файла. Name: TFileName; //Имя файла с расширением.

ExcludeAttr: Integer; FindHandle: THandle; FindData: TWin32FindData; {Содержит дополнительную информацию,

такую как :1

время создания файла, время последнего доступа

к файлу, полное и короткое имя.}

end;

Параметр Path - строка, содержащая путь к каталогу, в котором

необходимо провести поиск, а также маску имен файлов. Например: '.\test\*. * '.

Параметр Attr указывает специальные файлы, среди которых так­же нужно проводить поиск в дополнение к обычным файлам. Он может принимать следующие значения:

• faReadOnly - файлы с установленным атрибутом «только для_ чтения»;

• faHidden - скрытые файлы;

• faSysFile - системные файлы;

• faArchive - архивные файлы;

• faAnyFile - любые файлы;

• FaVolumelD - разделы диска;

• FaDirectory- директории. В следующем примере используются метка (Label 1) и две кнопки

(Search и Again), расположенные на форме. Когда пользователь на­жимает кнопку Search, в указанной директории находится первый файл, а в заголовке Caption метки Labell появляются имя и размер найденного файла (рис. 5 .1 ). Каждый раз, когда пользователь нажимает

Рис. 5.1. Внешний вид работающего приложения

- 58 -

Page 59: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 5. Работа с файлами в Delphi

кнопку Again, в заголовке метки появляются имя и размер следую­щего файла.

var SearchRec: TSearchRec; procedure TForml.SearchClick (Ser:der: TObject); begin

FindFirst('C:\Program Files\Borland\delphiб\Ыn\*.*', faAnyFile, SearchRec);

Labell.Caption .- SearchRec. Name + ' is ' + IntToStr(SearchRec.Size) + ' bytes in size';

end; procedure TForml.AgainClick(Sender: TObject); begin

if (FindNext(SearchRec) = 0) then Labell.Caption .- SearchRec.Name + ' is ' +

IntToStr(SearchRec.Size) + ' bytes in size' else

FindClose(Sear\hRec); end;

Рассмотрим следующую функцию:

function RenameFile(const OldFileName, NewFileName: String): Boolean;

Она используется для переименования файла с именем OldFileName в NewFileName. Если операция прошла успешно, то функция возвра­щает true. Если функция по той или иной причине не может переиме­новать файл, например, если файл с именем NewFileName уже сущест­вует, то возвращается false.

Вы не можете переместить файл, как это делается по команде «Пе­ренос», с одного диска на другой. Для этого нужно сначала копировать

файл, а затем удалить старый. Например, с помощью функции

function CopyFileTo(const Source: String; const Destination: String): Boolean;

Здесь первый параметр - строка, содержащая полное имя файла,

который нужно скопировать; второй - куда скопировать. Функция

вернет значение false, если файл по адресу, указанному во втором параметре, уже существует.

Теперь рассмотрим работу с данными, содержащимися в файлах.

При работе с файлами на уровне их составляющих элементов может быть использовано несколько видов файлов. Как правило, используют­

ся типизированные и текстовые файлы. (В ряде приложений может

- 59 -

Page 60: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: nроrраммированме с нуля

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

го типа и, как следствие) одинаковой длины. (Типом данных в файле может быть любой тип фиксированного размера.)

Напрямую с содержимым файла Pascal не работает. Нужно связать с файлом объявленную ранее переменную. Делается это с помощью команды

procedure AssignFile(var F; FileName: String);

Переменная F может быть описана одним из двух вариантов:

F: text; // текстовый файл F: file of <typename> // файл данных типа typename

где FileName - полное имя файла, который нужно связать с пере­менной.

Следующей командой (после связывания с файлом переменной) должна быть одна из трех команд, определяющих вид открытия файла.

procedure Reset(var F [: File; RecSize: Word] };

открывает для чтения существующий файл, связанный с файловой переменной F. RecSize. Она задает размер записи, который будет ис­пользоваться при передаче данных. Если этот параметр не указан, то

размер записи принимается 128 байт.

procedure Rewrite(var F: File [; Recsize: Word) );

создает новый файл или открывает существующий, стирая его содер­жимое. После этого можно записывать в него данные. Смысл пара­метров тот же, что и в предыдущем случае.

procedure Append(var F: Text);

открывает существующий текстовый файл для записи, но не стирает содержимое, новые данные добавляются в конец файла.

Далее в зависимости от того, какой тип файла был открыт, могут применяться около трех десятков различных команд, среди которых

для типизированных файлов:

procedure Read (F , Vl [ ,' V2, ... , Vn ] ) ;

для текстовых файлов:

procedure Read ( [ var F: Text; ] Vl [, V2, ... , Vn ] ) ;

- 60 -

Page 61: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Гnава 5. Работа с файnами в Delphi

Они считывают значения из файла, связанного с переменной F в ука­занные переменные.

procedure Readln([ var F: Text; ] Vl [, V2, ... ,Vn ]);

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

Для типизированных файлов

procedure Write(F, Vl 1 ••• ,Vn);

записывает в файл данные типа, соответствующего файловой пере­менной F;

procedure Write([var F: Text; ] Pl [ , Р2, ... , Pnl);

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

procedure Writeln{[ var F: Text; ] Pl [, P2 1 ••• ,Pn ]);

делает то же, что и предыдущий вариант, но после записи данных

вставляет символ перевода строки ( carriage return/line feed). При открытии файла в его начало помещается указатель, который

сдвигается каждый раз при чтении данных. Также указатель можно

переместить соответствующими командами. Положение указателя важно знать, чтобы иметь представление о том, что именно в следую­щий момент будет считываться приложением. Для типизированных файлов смещение указателя от начала файла указывается в байтах.

function FilePos(var F): Longint;

Эта функция используется для определения положения указателя. Когда файл только открывается и указатель находится в самом на­

чале файла, данная функция возвращает О, во всех остальных слу­чаях возвращается смещение указателя от начала файла в байтах. Функция не работает, если файл не открыт~ а также если он открыт как текстовый.

При использовании циклов с предусловиями, а также в некоторых

других случаях полезным бывает определить тот момент, когда ука­затель, смещаясь по файлу, оказывается в его конце. Специально для этого разработана функция Eof(var F).

Для типизированных файлов:

function Eof {var F): Boolean;

- 61 -

Page 62: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Для текстовых файлов:

function Eof [ (var F: Text)J: Boolean;

Эта функция проверяет, равняется ли смещение указателя от начала. файла его размеру. F - переменная, связанная с файлом. Функция возвращает true, если указатель находится в самом конце файла или файл пуст, во всех остальных случаях возвращается false. Эту функцию можно использовать только с файлами, открытыми для чтения; по­пытка использования ее с файлами, открытыми по командам Rewrite или Append, вызовет ошибку.

Полезной бывает функция определения размера файла:

function FileSize{var F): Integer;

Однако она имеет одну особенность: возвращает размер файла не в бай­тах, а в количестве записей. Например, если файл открыт как file of Byte, то функция вернет его размер в байтах, а если тот же файл открыть как

file of Integer, то возвращенное значение будет вчетверо меньше, пос­кольку под одну переменную типа integer используется 4 байта.

procedure CloseFile( leVar); // ранее открытый файл.

Иногда складывается такая ситуация, что не все данные успели

передаться в файл до его закрытия. В этом случае помимо потери

данных может возникнуть сложность с попыткой прочитать данные

из этого файла в дальнейшем. Чтобы такого не происходило, нужно

применять команду

procedure Flush(var t: Text);

которая дописывает все данные, оставшиеся в буфере файлового обмена, в целевой файл, что гарантирует, что все символы, передан­ные на данный момент в файл, на самом деле туда попали.

Существует еще несколько полезных функций для работы с файла­ми, однако они не столь применимы, и в общем случае будет достаточ­

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

Отдельно стоит рассмотреть работу с текстовыми файлами. Как следует из их названия, это файлы, содержимое которых является текстом. В Delphi предусмотрен очень удобный способ работы с та­кими файлами: все строки файла считываются в одну переменную типа TStringlist. Перед использованием ее необходимо объявить:

var F: TStringList;

- 62 -

Page 63: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 5. Работа с файлами в Delphi

Теперь компилятор «знает», что существует переменная F типа TStringlist, но при попытке ее использования выдаст ошибку, потому что переменной не выделена необходимая память. Для использования переменной необходимо ее инициализировать: выделить необходимое количество памяти для ее хранения и присвоить начальное значение.

Для этого служит метод Сгеаtе.

Если память выделена, то при завершении работы с переменной она должна быть возвращена системе. Если этого не сделать, то сколь

угодно большая память рано или поздно будет израсходована «мерт­выми» объектами. Для уничтожения объекта и возврата памяти сис­теме существует метод Free.

Таким образом, использование переменной типа TStringList, в об-щем случае, выглядит следующим образом: ·

var F: TStringList;

begin F :; TStringList.Crea

{операции с использованием

F.Free; end;

Примечание В отличие от простых типов данных, для которых функции выделения и освобождения памяти берет на себя компилятор, для классов необхо­димо вызывать специальные методы Сгеаtе и Fгее, называемые соответст­

венно конструктором и деструктором класса. Сравнивая С и Delphi, можно заметить, что в С также есть конструкторы и деструкторы с за­ранее определенными именами. Имя конструктора в С совпадает с име­

нем класса, а имя деструктора состоит из имени класса и тильды~.

Вернемся к классу TStringlist. Раз он разработан для работы с фай-лами, то в нем должны быть предусмотрены инструменты для чтения из файла и записи в файл. Для чтения из файла существует метод:

procedure LoadFromFile(const FileName: String);

Он записывает в свойство Strings объекта, из которого он был вызван, строки из указанного в качестве параметра процедуры файла. Это свойство является массивом строк. Соответственно, работа со счи­

танными из файла строками происходит по правилам работы с ячей­ками массивов. Каждая строка файла, отделенная символом перево­да строки, становится ячейкой массива. Например:

F.LoadFromFile ('D:\Text.txt');

- 63 -

Page 64: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

помешает все строки, содержащиеся в указанном файле, в свойство объекта F.Strings. Индексация массива начинается с нуля. То есть в результате выполнения следующих инструкций

F := TStringList.treate; F.LoadFromFile('D:\Text.txt'); Labell.Caption :~ F.Strings[O]; F.Free;

в заголовок Caption метки Labe11 будет помещена первая строка тек­ста, содержащегося в файле.

При чтении из файла количество прочитанных строк запомина­

ется в свойстве Count типа Integer и может быть использовано для проверки количества элементов в созданном массиве строк. Это мо­

жет оказаться полезным, если заранее неизвестно количество строк

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

С массивом строк, расположенным в свойстве Strings, можно про­изводить различные манипуляции, например:

function Add(const S: String): Integer;

добавляет строку S. Если массив отсортирован, то строка записыва­ется на положенное в порядке сортировки место; если массив не

отсортирован, то строка дописывается в конец. Функция возвращает

номер позиции, на которую бьша записана строка. Отсчет по-прежне­

му начинается с нуля.

procedure Clear;

очищает массив строк: удаляет все строки, которые в нем нахо­

дились.

procedure Dele (Index: Integer);

удаляет из массива Strings строку с номером Index + 1.

procedure Exchange(Indexl, Index2: Integer);

меняет местами строки с индексами? указанными в качестве пара~

метров.

function Find(const S: String; var Index: Integer): Boolean;

используется, чтобы получить значение индекса строки S в отсорти­рованном (в порядке таблицы ANSI) массиве Strings. Перед приме­нением поиска необходимо провести сортировку методом Sort.

- 64 -

Page 65: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 5. Работа с файлами в Delphi

procedure Insert(Index: Integer; const S: String);

добавляет строку S на позицию, определенную значением параметра Index. Нумерация начинается с нуля.

procedure Sort;

сортирует строки в массиве согласно ANSI. Еще один способ сорти­ровки - присвоить свойству Sorted значение true.

Зачастую измененный массив строк нужно сохранить в тот же или

другой файл, для этого служит следующий метод:

procedure SaveToFile(const FileName: String);

Данная процедура сохраняет каждый элемент массива в отдельную

строку в файле, указанном в качестве параметра FileName. Если ука­занного файла не существует, он будет создан.

F := TStringList.Create; F.LoadFromFile('D:\Text.txt'); F.Sorted := true; F.SaveToFile('D:\Text.txt'); F.Free;

Эта конструкция инициализирует переменную типа TStringlist, счи­тывает в нее строки из файла Text.txt, сортирует массив, а потом за­писывает результат в тот же файл и освобождает память, занимаемую переменной.

Еще один способ работы с файлами заключается в использовании

специализированного класса TFileStream. Его объекты и методы обес­печивают лучшую совместимость версий компилятора, с одной сто­

роны, но увеличивают количество операций, которые программист

вынужден описывать вручную, с другой.

Для начала работы необходимо объявить переменную этого типа:

var F: TFileStream;

Далее ее необходимо инициализировать. Инициализацией объек­та занимается конструктор Create:

constructor Create(const FileName: String; Mode: Word[;Rights: Cardinal]);

Параметром FileName конструктору в виде строки передается имя файла или полный путь к файлу, с которым предполагается работать.

- 65 -

Page 66: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Параметром Mode определяется режим или способ открытия, этот параметр может принимать следующие значения:

• fmCreate - открыть файл для записи; если этот файл не сущест­вует, то он будет создан;

• fmOpenRead - открыть файл для чтения; если файл не сущест­

вует, то произойдет ошибка: чтение из несуществующего файла невозможно~

• fmOpenWrite - открыть файл для записи; если указанный файл не существует, то произойдет ошибка;

• fmOpenReadWrite - открыть файл для чтения и записи (редак­

тирования).

Третий параметр (Rights) определяет, могут ли другие приложения работать с открытым файлом и, если могут, то каким образом. Пара­

метр может принимать одно из нескольких значений:

• fmShareCompat - другие приложения могут работать с этим

файлом без ограничений;

• fmShareExclш~ive - другие приложения не могут открыть ука­

занный файл;

• fmShareDenyWrite - файл может быть открыт другими прило­

жениями только для чтения;

• fmShareDenyRead - файл может быть открыт другими прило­

жениями только для записи;

• fmShareDenyNone - не показывать другим приложениям, что

файл уже используется.

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

можно не указывать.

По завершении работы с файлом его нужно закрыть, для этого доста­

точно уничтожить объект типа TFileStream, освободив ту область памя­ти, в которой он содержался. Сделать это можно, вызвав метод Free:

F.Free;

Для работы с файлами посредством объекта типа TFileStream используются три метода: Read, Write и Seek. Как следует из их на­званий, первый предназначен для чтения из файла, второй для запи­си, а третий для перемещения внутри файла. Рассмотрим каждый метод подробнее. Строка

F.Read(Buffer,20);

66 -

Page 67: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 5. Работа с файлами в Delphi

указывает приложению прочитать 20 байт и поместить результат в переменную Buffer. Например:

procedure TForml.FormActivate(Sender: TObje ); var

F: TFileStream; // Переменная типа объект ream. ffer: array[O .. S]of char; //Буфер для хранения про~итанных

данных.

begin F :~ TFileStream.Create('D:\Text.txt', fmOp~nRead);

F.Read(Buffer, 6); F. Labell.Caption := Buffer;

end;

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

ся в указанном файле (разумеется, только в том случае, если этот файл существует и программист не забыл поместить метку на форму).

Особенностью метода Read является то, что он возвращает число прочитанных байт. Это число обычно равно второму параметру, пе­редаваемому в метод. Переданное и возвращенное числа могут быть разными в случае, если при чтении был достигнут конец файла либо возникла какая-то физическая неполадка на диске.

Но что делать, если необходимо прочесть шесть байт, начиная с двадцатого? Для этого существует метод Seek:

function Seek(const Of t: I 64; Origin: TSeekOrigin): Int64;

Здесь Offset - число байт, на которые надо сдвинуться; Origin - ука­

зание на одну из точек, из которых возможно начало движения. Воз­

можны три варианта:

• soFromBeginning с начала файла;

• soFromCurrent от текущей позиции к концу файла;

• soFromEnd - от конца файла к началу.

Таким образом, строка

F.Seek(20, soFromBeginning);

указывает приложению переместить указатель текущей позиции в от­

крытом файле на 20 байт, начиная с начала. Еще одной особенностью метода Seek является то, что он возвра­

щает новую позицию указателя в файле относительно начала. Ис­пользуя эту его особенность, можно легко узнать размер файла:

67 -

Page 68: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: проrраммирование с нуnя

Size: F.Seek(O, soFromEnd);

Выполнение этой инструкции приведет к тому, что указатель пере­

местится в конец файла, а в переменную Size будет помещен размер этого файла в байтах.

Последним рассматриваемым здесь методом будет метод Write. В этот метод также передаются два параметра: переменная, содер­

жимое которой нужно записать, и количество байт, которые будут записаны. Если переменная занимает большее число байт, то будет

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

procedure TForml.ForrnActivate(Sender: TObject); var

F: TFileStream; // Переменная типа объект TFil ream. Buffer: array[O .. lOO]of Char; //Буфер для хранения

прочитанных данных

begin Buffer := 'qwertyuiopasdfghjkl'; F := TFileStrearn. F.Write(Buffer, 6); F.Free;

end;

( 'D: \Text. txt', fmOpenReadWrite);

Заглянув в указанный файл после работы приложения, можно

будет увидеть только первые шесть символов массива Buffer. После чтения и записи текущая позиция указателя в файле уста­

навливается в конец обработанного блока данных. То есть в случае

чтения указатель переходит на конец прочитанной области, а в случае

записи - на конец записанной. Если данные добавлялись в конец

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

В данной главе бьmи рассмотрены методы работы с файлами дан­ных, которые находят огромное применение практически во всех бо­лее-менее сложных приложениях. Если приложению нужно запом­

нить какую-то информацию в промежутках между работой, то фай­лы один из вариантов. Особое значение имеет работа с файлами, например, в приложениях, являющихся редакторами данных.

Контрольные упражнения

1. Написать программу, которая бы по щелчку на кнопке выво­дила следующую строку из файла в любой визуальный компонент

формы.

- 68 -

Page 69: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 5. Работа с файлами в Delphi

2. Написать программу, которая по щелчку на кнопке записывала бы строку из поля ввода в предопределенный файл.

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

нием регистра букв, а затем закрывалась без команды пользователя.

Для того чтобы инструкции начали выполняться сразу по запуску

программы, можно использовать событие формы OnCreate; для вы­хода из приложения - процедуру Exit.

Page 70: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Гnава G. Примеры вза11модейс1в11и оliыктов разных кпассов

В этой главе на нескольких примерах мы рассмотрим процесс

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

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

В.1. Пр11пожен11е «Кнопки»

Первое приложение (рис. 6.1) иллюстрирует работу с кнопками. При запуске приложения в окне расположены четыре кнопки

с фиксацией (SpeedButton), одна простая кнопка (Button), радиоrруп­па из четырех пунктов (RadioGroup) и один индикатор с флажком (CheckBox). Для визуализации их работы в окне также расположена графическая форма (Shape).

При нажатии на одну из четырех кнопок с фиксацией форма и цвет объекта Shape 1 устанавливаются в соответствии с рисунком на кноп­ке, а точка в радиогруппе, обозначающая текущий выбор, перемеща­ется на соответствующий пункт. При выборе другого пункта из радио­

группы ничего не происхрдит, зато, если нажать кнопку «Старт!»,

форма и цвет объекта Shape 1 устанавливаются в соответствии с вы­бранной радиокнопкой (цвет соответствует рисункам на кнопках с

фиксацией), а состояние кнопок с фиксацией изменяется. Установка или снятие флажка рядом с надписью «Штриховка» меняет стиль заливки объекта Shape 1.

Рис. 6.1. Приложение «Кнопки»

70 -

Page 71: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 6. Примеры взаимодействия объектов разных классов

Рис. 6.2. Размещение объектов на форме

Таким образом, практически все объекты в окне взаимосвязаны. Чтобы этого достичь, нужно выполнить следующие действия:

l. Разместить на форме объекты и задать им свойства Caption и ltems в соответствии с рис. 6.2.

2. Запустить редактор изображений (можно использовать постав­ляемый вместе с Delphi редактор изображений Tools ~ lmage Ed itor, стандартный PaintBrush или любой другой, который поз­воляет создавать изображения размером 1бх16 пике елей в фор­мате .bmp). Создать в нем четыре изображения: красный круг, синий эллипс, зеленый прямоугольник и желтый квадрат.

3. Установить свойство Shape объекта Shapel в значение stCircle, а свойство Brush.Color этого же объекта в значение cl Red.

4. Задать свойство Glyph кнопок с фиксацией таким образом, чтобы они выглядели, как показано на рис. 6.1.

5. Задать свойство Grouplndex всех четырех кнопок с фиксацией равным единице (или любому другому положительному числу). Свойство AllowAllUp установить в значение false.

6. Дважды щелкнуть по кнопке с нарисованным красным кру­гом. Написать в появившийся шаблон обработчика следую­щий код:

Shapel.Shape := stCircle; Shapel. . Color : clRed; RadioGroupl.:temlndex : О;

Здесь первая строка задает форму объекта Shapel (круг), вто­рая строка устанавливает цвет заливки (красный), а третья

строка устанавливает точку в RadioGroup на первый пункт.

- 71 -

Page 72: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: nрQrраммирование с нуля

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

8. Дважды щелкнуть на кнопке «Старт!!> левой кнопкой мыши. Откроется шаблон обработчика события OnClick.

9. Ввести в него следующий код:

Case RadioGroupl.Itemindex of О: begin

Shapel.Shape := stCi Shapel.Brush.Color : SpeedButtonl.Down ·-

end; 1: be9in

end;

З: Ьeqin

end; end;

clRed;· true;

-Этот код будет выполнять три оператора: установка формы

объекта Shape 1, установка цвета его заливки и изменение со­стояния кнопок с фиксацией. В приведенном листинге пропу­щены три участка кода. Их несложно заполнить самостоятель­

но по аналогии.

1 О. Создать шаблон обработчика события OnClick для объекта CheckBoxl. Ввести в него следующий код:

if CheckBoxl.Checked then Shapel.Brush.Style := bsBDiagonal

else Shapel.Brush.Style :~ bsSolid;

Этот условный оператор проверяет состояние флажка, и, если он установлен, свойство Style объекта Shapel изменяется на bsBDiagonal: заливка объекта становится штриховой. Если флажок не установлен,

то заливка становится сплошной путем присвоения этому свойству

значения bsSolid . .Все. Приложение готово.

- 72 -

Page 73: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 6. Примеры взаимодействия объектов разных классов

6.2. Ф11пь тр ввода Следующее приложение (рис. 6.3 а) осуществляет фильтрацию

вводимых символов. Это может оказаться очень полезным, если от

корректности вводимых пользователем данных зависит работоспо­собность приложения в целом, например в приложениях, выполняю­щих некие математические действия с введенными данными.

В поле Edit вводятся символы, но появляются в нем только цифры; для сравнения в заголовке метки Label появляются все вводимые символы.

Работает приложение относительно просто, и его разработка за­нимает куда меньше времени, чем в предыдущем случае. Необхо­димо:

1. Разместить на форме экземnляр объекта Label и объекта Edit, как показано на рис. 6.3 б.

2. Удалить текст из заголовка метки и из поля ввода. Для этого нужно задать в Инспекторе объектов свойства Label1.Caption и Edit1 .Text пустыми. Задать свойство Caption самой формы.

3. Выбрать в Инспекторе объектов событие OnKeyPress для объ­екта Editl. Дважды щелкнуть по нему левой кнопкой мыши -появится шаблон обработчика события TForm1 .Edit1 KeyPress. Обратите внимание на передаваемые в обработчик данные, в частности, на переменную Кеу. Зарезервированное слово var перед ней означает, что если изменить значение переменной в

обработчике, то значение глобальной переменной Кеу также изменится.

4. В шаблон обработчика событий вставить следующий код:

Labell.Caption := Labell.Caption + Кеу; if not (Кеу in [ '0' .. '9']) then Кеу := Chr (0};

а б

Рис. 6.3. а- пример фильтрации вводимых символов; б - примерный вид формы приложения

- 73 -

Page 74: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Здесь первая строка добавляет в заголовок метки Labell символ, соответствующий нажатой клавише, а условный оператор перед встав­

кой этого же символа в поле ввода заменяет его пустым символом

(Chr(O)), если он не лежит в диапазоне символов от О до 9. Символы взяты в апострофы, это значит, что они интерпретируются как данные

символьного типа, что соответствует типу переменной Кеу.

На этом разработка приложения завершена. Применив такой под­

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

зователем данных перед их использованием в математических опе­

рациях. Можно позволить пользователю вводить, например, только

русские буквы, или только буквы английского алфавита, или цифры

и определенный набор специальных символов. Все будет регулиро­ваться теми символами, которые стоят в квадратных скобках. Услож­

няя логическое условие, можно разрешить вводить только один де­

сятичный разделитель, а минус вводить только в первую позицию

поля, а также многое другое.

&.3. Контекстные меню Последний пример этой главы демонстрирует работу с контекст­

ными меню и сообщениями. Также он показывает одну интересную

особенность разработки интерфейса. Внешний вид приложения по­казан на рис. 6.4 а.

1. Создайте новое приложение и разместите на нем по два эк­земпляра компонентов PopUpMenu и Edit так, как показано на рис. 6.4 б.

2. Задайте свойства Text полей ввода и заголовок формы.

3. С помощью конструктора, вызываемого двойным щелчком по иконке PopUpMenu, создайте контекстные меню, как показано на рис. 6.5.

4. В окне Object TreeView дважды щелкните на первом элементе первого контекстного меню (Каждый). Появится редактор кода

с подготовленным шаблоном обработчика события OnClick. В этот обработчик впишите следующий код:

MessageBox (0, 'Красный', 'Цвет', МВ_ОК)

Точку с запятой ставить не обязательно, потому что сразу за

этим оператором следует закрывающая операторная скобка

( end); это нужно просто запомнить. ·

- 74 -

Page 75: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 6. Примеры взаимодействия объектов разных классов

5. Повторите пункт 4 для остальных шести строк первого контекст­ного меню, изменяя в параметрах оператора MessageBox только цвет, перебрав все цвета радуги от красного до фиолетового.

6. Задайте свойство PopUpMenu для одного из полей ввода (Edit1 ), выбрав из выпадающего списка PopUpMenu1.

7. Повторите пункт 6 для второго поля ввода, привязав к нему еще «мертвое», т. е. ничего пока не выполняющее, всплываю­

щее меню.

8. Щелкните один раз левой кнопкой мыши по первому элементу (Red) второго контекстного меню в окне Object TreeView. От­кройте в Инспекторе объектов страницу событий и найдите событие OnClick. Выберите из выпадающего списка обработчик щелчка по элементу Каждый уже готового меню.

9. Повторите пункт 8 для остальных шести строк второго кон­текстного меню. Таким образом вы задаете, что щелчок по одинаковым по смыслу строкам разных меню будет обрабаты­ваться одной и той же подпрограммой. Это избавляет от пов­торного написания кода и заметно уменьшает размеры про­

граммного модуля.

Запустите приложение. Окно приложения должно выглядеть при­

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

вий будет сообщение, внешний вид которого показан на рис. 6.6. Отметим, что это сообщение, вызываемое через MesageBox, обла­

дает большими возможностями, чем сообщение, вызываемое функцией ShowMesage. Как минимум в нем можно менять сам заголовок и тип сообщения. (О дополнительных возможностях MessageBox можно про­читать в Help.)

а 6

Рис. 6.4. а - внешний вид приложения RainBow; б - форма приложения

- 75 -

Page 76: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

а 6

Рис. 6.5. Контекстные меню: а-первое; 6- второе

Рис. 6. 6. Сообщение программы

В данной главе были рассмотрены несколько общих примеров,

иллюстрирующих работу с некоторыми простейшими компонентами

библиотеки компонентов Delphi. Целью главы было показать после­довательность разработки приложения (а не особенности работы с теми или иными объектами), а также убедить читателей, что создавать работоспособные и полезные приложения, используя IDE Delphi, можно буквально за несколько минут. Естественно, более сложные и объемные приложения потребуют больше времени и, возможно, боль­шего числа разработчиков, но суть самого процесса при усложнении задачи практически не меняется.

Контрольное упражнение

Добавьте в приложение «Кнопки» возможность выбора цвета и геометрии фигуры при помощи контекстного меню.

Page 77: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

rпава 7. Процесс отпадки проrраммы

В предыдущих главах были рассмотрены основные возможности

языка Object Pascal - то, без чего создание сколько-нибудь полезных приложений в Delphi весьма маловероятно. Однако IDE не носила бы такого названия, если бы не предоставляла программисту доволь­

но широкого спектра возможностей по отладке и тестированию про­

граммы. В данной главе речь пойдет именно о том, каким образом программист может упростить себе жизнь на одном из последних

этапов разработки приложения - этапе отладки кода.

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

т. е. ошибки механического характера. Их очень легко отследить и, как правило, довольно просто исправить. Другой вид ошибок - ошибки логические или смысловые. Технически все написано правильно:

программа успешно компилируется и запускается, но работает не так, как предполагал программист, либо вовсе аварийно завершается или

виснет. Такие ошибки локализовать гораздо сложнее, и их не всегда

удается исправить «малой кровью», иногда приходится переписывать

или дописывать значительные участки кода.

Информация лучше воспримется, если ее продемонстрировать на

примере. Создайте приложение. Поместите на форму кнопку и за­дайте ей обработчик события OnClick. В него поместите следую­щий код:

procedure TForml.ButtonlClick(Sender: TObject); var i, j, k: Integer; begin

i .- 13; j : = 2;

k : = 8; Buttonl.Caption := IntToStr(k);

end;

Все предельно просто, но в то же время·достаточно показательно.

Откомпилируйте и запустите приложение, после чего закройте его и

перейдите в редактор кода. Он несколько изменился с момента пос­

леднего редактирования. Внизу появилось дополнительное окно с двумя советами (Hint) (рис. 7.1).

_;. 77 -

Page 78: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Рис. 7.1. Дополнительное окщ) редаКтора кода

В этом окне расположены две строки, начинающиеся со слова

Hint (совет). В этих строках сообщается, что переменные i и j не ис­пользуются в приложении.

Еще одно изменение - синие точки, появившиеся слева от неко­

торых строк кода. (Если на вкладке Compiler диалога Project options установлена опция Optimization, то синие точки появляются так, как показано на рис. 7.2. Если эта опция не установлена, то синими точ­ками будут помечены все операторы программы.)

Эти синие точки показывают, какие строки вошли в исполняемый код приложения. Две неотмеченные строки с операторами присваи­

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

точку прерывания выполнения. Для того чтобы сделать это, нужно установить курсор на строке и нажать F5 или щелкнуть левой кнопкой мыши по серой панели возле этой строки. Если контрольная точка

var i,j,k:integer;

begin i: = 13;

j:=2;

k:=B;

Buttonl. Caption : = IntToStr (k) ;I

Рис. 7.2. Результат компиляции с оптимизацией

- 78 -

Page 79: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 7. Процесс отладки программь~

размещена в строке, оптимизированной при компиляции, то прерыва­ния вы11олнения, разумеется, не произойдет, а при последующем пе­

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

Итак, установите контрольную точку в строке

k : 8;

Запустите программу, нажмите кнопку. Выполнение программы приостановится и откроется Окно редактора кода. В нем будет выде­лена строка, перед которой остановилось выполнение программы.

Первое, что стоит сделать, это посмотреть значения переменных, для этого достаточно навести на переменную курсор мыши и на некоторое

время задержать его (это можно делать как в строке остановки про­граммы, так и в любой другой, находящейся до или после нее). Дру­гой способ узнать значение переменной выделить ее или просто поставить курсор на соответствующую переменную и нажать Ctrl + F7, вызвав, таким образом, окно Evaluate/Modify (рис. 7.3).

Если вы попытаетесь узнать значения переменных i I'!.'!И j, то из этого ничего не выйдет, поскольку они не вошли в исполняемый код,

следовательно, приложение просто не знает об их существовании.

Попытка узнать значение переменной k приведет к появлению сооб­щения (см. рис. 7.3): «Переменная 'k' не доступна здесь из-за опти­мизации», другими словами, переменной k еще не было присвоено значение, поэтому компилятор еще не выделил под нее память (то, на чем было акцентировано внимание выше: работа программы приос­тановилась перед выполнением инструкций, находящихся в указанной строке). Другими словами, данная стро~а в качестве контрольной точки мало чем может быть полезна при отладке. Для того чтобы выполнить одну строку программы, используются команды F7 или F8. Отличаются они тем, что F7, встретив строку с вызовом подпро­граммы, не входящей в стандартные библиотеки, перенесет указатель следующей выполняемой строки в начало подпрограммы, а F8 прос­то выполнит встреченную подпрограмму, не отвлекая программиста

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

не может быть никаких неожиданностей, то и отвлекаться на нее не стоит. В данном случае все равно, какую :клавишу вы нажмете. Уп­

равление перейдет в следующую строку и там снова приостановит работу приложения.

- 79 -

Page 80: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Рис. 7. 3. Окно просмотра и изменения значений переменных и выражений в случае несуществующей переменной

Рис. 7. 4. Окно просмотра и изменения значения переменной k

; ~: !\eik 8

Рис. 7. 5. Список наблюдаемых переменных

Вызовите еще раз окно Evaluate/Modify для переменной k. Теперь в поле Result будет находиться текущее значение переменной. Его при желании можно изменить. В данном случае менять его можно на

любое целое число из диапазона Integer. Однако в других случаях

- 80 -

Page 81: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 7. Процесс отладки программы

возможны и более жесткие ограничения, которые программист должен

отслеживать самостоятельно, например, если переменная влияет на

индекс элемента массива, то неосторожное задание ее величины может

привести к выходу за границы массива, что крайне нежелательно,

если только программист не хочет постав11ть эксперимент «а что будет,

если?». Примерный вид окна Evaluate/Modify показан на рис. 7.4. Измените значение переменной k. Для этого введите новое значе­

ние в поле New Value (новое значение) и нажмите Enter или кнопку Modify инструментальной панели. Переменная примет новое значение, и если теперь продолжить выполнение приложения, то на заголовке

кнопки вместо 8 появится введенное значение. Здесь же предоставля­ется возможность отслеживать не только значения переменных, но и

значения выражений с их участием. Если в поле Expressipn ввести вместо k выражение k + 10 и нажать кнопку Evaluate инструменталь­ной панели, то в поле Res1Jlt появится число 18, а поле New value станет недоступным для редактирования. Здесь можно писать любые выражения, доступные языку Object Pascal, в том числе и лос~ческие, например, выражение k >О в поле Result выдаст true, а k :<j).-" ·-false.

Кнопка Watch в том же окне добавляет выбранную переменную в список наблюдаемых (Watch List) (рис. 7.5).

Основное достоинство этого списка в том, что его можко,размес­

тить на пустом месте рабочего стола и, по мере продвижен~о коду, отслеживать изменения, происходящие со значениями вь:fбt1>анных переменных. В частности, его можно прикрепить к Окну редактора

кода в качестве дополнительного окна, для этого достат°'61о подта-• щить список мышкой в нижнюю часть окна редактора ко~·;.

Переменную в этот список можно добавить и без диалога:·~vаluаtе/ Modify. Достаточно установить на ней курсор и нажать Ctrl + F5.

Таким образом, останавливая работу программы в нужнь1х местах и следя за поведением переменных, можно обнаружить смЬiсловые

ошибки, которые по-другому найти очень проблематично. Однако

если контрольная точка находится в теле цикла с большим количест­

вом повторений, то останавливать работу программы при каждом

повторении - довольно трудоемкая и практически бесполезная за­

дача, если сбой происходит не при начальных значениях переменной

цикла. Для такой ситуации правильнее было бы поручить IDE, а точнее Отладчику (Debugger), приостановить работу программы, когда будет выполнено некое условие. Сделать это можно, щелкнув правой кнопкой мыши по контрольной точке Breakpoint properties. Откроется диалог (рис. 7.6), в котором можно задать условие приос­тановки работы программы в данной контрольной точке.

- 81 -

Page 82: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Рис. 7. 6. Диалог задания условий для приостановки работы программы

В строке Condition можно написать логическое выражение. Когда оно примет значение true при прохождении этой контрольной точки, работа приложения приостановится. В строке Pass count можно за­дать количество повторов до остановки. Например, число 2 в этом поле означает, что выполнение программы будет приостановлено,

только когда эта точка будет проходиться во второй раз.

Описанные выше способы поиска логических ошибок кода помо­гают найти практически все ошибки, однако иногда полезнее исполь­

зовать другой инструмент, предназначенный не совсем для этих целей.

Имеются в виду сообщения. Каждый пользователь Windows много раз видел маленькие окошки с различными сообщениями, предуп­реждениями, запросами и запр~тами. Как правило, эти сообщения не приносят положительных эмоций. У программиста в Delphi есть возможность поставить сообщения себе на службу. Строка

ShowMessage('k =' + IntToStr(k));

вызовет появление сообщения во время работы приложения (рис. 7. 7).

Рис. 7. 7. Сообщение, вызванное процедурой ShowMessage()

- 82 -

Page 83: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 7. Процесс отладки программы

В текст сообщения может быть включена любая информация, как правило, это значения каких-либо переменных. Можно также встро­

ить процедуру ShowMessage() в условный оператор, тогда сообщение будет выдаваться в предусмотренных случаях. Возможности ограни­чены только фантазией программиста и размером его монитора: не

стоит пытаться вписать в текст сообщения все значения массива раз­мером 5Ох50. Как видите, варианты, которые можно реализовать с

помощью сообщений, в основном те же, что и для контрольных точек,

однако иногда сообщения проще и удобнее в условиях конкретной задачи.

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

будучи правильно примененными, помогают найти все тонкие места кода, из-за которых приложение может работать некорректно.

Контрольное упражнение

Выберите любое приложение из приведенных ранее в книге или

разработанных вами самостоятельно и дополните код таким образом,

чтобы можно было использовать все варианты работы с контрольны­

ми точками (условные остановки, отслеживание текущих значений

переменных и выражений с их участием, индикация выполнения

определенного участка кода).

Page 84: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

rпава~ 8. &11in1oтe1a компонентов Delpl1i (справочное пр1nоJКен1е)

Библиотека компонентов (Visual Component Library, VCL) Delphi включает множество стандартных классов объектов, с помощью которых разработчик создает свое приложение. Палитра компо­

нентов расположена в правой части панели инструментов IDE (рис. 8.1).

Число вкладок или страниц в палитре больше, чем может быть

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

стрелками, расположенными в правой части палитры.

Ранее уже упоминалось, что для размещения компонента на

форме необходимо открыть соответствующую страницу палитры, щелкнуть по компоненту левой кнопкой мыши, а затем щелкнуть примерно в том месте формы, где предполагается расположить объ­ект. После размещения объект можно двигать по форме и растяги­вать/сжимать мышью, редактировать его положение и размер из

Инспектора объектов, менять свойства Align, Width и Height непо­средственно в коде приложения. Размер объекта можно указать и в мо-мент вставки, если выделить мышью некоторую область. ·

По двойному щелчку компон~нт разместится в центральной час­

ти формы. Если необходимо разместить несколько однотипных объ­ектов на форме, это можно сделать, нажав Shift перед щелчком по компоненту в палитре. В этом случае каждый новый щелчок на фор­

ме будет размещать там новый экземпляр выбранного компонента до

тех пор, пока не будет нажата кнопка со стрелкой в левой части па­

литры.

Имена компонентов появляются на всплывающих подсказках.

В табл. 8.1 дано краткое описание закладок, включенных по умол­чанию в палитру Delphi 6.

Рис. 8.1. Палитра компонентов IDE

- 84 -

Page 85: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphl (справочное приложение)

Таблица 8.1

Компонент Описание

Standard Содержит наиболее часто используемые компоненты

Additional Дополнение к предыдущей панели

Компоненты, обеспечивающие взаимодействие с объектами

Win32 32-разрядного (кросс-платформенного) интерфейса. Выбрав в меню File-+ New - CLX Application, можно заметить, что вкладка Win32 заменяется вкладкой Common Controls

System Компоненты специализированного системного управления (таймер, плеер и т. д.)

Основные компоненты для организации доступа к базам данных* DataAccess без использования каких-либо специальных механизмов доступа,

таких как dbExpress, BDE, ADO и т. д.

Компоненты для отображения и редактирования данных. Используются при создании пользовательского графического

Data Control интерфейса приложений, работающих с базами данных, и могут применяться вне зависимости от того, какая технология

взята за основу при построении БД

Компоненты для организации доступа к БД. Рассчитаны на работу с базами 082, lnterBase, MySQL и Oracle. Работают только

dbExpress посредством SQL-зanpocoв, обеспечивают доступ к данным в кросс-платформенных приложениях. Это наиболее быстрый и наименее ресурсоемкий способ доступа к базам данных

Позволяет строить многоуровневые {работающие на нескольких машинах) приложения для работы с БД. Такие приложения

DataSnap обмениваются данными no локальной сети или по сети Интернет. Технология позволяет создавать, например, централизованное управление производственным процессом и подцержку

тонких (thin) клиентов

Компоненты для организации доступа к БД. Рассчитаны на работу ВОЕ (Borland с базами Paradox, dBase, FoxPro и текстовыми файлами. Database Подцерживают работу посредством SQL-эапросов с любыми БД. Engine) На настоящий момент технология устарела и поставляется

в основном для совместимости с более ранними версиями

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

ADO таблицами, базами данных. ADO работает с запросами SQL,

(ActiveX Data позволяет отслеживать изменения в источнике данных

(транзакции). Лучше всего подходит длs:~ работы с базами данных Object) Microsoft: MS SQL Serveг или MS Access. Использование ADO удобно при переносе на другой компьютер с ОС Windows: нет необходимости в дополнительно устанавливаемом ПО

* Компоненты Delphi позволяют работать только с реляционными БД.

- 85 -

Page 86: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Продолжение табл. 8.1

Компонент Описание

Компоненты, реализующие непосредственный доступ к БД, lпterBase созданным на основе lпterBase. Работают с запросами SQL

и позволяют отслеживать транзакции

lпternet Поддерживает создание приложений для WеЬ-серверов

Содержит компоненты, обеспечивающие работу с различными сетевыми протоколами, среди которых: Интернет-протокол

FastNet TCP/IP, протокол передачи файлов FГР (File Traпsfer Protocol), протокол работы с гипертекстовыми документами НТТР, специальный протокол передачи новостей NNTP (Networking News Traпsfer Protocol) и др.

Поддерживает функции многомерного анализа данных.

Decision Cube Компоненты этой страницы позволяют представить информацию базы данных в более удобном для пользователя виде

Позволяет визуально разрабатывать отчеты. Поддерживает полосы, отступы, колонтитулы, заголовки, подведение итогов.

QReport Можно строить отчет из любого источника (таблицы, списки, выборки, массивы и т. д. ). Есть возможность предпросмотра для проверки результатов, автоматического выполнения расчетов

Содержит стандартные диалоговые окна Windows для обеспече-Dialogs ния привычного интерфейса вновь создаваемых приложений для

таких операций, как открытие, сохранение и печать файлов

Содержит компоненты, идентичные элементам управления Windows 3.1 для совместимости с приложениями, созданными

Win 3.1 с помощью ранних версий Delphi. Большинство из них поддерживает практически те же функции, что и более новые 32-битные компоненты

Примеры компонентов, которые программист может создавать

Samples и добавлять в палитру. Коды этих компонентов по умолчанию

находятся в директории \Source\Samples

ActiveX Объекты ActiveX. Полностью работоспособные портативные приложения, созданные независимыми разработчиками

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

lndy Clients lnternet Direct. Интернет-компоненты с открытым кодом, включаемые в популярные Интернет-протоколы

lndy Servers, Практические дополнения к предьщущему

lпdy Misc

Servers Оболочки для общих СОМ серверов

Как видите, Delphi предоставляет очень широкий спектр функций, реализуемых через компоненты библиотеки. Однако редко програм­

мисты используют сразу все компоненты, и даже сразу все страницы

- 86 -

Page 87: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение)

практически никогда не используются. Ниже рассматриваются ком­

поненты, находящиеся на первых двух страницах палитры: Standard и Additional (табл. 8.2).

Компонент

Закрытый список

Таблица 8.2

Тип Описание

Компоненты страницы Standard

MainMenu

PopupMenu

Label

Edit

Memo

Button

CheckBox

RadioButton

ListВox

Создает главное меню для формы. Чтобы получить доступ к пунктам меню, необходимо добавить экземпляр на форму и вызвать Дизайнер меню (Menu Designer) двойным щелчком мыши

Создает всплывающее меню, вызываемое при нажатии правой кнопки мыши. Чтобы получить доступ к пунктам меню, необходимо добавить экземпляр на форму и вызвать Дизайнер меню (Menu Designer) двойным щелчком мыши

Объект для вывода на форму текста, который пользователь не может изменить

Поле редактирования текстовой информации. Здесь пользователь может ввести или изменить однострочный текст

Поле редактирования текстовой информации. Здесь пользователь может ввести или изменить многострочный текст

Кнопка с надписью, обычно используется для инициации определенного действия

Флажок, который пользователь может выставлять как Да/Нет или true/false. Используется для представления группы настроек, которые не являются

взаимоисключающими: можно выбрать больше одного флажка в группе

Флажок, который пользователь может выставлять как Да/Нет или true/false. Используется для представления группы настроек, являющихся взаимоисключающими:

можно выбрать только один флажок в группе

Выпадающий список выбора с полосой вертикальной прокрутки. Чтобы сформировать список, необходимо добавить экземпляр на форму и нажать кнопку с многоточием возле пункта ltems в Инспекторе объектов

- 87 -

Page 88: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Компонент

Комбинированный список

Нете кетовая таблица

Продолжение табл. 8.2 Тип Описание

Выпадающий список выбора, объединенный с полем ввода (Edit). Пользователь может ввести данные в поле или выбрать из списка.

ComboBox Чтобы сформировать сnисок, нужно добавить экземпляр на форму и нажать кноnку

ScroolBar

GroupBox

RadioGroup

Panel

с многоточием возле пункта ltems в Инспекторе объектов

Используется для прокрутки содержимого окон и форм. В обработчике событий OnScroll программистом определяется, что именно

происходит при изменении положения

бегунка. Также используется для предоставления возможности выбора значения величины из заданного диапазона

Контейнер. У помещенных на него компонентов есть возможность группового

редактирования опций

Контейнер, содержащий радиокноnки. Удобный способ задания количества и состава радиокнопок, последующего обращения к их свойствам из кода приложения

Панель, которая может содержать другие компоненты. Обычно используется для создания инструментальных панелей и строк статуса

Компоненты страницы Additiona/

Кнопка, на которой могут быть размещены

BitBtn изображение и заголовок

Кнопка, которая может содержать иконку (glyph), но обычно не содержит заголовок.

SpeedButton SpeedButton часто компонуются в группы на объекте Panel для создания инструментальной панели

Похож на компонент Edit, но обеспечивает ввод и редактирование данных

MaskEdit в соответствии с некоторой маской (время, телефонные номера)

Таблица, используемая для отображения

StringGrid строковых (текстовых) данных

DrawGrid

Таблица, используемая для отображения нетекстовых данных

- 88 -

Page 89: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение)

Рамка

(····.!, х- ~: ~i; - ~ ·~: ';'у - • _.:i

Контейнер с прокруткой

Список флажков

График

lmage

Shape

Bevel

Элемент для размещения на форме содержимого графических файлов

Самостоятельный rрафический примитив, используемый для отображения графических форм

Линия или контейнер с трехмерным оформлением

Контейнер с изменяемыми размерами, в котором, при необходимости, отображаются

ScroolBox линейки прокрутки

Прокручиваемый список (похожий на

CheckBoxlist ScroolBox), в котором каждый элемент списка представляет собой CheckBox

Разделитель, часто используемый на форме между двумя элементами управления,

Splitter чтобы позволить пользователю изменять мышью размеры элементов во время работы приложения

Не редактируемый текстовый компонент, похожий на метку (label). Как правило,

StaticText используется для обеспечения пользователя информацией о состоянии приложения в текущий момент

Основа для размещения инструментальных панелей с возможностью динамического

ControlBar перемещения их мышью относительно друг друга в процессе работы приложения

labeledEdit

ColorBox

Chart

Компонент Edit со встроенным компонентом Label

Комбинированный список, позволяющий пользователю выбрать цвет

Компонент для вывода графиков

Перечисленные основные компоненты палитры можно условно

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

- 89 -

Page 90: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

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

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

<Имя>.<Свойство>

Еще одним общим свойством всех объектов является свойство Tag. Оно не несет изначально никакой целевой нагрузки и может быть использовано для хранения каких-либо данных вспомогательного характера.

8.1. Меню Первыми в списке идут два типа меню. Создание их довольно

однотипно, к тому же, как правило, всплывающее (PopUp) меню не добавляют в приложение, в котором отсутствует главное (Main) меню. Практически в любом Windоws-приложении присутствуют главное и всплывающее меню~ что избавляет от необходимости уточнять, для чего они применяются.

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

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

ворить эту потребность~ создать несколько вариантов главного меню и своевременно их сменять. Делается это путем присвоения свойству Menu формы приложения имени соответствующего варианта:

MainMenн2;

Имена пунктов и страниц меню хранятся в свойстве ltems, которое заполняется с помощью конструктора (рис. 8.2 а).

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

- 90 -

Page 91: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение}

а 6

Рис. 8.2. а Конструктор главного меню; б свойства пункта меню

Набор свойств :каждого пункта меню (рис. 8.2 б) позволяет реа­лизовывать любые эффекты, встречающиеся в главных меню типич­ных приложений.

AutoCheck определяет автоматическое изменение свойства Checked при выборе пункта (опции) меню.

Checked определяет состояние опции как объекта типа CheckBox: если установлено true, рядом с опцией появляется га~очка.

AutoHotkeys определяет, будет ли программа отслеживать уни­кальность :клавиш быстрого вызова для подопций:

maAutomatic - проверка автоматически при создании подопции;

maManual - проверка с помощью вызова специального метода

(RethinkHotkeys ); maParent - проверка по правилу, установленному для опции

верхнего уровня.

91

Page 92: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: nроrраммирование с нуля

AutoLineReduction задает автоматическое удаление лишних раз­делителей между опциями многоколончатого меню второго уровня.

Возникновение лишних разделителей возможно) например, при ди­

намическом построении меню в процессе работы приложения. При­нимает те же значения, что и AutoHotkeys; для проверки использует метод RethinkLines.

Bitmap позволяет установить рядом с пунктом меню иконку, ил­люстрирующую ее содержимое.

Break позволяет создать многоколончатый список подменю, уста-навливает несколько разновидностей разрывов раздела на столбцы:

mbNone - значение по умолчанию, разделение запрещено;

mbBarBreak - колонки разделяются линией;

mbBreak - колонки разделяются расстоянием.

Caption содержит заголовок пункта меню. EnaЫed, будучи установленным в значение false, делает соответ­

ствующий пункт меню серым и не реагирующим на щелчки мыши.

Radioltem, установленное в значение true, позволяет работать с пункгами меню, имеющими одинаковые значения свойства Grouplndex, как с объектом RadioGroup. (Свойству AutoCheck необходимо пред­варительно задать true.)

ShortCut позволяет выбрать сочетание клавиш для быстрого вы­зова пункта меню из предложенных.

VisiЫe, установленное в значение false, делает опцию невидимой. Основное событие для этого объекта OnClick, соответствующее

щелчку левой клавиши мыши на пункте меню.

Компонеmу палитры PopUpMenu соответствует контекстное меню, которое вызывается щелчком правой клавиши мыши на некотором

объекте формы. В него обычно включают те команды главного меню, которые чаще всего используются при работе с данным объектом. Компонент, так же как и MainMen1J, является невизуальным. Контекст­ных меню может быть несколько для каждой формы. Все оконные компоненты имеют свойство (PopUpMenu), которое указывает, какое контекстное меню, из размещенных на форме, будет вызываться по щелчку правой кнопки мыши. При первоначальном размещении объ­екта на форме свойство PopUpMenu пусто, и его можно задать, выбрав контекстное меню из выпадающего списка, содержащего все разме­

щенные на форме контекстные меню. Формирование контекстного меню происходит практически так же,

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

- 92 -

Page 93: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение)

8.2. Palioтa с текстом К компонентам для работы с текстом относятся Label, StaticText,

Panel (в качестве дополнительной возможности может содержать текст, хотя в основном этот компонент применяется для группировки

элементов управления), Edit, MaskEdit, LabeledEdit, Memo, StringGrid. Первые три компонента из перечисленных выше обычно использу­ются для отображения различных надписей на форме. Рассмотрим их подробнее.

Текст, отображаемый в компоненте, определяется содержимым

свойства Caption. Как и большинство остальных свойств, его можно задавать при проектировании формы или программно в процессе работы приложения. Например:

Labell.Caption :='Текст для размещения на форме';

Апострофы указывают, что свойство имеет строковый тип, а значит, и присваиваться ему могут только строковые значения. Если же не­обходимо вывести в метку числовую информацию, то применяют уже использованные в предыдущих главах функции IntToStr(Integer) и FloatToStr(Float). К строке в правой части выражений, аналогичных приведенному выше, применимы все функции для работы со строко­вым типом данных.

Для метки (Label) единственно доступными возможностями офор­мления надписи являются свойства Color (определяет цвет фона для текста) и Font (определяет параметры используемого в объекте шриф­та). StaticText и Panel, помимо этого, имеют еще и свойство BorderStyle, определяющее рамку вокруг текста. А компонент Panel, ко всему прочему, имеет еще и свойства Bevellnner, BevelOuter, BevelWidth, BorderWidth, которые представляют достаточно широкие возможнос­ти по оформлению надписи.

Положение и размеры визуальных компонентов (а все компонен­ты для работы с текстом являются визуальными) задаются свойства­ми Тор, Left, Width и Height. Первые два определяют координаты ле­вого верхнего угла объекта относительно левого верхнего угла кли­ентской области формы или панели, на которой объект расположен. Последние два - ширину и высоту объекта в пикселях.

Также можно задать несколько стандартных вариантов располо­жения объекта вдоль одного из краев клиентской области путем за­дания соответствующего значения свойства Align.

Свойство Alignment определяет форматирование текста по левому краю, по правому краю или по середине.

Свойство WordWrap определяет допустимость переносц,_, если длина текста превышает соответствующий размер объекта.

- 93 -

Page 94: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Отметим, что если в значение свойства Caption входит символ &, то в заголовке следующая за символом & буква или цифра отображает­ся подчеркнутой. Нажатие подчеркнутого символа на клавиатуре при

нажатой клавише Alt приводит к переносу фокуса на объект формы, который указан в свойстве FocusControl.

Если рассмотренные выше объекты предназначены в основном

для вывода текста, то все остальные: Edit, MaskEdit, LabeledEdit, Memo, StringGrid - служат для ввода, редактирования и вывода тек­

стовой информации в том или ином виде. Наиболее простой компо­нент поле ввода Edit. Благодаря этому он применяется чаще всего в различных диалогах и формах для ввода и редактирования тексто­

вых данных. У него отсутствует свойство Caption, однако имеется его аналог свойство Text. Для того чтобы в поле появился какой-либо текст, достаточно присвоить этому свойству необходимоt; значение

программно:

Editl.Text : 'Текст, вводимый на форме';

или в соответствующем поле Инспектора объектов. Однако чаще Edit используется для считывания текста.

var Str: String; begin

Str := Editl.TeXti end;

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

var Str: String; begin

Str := Editl.Text; Edit2.Text := Str; Labell.Caption : Edit2.Text;

end;

В рассмотренном примере текст, находящийся в объекте Edit 1, будет выведен на форму с помощью двух других объектов: Edit2 и Label 1.

При вводе данных в Edit пользователю предоставляются основные возможности работы с текстом, характерные для редактирования тек­ста в текстовых редакторах. Есть возможность выделения текста, пос­

ледующей работы с буфером обмена, отмены последней операции

(UnDo ). Имеются также свойства, недоступные из Инспектора объек­тов: Sellength, SelStart, SelText. Они содержат длину выделенного фраг­мента, номер первого выделенного символа, сам выделенный текст.

94 -

Page 95: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение)

Иногда бывает полезно вывести текст, который пользователь не имеет права менять. Это можно сделать, и используя поле ввода.

Необходимо установить свойство ReadOnly равным true, а свойство AutoSelect false. В этом случае окно ввода начинает выполнять функции метки, однако позволяет размещать текст, превышающий

длину самого поля с возможностью прокрутки текста для его про­

смотра. Метка таких возможностей не имеет. Аналогично свойству Caption, свойство Text работает только с тек­

стовыми данными. Для преобразования в текстовый вид используют­ся приведенные выше функции IntToStr и FloatToStr, а также функции обратного преобразования StrTolnt и StrToFloat.

Свойство Maxlength определяет максимальное количество вво­димых символов. Если значение установлено равным нулю, то длина

не ограничена.

Свойство Modified доступно только из кода приложения и пока­зывает, был ли изменен текст, содержащийся в поле ввода.

PasswordChar позволяет применять Edit для ввода паролей. Если значение этого свойства отлично от начального значения #0, то вместо символов, вводимых пользователем, в поле Edit будут появляться сим­волы, указанные в свойстве PasswordChar. Как правило, это * или #.

Компонент MaskEdit отличается от Edit только тем: что в нем можно задать маску вводимой строки. Это осуществляется с помощью

свойства EditMask, которое состоит из трех полей, разделенных точ­кой с запятой;. Первое поле содержит специальным образом задан­ную маску ввода (табл. 8.3). Второе устанавливается в 1 или О и оп­ределяет, будет ли свойство Text содержать вводимые пользователем данные вместе с символами маски ИJIИ без них. Третье определяет символ, показывающий позиции, которые еще не заполнены пользо­

вателем.

Ввести маску можно непосредственно в соответствующее поле

Инспектора объектов, а можно нажать многоточие справа от этого

поля и вызвать редактор масок (рис. 8.3). Поэкспериментируйте с этим редактором. Логика его работы

очень проста и полностью отражена в приведенной выше таблице.

Компонент LabeledEdit представляет собой простое объединение метки (Label) и поля ввода (Edit). Его свойства в основном повторя­ют свойства поля ввода, в том числе Text. А Editlabel содержит ос­новные свойства метки (Label)~ в том числе Caption.

Компонент Memo - это поле для ввода, редактирования и выво­

да мноrострочного текста. Фактически этот компонент является рас­

ширением компонента Edit. Как следствие, Memo обладает возмож­ностями работы с буфером обмена и отмены последней операции

- 95

Page 96: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

(UnDo ). Параметры шрифта одинаковы для всего текста и определя­ются свойством Font. (Существует и более продвинутая версия окна редактирования многострочного текста: RichEdit, которая позволяет работать с текстом ~ «обогащенном» формате RTF.)

Таблица 8.3

Служебные символы Значение EditMask

L* е этого символа должна быть буква

А На этом месте должна быть буква или цифра

с Любой неnустой символ

о В данной позиции может быть только цифра

9 В данной позиции может быть цифра, но позиция может остаться пустой

# . ~ " Могут быть только цифра, знаки+/- либо пустой символ ~···}

Позволяет следующий символ рассматривать ' \ не как служебный, а как текстовый

Используется для разделения часов, минут и секунд в

соответствующих шаблонах. Если в настройках системы •,

установлен другой символ-разделитель, будет использоваться он \

' .) Применяется для разделения года, месяца 1 и дня в соответствующих шаблонах •,

' Используется для разделения полей маски

Автоматически вставляет пробел в текст. При вводе текста эта позиция пропускается курсором

Определяет подавление пробелов: если символ есть ! в любом месте маски, подавляются пробелы перед текстом;

в противном случае идущие после текста

> Преобразует последующие символы до конца строки или до символа< в заглавные i

< Преобразует последующие символы до конца строки или до символа > в строчные

<> Изменение регистра не осуществляется

Такие свойства, как Alignment и WordWrap, для компонента Memo имеют тот же смысл, что и для меток, и определяют выравнивание

текста и допустимость переносов длинных строк. ReadOnly и Maxlength также аналогичны рассмотренным выше. WantReturn и WantTab~ уста­новленные в значение false, запрещают вводить в текст символы пере­вода строки и табуляции. ScroolBars указывает наличие полос прокрут­ки текста.

* Наряду с заглавными буквами используются и строчные, обладающие допопнитель­ной возможностью размещения пустого символа.

- 96 -

Page 97: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение)

E:>(tension Social Security S hort Zip Code Long Zip Code Date

Рис. 8.3. Редактор масок ввода

позволяет изменять текст на эт аnе

проект~.iрования формы

Рис. 8.4. Редактор списка строк

(415]555·1212 15450 555.55.5555 90504 90504·0000 06.27.94 09:05:15РМ

13:45

Lines является основным свойством рассматриваемого объекта. Оно имеет тип TString и содержит строки текста из поля редактиро­вания. Существует несколько способов задания текста н;а этапе про­

ектирования: ввод непосредственно в соответствующее поле Инспек­

тора объектов с помощью Редактора списка строк (рис. 8.4) или по­средством Окна редактора кода _Code Editor.

Получить доступ к содержащемуся в объекте тексту можно с по­мощью Lines.Strings[] или Memo1.Text. Например, строка

ShowMessage(Memol. nes.Strings[O]);

вызывает появление сообщения, содержащего первую строку ( нуме­рация строк начинается с О).

ShowMess (L'1епю1. х~) ;

- 97 -

Page 98: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля .

в отличие от предыдущего примера, вызовет появление сообщения со всем текстом, содержащимся в поле редактирования Memo.

Стоит учесть, что построчный доступ при включенном переносе слов (WordWrap) малополезен, поскольку содержимое строки суще­ственно зависит от изменения размеров поля ввода Memo. Например, если задано:

Memol.Align := alClient;

то текст, размещенный в нескольких строках при свернутом окне

приложения, вполне может вписаться в одну-две строки, когда окно

приложения будет развернуто на весь экран.

Свойство Count хранит количество строк текста и предназначено только для чтения.

Методы Clear и Add предназначены, соответственно, для удаления содержимого окна и добавления еще одной строки в конец списка.

Для работы с файлами предусмотрены методы LoadfromFile и SaveToFile.

Компонент StringGrid представляет собой таблицу, содержащую данные строкового типа. Данные могут быть доступны для чтения

или для чтения и записи одновременно. Таблица может иметь поло­сы прокрутки и фиксированные столбцы и строки, которые не про­

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

С помощью свойства

Cells[ACol 1 ARow: Integer]: ring;

можно получить доступ к конкретной ячейке, а с помощью свойств

Cols[]: TStrings и Rows[]: TSt ngs

доступ к списку строк, содержащихся в указанном столбце и списку

столбцов, содержащихся в указанной строке, соответственно. Свойства ColCount и RowCount содержат количество столбцов

и строк. LeftCoJ и TopRow индексы самой левой верхней ячейки из

тех, что видимы на данный момент в результате прокрутки. А Col и Row содержат индексы выделенной ячейки.

Основным методом, используемым при работе, является OnSelectCell, срабатывающий при выделении.

В процедуру

procedure StringGridl ARow:

ее ll(Sender: TObject; ACol, ; var CanSelect: Boolean);

98 -

Page 99: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение)

передаются индексы выбранной ячейки и логическая переменная,

характеризующая возможность ее выбора. Таблица StringGrid является производным объектом от таблицы

DrawGrid. Функциональность StringGrid расширена за счет добавления свойств и методов для работы с текстом (Cells, Cols, Rows). Осталь­ные свойства этих таблиц схожи.

Компонент DrawGrid, как и многие другие компоненты в Delphi, имеет свойство Canvas (холст, канва), на которой можно размещать изображения, используя графические процедуры класса. Имеется

также метод CellRect, возвращающий координаты области, отведен­ной под указанную ячейку:

function CellRect(ACol, ARow: Longint): TRect;

Нумерация строк и столбцов начинается с нуля.

8.3. Кнопки Наиболее простой кнопкой является компонент Button, немногим

реже используется BitBtn. Свойства и методы у них в основном одни и те же, но второй компонент позволяет добавлять на кнопку поясняю­

щую картинку.

Основное свойство кнопки - Caption, а основной метод-OnClick. Свойство Caption позволяет задать клавиши быстрого доступа. Если перед каким-либо символом заголовка поставить&, то этот символ

будет отображен подчеркнутым, а нажатие Alt +символ приведет к тем же результатам, что и нажатие кнопки. OnClick определяет пове­дение приложения в случае щелчка по данной кнопке.

Свойство Cancel, установленное в true, ассоциирует кнопку с на­жатием клавиши Esc. Свойство Default, установленное в true, ассо­циирует кнопку с нажатием клавиши Enter. Исключение представля­ет собой ситуация, когда в фокусе находится другая кнопка, в этом

случае при нажатии Enter будет выполнен обработчик события OnClick кнопки, которая находилась в фокусе.

Вышесказанное относится к обоим видам кнопок. Теперь рас­

смотрим особенности кнопки класса BitBtn. Изображение размещается на этой кнопке посредством свойства

Glyph. Нажав кнопку с многоточием рядом с полем значения этого свойства в Инспекторе объектов, вы увидите диалог просмотра изоб­ражения (рис. 8.5).

При нажатии кнопки Load открывается стандартный диалог откры­тия файла, в котором нужно указать файл с расширением .bmp. После

- 99 -

Page 100: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: проrраммирование с нуnя

Рис. 8.5. Окно выбора картинки для свойства Glyph

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

рех)*. Каждое изображение отображается при соответствующем ста­тусе кнопки. Первое отображается по умолчанию, второе - когда кнопка недоступна, третье - когда нажата, четвертое при фиксации кнопки (SpeedButton) в нажатом состоянии. Количество изображений в загруженном файле можно узнать из свойства NumGlyphs.

Положение надписи и изображения на кнопке определяется свой­ством Margin. По умолчанию свойство равно -1, что соответствует нахождению заголовка и изображения в центре кнопки.

Свойство Layout задает относительное положение надписи и изо­бражения, Spacing -расстояние между надписью и изображением в пикселях.

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

окончательном варианте приложения все использованные стандартные

варианты оформления лучше заменить собственными, поскольку ис-

* В этом случае изображения должны располагаться в файле rориз.онтально слева направо, быть одинаковой ширины и высоты.

- 100 -

Page 101: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение)

пользование стандартных дизайнерских решений уменьшает возмож­ности разработчика заранее предопределенным набором штампов.

Кнопка с фиксацией SpeedButton, так же как и предыдущая, име­ет возможность размещения на ней изображения, но кроме этого имеет возможность быть зафиксированной в нажатом состоянии до наступления определенных событий.

У этой кнопки также есть свойство Caption, однако чаще всего оно остается пустым: значение кнопки полностью передается только

изображением. Особенностью этого вида кнопок является свойство Grouplndex

(индекс группы). Если он равен О, то у кнопки отсутствует фиксация. Если Grouplndex >О и при этoмAllowAllUp = true, то кнопка по щелч­ку нажимается и остается в нажатом состоянии до повторного щелч­

ка. Если есть группа кнопок с одинаковым ненулевым значением

свойства Grouplndex и установленным свойством AllowAllUp, то одно-. временно нажатой может быть только одна из кнопок: при нажатии на другую кнопку из этой группы первая отщелкивается. Щелчок по нажатой кнопке приводит к ее освобождению. Если же Allow AllUp = false, то при щелчке на нажатую кнопку ничего не происходит, поскольку

состояние, когда ни одна кнопка из группы не нажата, запрещено.

Можно сказать, что в таком варианте кнопки работают аналогично радиокнопкам, которые ниже будут рассмотрены подробнее.

Состояние кнопки во время работы приложения можно узнать по свойству Down логического типа. Оно истинно, если кнопка зафик­сирована в нажатом состоянии, и ложно в обратном случае.

Радиокнопки (RadioButton) - элементы, которые, будучи соб­

раны в одну группу, предоставляют пользователю возможность вы­

брать один из взаимоисключающих вариантов.

Проще всего создавать и редактировать такие группы, используя

компонент RadioGroup - панель группы радиокнопок. Эта панель

содержит регулярно расположенные радиокнопки (рис. 8.6). * Надпись вверху панели задается свойством Caption, а надписи

отдельных кнопок - свойством ltems, цмеющим тип TStrings. Щелк­нув на кнопку с многоточием в соответствующем поле Инспектора

объектов, вы можете вызвать Редактор списка (String List Editor). Количество пунктов соответствует количеству введенных строчек.

Свойство Columns позволяет расположить кнопки в несколько столбцов. По умолчанию Columns = 1, т. е. кнопки размещаются в

одну колонку. Itemlndex содержит индекс выбранной кнопки. По умолчанию значение этого свойства -1. Это означает, что ни одна кнопка не выбрана.

* Регулярность ~равномерное расположение по высоте. - 101 -

Page 102: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Иногда целесообразнее использовать нерегулярное расположение радиокно­

пок, такую возможность дают объекты

RadioButton, расположенные на панели GroupBox. Эта панель только служит кон­тейнером для других элементов, в данном

случае - радиокнопок, поэтому главным

Рис. 8.6. Объект RadioGroup ее свойством будет заголовок, аналогич-ный заголовку компонента RadioGroup.

Радиокнопки, размещенные на панели, имеют каждая свое свойство

Caption. Также они имеют свойство Checked, определяющее, выбрана ли та или иная кнопка. Специфика элемента управления позволяет

выбрать только одну радиокнопку. На этапе проектирования в Checked должно быть установлено значение true для одной из кнопок.

Радиокнопки можно размещать как на панели GroupBox, так и на обычной панели (Panel) или прямо на форме. Объединение их в груп­пы будет происходить автоматически для всех радиокнопок, распо­

ложенных на одном объекте.

Индикаторы с флажком (CheckBox) внешне схожи с компонен­том RadioButton, однако имеют несколько другое назначение: если набор радиокнопок предоставляет пользователю выбрать один из

взаимоисклюЧающих вариантов, то каждый индикатор с флажком позволяет установить или снять какую-либо опцию. В данном случае

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

По умолчанию возможны два состояния индикатора: флажок ус­тановлен (State = cbChecked) и флажок снят (State = cbUnchecked), однако если установить AllowGrayed = true, то будет возможно и третье состояние - промежуточное ( cbGrayed), когда установленный флажок окрашен в серый цвет. Все эти свойства можно устанавливать ·· как во время проектирования, так и программно.

Индикаторы с флажком могут использоваться одновременно для

установки опций и для отображения их текущего состояния. Во время работы приложения состояние индикатора можно про­

верять по значению свойства Checked. Оно истинно, если индикатор установлен (его свойство State равно cbChecked), и ложно в осталь­ных двух случаях.

Как и у радиокнопки, содержимое и положение заголовка задает­

ся свойствами Caption и Alignment. Аналогично компоненту RadioGroup, представляющему собой

простой способ группировки радиокнопок, существует компонент

CheckListBox (рис. 8.7), который позволяет быстро разместить на

- 102 -

Page 103: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi {справочное приложение)

форме несколько близких по смыслу индикаторов, а также выделить Их общей рамкой.

Элементы списка содержатся в свойстве ltems, имеющем тип TStrings, т. е. обращаться к отдельной строке (элементу списка) можно как к элементу массива по ее индексу. Нумерация начинается с

нуля. Изменить этот список во время работы мож-но, используя методы класса TStrings (см. Help).

Рис. 8. 7. Объект CheckListBox

Свойство Sorted позволяет сортировать список по алфавиту. Если свойство установлено, то каждый вновь добавляемый элемент будет располагаться не в конце списка, а в соответствии со своим наиме~

нованием.

Состояние же самих индикаторов отображается в свойствах Checked и State. Оба они являются массивами, только первое является массивом логического типа, а второе типа перечисления. Эти свойства можно

просматривать или устанавливать программно:

CheckListBoxl.Checked [О) := true; CheckListBoxl.State [10 cbGrayed;

В этом примере первый индикатор списка устанавливается в со­стояние «выбраю>, а одиннадцатый - в промежуточное состояние. Очень удобно проверять или устанавливать значения индикаторов с помощью циклов for.

Важной чертой компонента является событие OnClickCheck. Оно возникает при каждом щелчке пользователя по индикатору (измене­

нии состояния). В этот обработчик не передается номер строки, в которой произошло изменение, но изменение индикаторов можно проверить из массивов, рассмотренных выше.

8.4. Списки К спискам на первых двух страницах палитры можно отнести та­

кие компоненты, как ListBox, ComboBox, а также ColorBox (рис. 8.8). Основная их функция - позволять пользователю выбирать из спис­ка одно значение (в случае ComboBox и ColorBox) или несколько значений (в случае ListBox).

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

Свойство MultiSelect компонента ListBox, установленное в true, определяет возможность выбрать несколько элементов списка. Если установлено свойство ExtendedSelect, то множественный выбор про­исходит с использованием клавиши Shift.

- 103

Page 104: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

ListBo:-i а

ь с

d

Рис. 8.8. Списки

Если выбрано несколько строк сразу, то проверить, какие именно

выделены, можно по свойству Selected[lndex: lnteger] - массиву

переменных логического типа. Если множественный выбор запрещен,

то можно воспользоваться свойством ltem 1 ndex, которое содержит номер выбранного пункта (нумерация с нуля); если ничего не выбра­но, его значение будет равно -1.

Также есть свойство Columns, определяющее количество столбцов списка, и Sorted, устанавливающее сортировку элементов по алфа­ви1у.

Компонент ComboBox может принимать несколько вариантов внеш­него вида в зависимости от значения свойства Style. Существует пять возможных значений этого свойства:

1. csDropDown - выпадающий список с полем ввода для набора

текста вручную. Высота поля ввода и расстояние между пунк­

тами списка определяются высотой текста.

2. csSimple - поле ввода. После начала ввода предлагается за­

вершение из списка, если имеется пункт с совпадающими пер­

выми символами.

3. csDropDownlist - выпадающий список без возможности руч­

ного ввода текста. Пользователь может только выбрать один из

перечисленных в списке вариантов. Высота поля ввода и расстоя­

ние между пунктами списка определяются высотой текста.

4. csOwnerDrawFixed - то же, что предыдущий, разница в том,

что высота поля ввода и расстояние между пунктами списка

задаются значением свойства ltemHeight.

5. csOwnerDrawVariaЫe - то же, что предыдущий, но пункты спис­

ка могут иметь различную высоту. Этого можно достичь, изменяя

свойство ltemHeight в обработчике события OnMeasureltem. Для остальных стилей списка это свойство программно недоступно.

- 104 -

Page 105: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение)

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

Как и в предыдущем случае, имеется свойство Sorted. Список выбора цветов аналогичен по функциональным возмож­

ностям комбинированному списку. Разумеется, в нем нет свойства

Style и нет возможности редактировать состав при проектировании формы.

8.5. Dстаnьные компоненты Объединять в отде.льные группы оставшиеся компоненты боль­

шого смысла нет, поэтому просто рассмотрим их по порядку пере­

числения в табл. 8.2.

ScrollBar Основные его свойства - Position, Min и Мах. Последние два

задают соответственно нижнюю и верхнюю границы диапазона, тог­

да как первое задает текущее выбранное значение в этом диапазоне. Все три свойства - переменные целого типа. Например, если Min = О,

а Мах = 5, то Position может принимать только шесть значений (от О до 5), а ползунок, соответственно, шесть положений.

Свойство Кind, принимая значения trHorizontal или trVertical, за­дает горизонтальное или вертикальное положение объекта.

LargeChange задает количество пунктов, на которые перемеща­ется ползунок при нажатии клавиш PgUp или PgDn. При нажатии стрелок вверх и вниз ползунок перемещается на 1 пункт.

PageSize.зaдaeт размер ползунка в единицах диапазона (от Min до Мах).

Компонент ScrollBar (рис. 8.9) предназначен для прокрутки со­держимого окон и форм. В обработчике событий OnScroll програм­мистом определяется, что именно происходит, если изменяется по­

ложение бегунка. Поскольку большинство объектов содержат уже встроенные линейки прокрутки, ScrollBar чаще используется для предоставления возможности выбора значения из заданного диапа­

зона: крайние положения ползунка соответствуют ГJ?аницам диапа­

зона, а возможные промежуточные положения ползунка соответству­

ют остальным значениям из этого диапазона.

Рис. 8.9. ScrollBar

- 105 -

Page 106: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

lmage Многие визуальные компоненты имеют свойство Canvas, оно поз­

воляет рисовать на объекте с применением таких методов, как Аге, Ellipse, Floodfill, LineTo, Rectangle и многих других. Однако при рисо­вании таким способом возникают проблемы с обновлением изображе­ния при частичном перекрытии его другими окнами. Приходится до­

писывать обработчики событий, которые бы перерисовывали нанесен­ное изображение при каждом изменении, произошедшем с формой.

Компонент lmage освобождает программиста от этой задачи и са­мостоятельно отслеживает состояние изображения, перерисовывая

его при необходимости. Рассмотрим пример рисования на канве объекта Image 1:

Imagel.Canvas.MoveTo(20, 20); Imagel.Canvas.LineTo(SO, 50);

Здесь графический курсор сначала перемещается в точку с коррди­натами Х = 20 и У= 20. Координаты берутся относительно левого верхнего угла объекта Imagel. Второй строчкой приведенного при­мера рисуется линия из текущего положения графического курсора

(20, 20) в точку с координатами Х = 50, У= 50. С помощью стандартных методов рисования на канве можно со­

здавать относительно сложные изображения. При этом не требуется

изменять код, если разработчик решит переместить область изобра­жения в другое место формы, поскольку система координат пере­местится вместе с объектом Image 1.

Однако чаще этот компонент используют для вывода изображений

из файлов. В свойство Picture можно занести имя .bmp или .ico файла. Для

этого нужно нажать кнопку с многоточием справа от соответствую­

щего поля в Инспекторе объектов. Откроется уже знакомый вам по компоненту BitBtn диалог открытия файла (см. рис. 8.5), в котором можно будет выбрать необходимый файл.

Также для сохранения и считывания изображения из файла во вре­

мя работы приложения существуют два предопределенных метода:

procedure LoadFromFile(const FileName: String); procedure SaveToFile(const FileName: String);

например:

Imagel.Picture.LoadFromFile('C:\Bitmap.bmp');

С помощью свойств Stretch (растяжение изображения до размеров объекта класса Image), Proportional (пропорциональность растяжения),

- 106 -

Page 107: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение)

AutoSize (автоматическое изменение размера объекта класса Image до размеров выбранного изображения) и Transparent (прозрачность всех пикселей, цвет которых совпадает с цветом нижнего левого пик­

селя) можно определить внешний вид изображения. Свойство Center центрирует выбранное изображение на площади объекта.

Shape Компонент Shape используется для добавления на форму геомет­

рических примитивов и имеет одноименное свойство, определяющее его форму. Его можно задавать как во время проектирования, так

и в процессе работы приложения:

Shapel.Shape : s rcle;

Данная строка изменит форму объекта Shape 1, сделав его круглым. Размеры определяются текущими свойствами Width и Height.

Свойство Brush определяет цвет и способ штриховки заполне­ния:

Shapel.Brush.Color : clGreen; Shapel.Brush.Style : bsDiagCross;

Эти строки устанавливают цвет заливки зеленым, а саму заливку

делают диагональной клеткой.

Как правило, этот компонент используется для декоративного

оформления формы или в тех случаях, когда на форме пользователю

предоставляется возможность манипулировать простейшими геомет­

рическими объектами.

Bevel Этот компонент в отличие от компонента Panel не может исполь·

зоваться для группировки, например, радиокнопок, но позволяет

зрительно выделить несколько объектов общей рамкой. Свойства, использующиеся для задания внешнего вида компонента Bevel, Shape и Style.

ScrollBox Этот компонент предназначен для создания на форме области,

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

объект будет помещен на форму. Например, в объект рассматривае· мого типа может быть помещена метка с текстом, превосходящая по

размеру сам объект. В этом случае отображается только часть метки

- 107 -

Page 108: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

и появляются линейки прокрутки, позволяющие увидеть остальную ее часть.

Чтобы разместить в ScrollBox несколько объектов, полезно быва­ет увеличить контейнер, а после завершения размещения уменьшить

его обратно.

Splitter · Этот компонент является разделителем и применяется в тех слу­

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

1. Разместите на пустой форме панель (Panel). Задайте ее свойст­ву Align значение alTop.

2. Запустите приложение и попытайтесь изменить размер панели,

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

те приложение.

3. Разместите на форме разделитель (Splitter).

4. Задайте его свойству Align значение alTop.

5. Задайте его высоту (Height) равной четырем пикселям.

6. Запустите приложение и попытайтесь перетащить мышкой разделитель вниз. Разделитель должен перетаскиваться, а вмес­

те с ним должна изменяться высота панели.

Таким способом можно разместить целый ряд панелей, отделенных друг от друга объектами типа Splitter.

Одним из полезных свойств разделителя является свойство MinSize -минимальный размер панелей, между которыми находится этот ком-

понент.

Событие OпMoved наступает после того, как разделитель был

перемещен на новое место и пользователь отпустил кнопку мыши.

В обработчике этого события можно предусмотреть действия, необ­

ходимые для корректной работы приложения, например, сортировку элементов на панели, проверку правильности их размеров и взаим­

ного расположения.

ControlBar Этот компонент предоставляет широчайшие возможности по со­

зданию инструментальных панелей. Достаточно разместить на нем,

как на панели, несколько более мелких компонентов. Задать им свой­

ства DragMode = dmAutoшatic и DragKind = dkDock - и во время работы приложения их можно будет перетаскивать по этому контей­неру, меняя местами и располагая в любом порядке. А если задать

- 108 -

Page 109: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное приложение)

свойство AutoDrag панели как true, то при перемещении за границы контейнера элементы начнут отцепляться от панели и оформляться

в отдельные окна.

Chart Компонент Chart (рис. 8.1 О) происходит от типа TPanel и, как

следствие, имеет все свойства компонента Panel. Проще говоря, Chart - это стандартный компонент типа TPanel с большим набором дополнительных возможностей для вывода графиков. Chart является панелью для размещения на ней объектов типа TSeries.

Примечание Во встроенной справочной системе Delphi имеется довольно обширный и подробный раздел, который называется TeeChart User Guide.

Свойства панели графиков и самих графиков можно задавать на

этапе проектирования приложения с помощью многостраничного

диалога Editing Chart (рис. 8.11 ), который вызывается по щелчку правой кнопки мыши.

При создании панель появляется на форме пустой и сама не име­ет средств для отображения последовательностей чисел в виде гра­фиков. Панель имеет свойство Canvas, что позволяет использовать примитивную графику. Для отображения на панели графика нужно сначала создать объекты Series. Это можно сделать из диалога редак­тирования свойств диаграммы, страница Chart, вкладка Series, кноп­ка Add. Появляется еще один диалог, позволяющий выбрать вид отоб­ражения конкретного графика: линейный, точечный, круговая диа­грамма, столбчатая диаграмма и т. д. При добавлении графиков на панель они отображаются в общем виде на форме. В окне запущен­

ного приложения панель графиков будет оставаться пустой до тех пор, пока не будут указаны конкретные значения. Это можно сделать, используя метод AddXY. Например:

for i := О to 50 do Seriesl.AddXY(0.02 * Pi * i, Sin(0.02 * Pi * i), ", clRed);

Этот цикл попиксельно добавляет график синуса, отображаемый красным цветом. Аналогично можно брать значения из какого-либо массива значений или из файла с данными.

Для того чтобы очистить серию и тем самым стереть график и под­готовить его к приему новых данных, применяется метод Clear.

Chartl. Ser ies [ 1] . Clear;

или

Seriesl.Clear;

- 109 -

Page 110: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Азбука Delphi: программирование с нуля

Рис. 8.1 О. Объект Chart

~ Pi 11 Series1

~~11 Serie.:~

Рис. 8.11. Диалог редактирования свойств графика

- 110 -

Page 111: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

Глава 8. Библиотека компонентов Delphi (справочное nр~ложение)

Такая строка удалит первый график с панели; теперь в этот график можно вводить новые значения аргумента и функции.

Если необходимо предоставить пользователю возможность про­сматривать на выбор часть графиков из некоторого набора, то имеет

смысл использовать объекты CheckBox. Например, пользователь мо­жет выводить тот или иной график на панель, установив соответствую­

щий флажок, и убирать, сняв его. Это можно реализовать, например,

следующим кодом:

if Checkboxl.Checked then Seriesl.Active := true

else Seriesl.Active := false;

Написав аналогичный код для остальных графиков, можно пре­

доставить пользователю широкие возможности по анализу и сравне­

нию данных.

В этой главе была рассмотрена работа практически со всеми ком­понентами первых двух страниц Палитры компонентов. Именно с

этими страницами начинающий пользователь работает больше всего. Остальные компоненты, как правило, либо представляют собой рас­ширение компонентов первых двух страниц, либо применяются в очень специфических задачах (см. табл. 8.1 )~ которые не приходится решать начинающим разработчикам приложений в Delphi.

Page 112: ПРОГРАММИРОВАНИЕ С НУЛЯmsk.edu.ua/ivk/Informatika/Books/Programmirovanie/Azbuka... · 2014-05-02 · модулей, включенных в проект. Для

СИБИРСКОЕ УНИВЕРСИТЕТСКОЕ ИЗДА теnьсrво

Дпя писем: Тел./факс:

Отдел продаж:

630058, Poccиst. r. Новосибирск. а/я 134 (383) 332·52~32

[email protected] Москва: (495} 661-09-96 Новосибирск: (383) 330-50-19

книга - почтой: [email protected]

Информация дnя авторов, актуальный прайс-лист и подробное описание продукции издательства - на официальном сайте

www.sup99.ru

Бескоровайный Илья Викторович

АЗБУКА DELPHI: ПРОГРАММИРОВАНИЕ С НУЛЯ

Редактор О. И. Сал.мина Менеджер проекта О. И. Ca;r1Jmнa

Обложка В. Ю. Анттюв, О. И. Сш1.J1-1uна

Корректоры Л. А. Федотова, А.1. А. Русанова Комш>ютерная верстка М С. Дрожжин

Соответствует гигuенuческши требованиям к книж·ным изданuя."11. (сан.-эпuд. закл. }'{о 54.НС.05.953.П.013186.12.05 от 26.12.05)

Подписано в печать 19 .10.07. Формат 6Ох9О/1 б. Бумаrа газетная. ечать офсетная. Усл. печ. л. 7. Уч.-изд. л. 5. Тираж 3100 экз. Заказ № 1207

Сибирское университетское издательство

630058, Новосибирск, ул. Русская, 39

ОАО «Советская Сибирь» 630048, Новосибирск, ул. Немировича-Данченко, 104