Текст
                    1ЩРЕ.П. Истомин R R ?	« M
B.B Н0ВИК081 M B H j
!
t > I
| ’ I
ВЬ'с0К0^0ВНЕВЫ
МЕТОДЫ I
и вйЖ. I
I >
 ,
W
S
I
jp3
I	* $
f I
? I
I t :
I I j
•> &
:«• ms '•
. • » ‘i
J АНДРЕЕаСКВДиаддтЕльскийдом

РОССИЙСКИЙ ГОСУДАРСТВЕННЫЙ ГИДРОМЕТЕОРОЛОГИЧЕСКИЙ УНИВЕРСИТП Е.П. Истомин, В.В. Новиков, М.В. Новикова ВЫСОКОУРОВНЕВЫЕ МЕТОДЫ ИНФОРМАТИКИ И ПРОГРАММИРОВАНИЯ учебник Рекомендозан Учебно-методическим объединением по образованию в области прикладной информатики г качестве учебника для студентов ВУЗов, обучающихся по специально- сти 351400 «Прикладная информатика (по областям)» и другим междисциплинарным специальностям 1 groHjW'l щи! IOihkh ООО «Андреевский издательский дом» САНКТ-ПЕТЕРБУРГ, 2006
УДК 681.3.06.: 800 92 ББК 22.18 И 89 Истомин Е.П., Новиков В.В., Новикова М.В Высокоуровневые методы информатики и программировании: Учебник — 016. ООО «Ан- дреевский издательский дом», 2006 г. - 228 с. ISBN 5-902894-0'7-7 Рецензенты: профессор Военно-морской академии им. Н.Г. Кузнецова, заслуженный дея- тель науки и техники РФ, доктор технических наук, профессор Петров В.А., доктор технических наук, профессор Григорьев Ю.Д. Учебник «Высокоуровневые методы информатики и программирования», являясь продолжением учебника «Информатика и программирование» авторов Истомина 1 11., Неклюдова С.Ю. и Романченко В.И., расширяет возможность подготовки специалистов широкого профиля. В кни1 с подробно рассмотрены вопросы модульного и структурного программирования, объектно-ориентированное программирование и технология создания программ в среде DELPHI. Материал изложен в соответствии с Государственным стандартом по специально- сти «Прикладная информатика ino областям)» и требованиями современных технологий программирования. Данная книга может быть использована в качестве учебника для студентов выс- ших и средних учебных заведений, в тоже время ею могут воспользоваться специалисты в различных отраслях науки для непосредственной творческой и профессиональной работы, требующей знания высокоуровневых методов программирования. Истомин Е. П., Новиков В. В., Новикова М. В. Высокоуровневые методы информатики и программирования Учебник Редактор: Воронина О Н. Верс~ка: Истомин Д.Е. Лицензия ЛП № 000216 от 14.07.1999 г. ООО «Андреевский изда’ельский дом» 197738, Санкт-Петербург, пос. Репино, Приморское шоссе, д. 394 E-mail biom@nm.ru Подписано в печать 12.01.2006 г. Печ. листов 14. Тираж 2000 экз. Отпечатано с готовых диапозитивов в ООО «Бильбо» © Истомин Е.П., Новиков В.В., Новикова М.В. © ООО «Андреевский из ia гельский дом»
ВВЕДЕНИЕ Программирование представляет собой сферу действий, направленна ю на создание программ. Программирование может рассматриваться как наука и как искусство. В свою очередь программа - это последовательность команд компью- тера, приводящая к решению задачи Программа является результатом интеллек- туального труда, для которого характерно творчество. Про1 раммы предназначе- ны для машинной реализации задач. Задача представляет собой часть проблемы, подлежащей решению с помощью технических средств, а приложение (синоним программа) - реализованное на компьютере решение данной задачи. 1 аким обра- зом. можно заключить, что приложение - это программная реализация решения задачи на компьютере. В свою очередь программное обеспечение (ПО) является совокупностью программных продуктов и технической документации к ним. а программный продукт (ПП) - это комплекс взаимосвязанных программ, предна- значенный для реализации определенной задачи массового спроса. Программы являются кри герием развития вычислительной техники, они делятся на у ти питы (для нужд разработчиков) и программные продукты (для удовлет ворения потреб- ное гей пользователя). В настоящее время при создании npoi раммных продуктов возникает ряз проблем, основными из которых являются следующие: 1. Быстрая смена вычислительной техники и алгори гмических языков. 2. Не стыковка ЭВМ друг с другом (VAX и IBM). 3. Отсу гс в, е полного взаимопонимания между заказчиком и исполни- телем к разработанному программному продукту. 11 астоящий учебник направлен на изучение следующих аспектов про- граммирования: новейших направлений в области создания з ехнологий программиро- вания; законов эволюции программного обеспечения; со здания мо [ульных программ. - элементов теории модульного программирования; объектно ориентированного программирования; объектного типа данных: переменных объектного типа; - конструкторов и деструкторов; инкапсуляции, наследования, полиформизма; классов и объектов; ос обенностей программирования в оконных операционных средах; основных стандарт ных модулей, обеспечивающих работу в оконной операционной системе: ин тегрированной среды программирования; системы окон разработки, системы меню: - основ визу а зьного проз раммирования: компонентов и их использование; ра смешения нового компонента и реакции на собы гие.
4 Глава 1. Новейшие наг равления в области создания техно~ю~ии программирования ГЛАВА 1. НОВЕЙШИЕ НАПРАВЛЕНИЯ В ОБЛАСТИ СОЗДАНИЯ ТЕХНОЛОГИЙ ПРОГРАММИ- РОВАНИЯ В основе тог о или иного языка программирования лежит некоторая । руко- водящая идея, оказывающая су шественное влияние на с гиль соответствующих программ. 1.1. Структурное программирование Структурное программирование - методология npoi раммирования, бази- рующаяся на системном подходе к анализу, проектированию и реализации про- граммного обеспечения. Эта методология родилась в нача ie 70-х i одоь и i (каза- лась настолько жизнеспособной, что и до сих пор является основной в большом количестве проектов, основу' этой технологии составляют следующие положения: • Сложная задача разбивается на более мелкие, функционально лучше управляемые задачи. Каждая задача имеет один вход и один выход. В эт ом случае управляющий поток программы состоит из совоку пнос ги элементарных подзадач с ясным функциональным на значением. • Простота управляющих структу р, используемых в задаче. Это положе- ние означает, что логически задача должна состоя гь из минима шной, фу нкцио- нально полной совокупност и достаточно простых управ тяющих стру ктур. В каче- стве примера такой системы можно привести а тгебру' логики, в которой каждая функция может быть выражена через функционально потную систему: дизъюнк- цию, конъюнкцию и отрицание Разработка npoi раммы должна вестись поэтапно. Па каждом эт але до гж- но решаться ограниченное число четко поставленных задач с ясным пониманием их значения и роли в контексте всей задачи. Если такое понимание не достигает- ся, это говорит о том, что данный этап слишком велик, и его нужно разделить на более элементарные шаги. Согласно требованиям структурною программирова- ния, наиболее часто детально проработанные алгоритмы изображав ) гея в виде блок-схемы. При их разработке используются условные обозначения согласно ГОСТу («следование», «ветвление», «цикл») (рис. 1). Рис. 1. Фрагменты б. юк схемы алгоритма 1.2. Нисходящее проектирование Метод предполагает последовательное разложение функции обработки данных на прост ые функциональные элементы (’ сверху вниз"). В резуль гате строится иерархическая схема, которая отражает состав и
В лСОКЛУг’ОВНЕВЫЬ МЕТОДЫ ИНФОРНАВ Кй И ПРОГРАММ 'РОВАНИЯ 5 взаимоподчиненность отельных функций. Она ноет название функциональная структура алгоригма (ФСА) приложения в ко горой отражаются- • це ти предмет ной облает и (цель-по, [целы; • состав при тожений (задач обработ ки", обеспечивающих реализацию поставленных це тей; • характер взаимосвя ш приложений с их основными характ еристиками; • функции обработки тайных. Рассмотрим функциональную ст руктуру приложения (рис. 2). Рис 2.1 ]ример функциональной стру ктуры при южения Подобная структура отражает состав и взаимосвязь функций обработки информации для реа тизации приложений, не раскрывая логику выполнения каж- дой отдельной функции. Разложение до тжно носить строго функциональный харак гер. т.е. о г тель- ный элемент ФСА описывает законченную содержательную функцию обработки информации, которая предполагает опредетенный способ реащзации на про- граммном уровне. Фу нкции ввода/вывода информации отделяют от фу нкций вычислитель- ной или логической обработки данных. Некоторые функции например Ф2, ФМ далее неразложимы на состав- ляющие, они предполагают непосредственну ю программную реализацию. Дру гие функции Ф2... могут быть представлены в виде структурного объединения более простых функций, например Ф11, Ф12 .. Для всех функций-компонентов осуще- ствляется самостоятельная программная реализация составные функции типаФ1, ФМ реализуются как программные модули, управляющие функциями - компо- нентами, например, в виде программ-меню. По частоте использования функции делятся на однократно выполняемые и повторяющиеся.
6 Главу. 1. Hoerfti in* ндправлез ия в области создания технэлогиЕ прсгрАммиревА! ,1я. 1.3. Концепция модульного программирования Так же как и для структурной технологии программирования, концепцию модульно! о программирования можно сформулировать в виде нескольких поня- тий и положений: • Функциональная декомпозиция задачи - разбиение большой задачи на ряд более мелких, функционально самостоят ельных подзадач - модулей. Моду ги связаны между собой только по входным и выходным данным. • Модуль - основа концепции модульного программирования. Каждый модуль в функциональной декомпозиции представляет собой "черный яшик'г с одним входом и одним выходом. Модульный подход позволяет безболезненно производить модернизацию программы в процессе ее эксплуатации и облегчает ее сопровождение. Дополнительно модульный подход позволяет разрабатывать части программ одного проекта на разных языках программирования, после че, о с помощью компоновочных средств объединять их ь единый загрузочный модуль. • Реализуемые решения должны бы гь прост ыми и ясными. Если назна- чение модуля непонятно, то это говори г о т ом. что декомпозиция начальной или промежуточной задачи бы та проведена недостаточно качественно. В этом слу чае необходимо еше ра з проанализировать задачу и, во зможно, провес ги дополни- тельное разбиение на подзадачи. При наличии сложных мест в п| юекте их нужно подробнее документировать с помощью продуманной системы комментариев. Этот процесс нужно продол жать до тех пор, пока действительно не удасться до- биться ясного понимания назначения всех модулей задачи и их от имального со- четания. • Назначение всех переменных моду, зя должно бы гь описано с помощью комментариев по мере их определения 1.4. Объектно-ориентированное программирование (ООП) Идея OOII заключается в с гремлении связать данные с обрабатывающими эти данные процедурами в единое целое - объект. ООП основано на трех важн зй- ших принципах, придающих объектам новые свойства. Этими принципами явля- ются инкапсуляция, наследование и по. шморфизм. • Инкапсуляция - объединение в единое це юе данных и алгоритмов об- работ ки этих данных. В рамках ООП данные называются полями объекта, а алго- ритмы - объектными методами. • Наследование - свойство объектов порождать своих «потомков». Объ- ек г - «потомок» авт оматически наследует о г «родл гелей» все поля и мет оды. мо- жет дополнять объек гы н эвыми полями и заменягь (перекрыва гь) методы «роди- теля» или дополнят ь их. • Полиморфизм - свойство родственных объектов н.е. объектов, имею- щих одного общего «родителя») решать схожие по смыслу проблемы разными способами. 1.5. CASE-системы Предел авьение о CAS1: - комплексах связано в нашем с<, знании с чем-то, не имеющим от ношения к обычному программированию. В Америке из-за сильнейшей конкуренции CASE -средства используются подавляющим большинством фирм - разработ чипов программно! о обеспечения. Мощный толчок CASE-cpe, гс гва получили в пору внедрения объектно-
ВНССЖОУРОВНЕВЬ'Е МСТСДЫ ИНФО ’МАТИКИ И ТРОГТАММИРОВАНИЯ 7 ориентированной технологии разработки ПО. koi да ст арого. проверенного време- нем метода проектирования 'сверху вниз" с гало явно недост а точно. К тому же появились технологии объектного моделирования В< ioch, ОМТ, UM L, сами по себе весьма сложные для привя жи к я 1ыкам программирования. чтобы опериро- вать ими вру чную. Сегодня лидирующей ь мире CASE-системой считае гея Rational Rose корпорации Rational Software Система Rational Rose нацелена на создание моде- лей с использованием языка Unified Modeling Language (UML). Кстати, L'ML стал стандартным языком объег: гно-ориент ированной разработки не без подачи Ra- tional Software, которая не только выпускает программные продукты, где исполь- зуются IIML, но и активно принимас г участие в организации Object Management Group (OMG). занятой созданием и обнов гением спецификаций языка UML. тех- нологии распределенных вычислений CORBA и т.д. В компании Rational работа- ют три создателя и евангелие га объектно-ориентированной разработки и языка UML. Это 1 ради Буч. Айвар Джекобсон и Джим Рамбаух. Последняя версия CASE-системы компании Rational Software Rational Rose 98 успешно применяется для создания коммерческо! о ПО и поддерживает популярные языки npoi раммирования Java. Cu++, Смотток. Ада, Visual Basic, Power Builder и 1 orte. Кроме т ого. пакет Rose 98 способен генерирова гь описания на языках Interface Definition 1 .anguage HDD для приложений CORBA и 1 )ata Definition Language (DDL) для приложений доступа к ба 1ам данны к, в том числе и Oracle 8. Разумеется, поддержка того или иного языка программирования зависит от того, о какой редакции пакет a Rational Rose 98 идет речь. К примеру, нельзя требоват ь многого от самого прост oi о варианта пакета - Rose 98 Modeler Edition. Зато Rose 98 Enterprise Edition оснащен от души. 11ельзя не от метить, что система Rose - признанный лидер среди средст ь визуального моделирования, и, используя ее, можно интерактивно разрабатывать архитектуру создаваемого прил зжения, генерировать его исходные тексты и па- раллельно работать над докумен ированием разрабатываемой системы. С помо- щью Rational Rose можно создана гь новые модели на базе обратного разбора дво ичных сот модулей или исходные тексты при1 тадных программ и библиотек классов. Преимущества о г применения Rational Rose 98 значи гельны. 1. С окращение цикла разработки при южения. 2. Увеличение продукт ивности работы программистов. 3. Улучшение потребительских качеств создаваемых программ за счет ориен гании на поль ювате гей и бизнес. 4. Способность вести большие проекты и i руппы проектов. 5. Возможное гь повторного использования уже созданного 1IO за счет упора на разбор их архитектуры и компонентов. 6. Язык UML слу жит универсальным "мостиком" между разработчиками из разных отделов. 1.6. Технологическая схема решения задач Технологическая схема, в которой по тьзоват еть. же 1ающий реши гь свою задачу на ЭВМ. обращается за консультацией к специалисту по а шоритмизации (формализации), а тот. в свою очередь, к программисту, создающему программу на основе фирма тьной модели решаемой задачи, сейчас отходит в прошлое. Она оказывается неэффект ивной по ряду причин. Например, пользова-
8 Глава 1. Новейшие t агравления в оьласти создания техноло им 1рограмми«ов^.ния. тель не всегда точно знает, чего он хочет, и алгоритмист, когда формализует за- дачу, поневоле упрощает ее, теряет или отбрасывает многое из того, что пользо- ватель знает, но либо не сообщил алгори гмисту, либо опрометчиво согласился на предлагаемые упрощения. Полученная после этого модель программируется и реализуется на ЭВМ. А пользователь явно не доволен. Только теперь он понял, что ему нужно, и видит, что ему дали не то. что ему необходимо. После этого на- чинается второй раунд взаимодействия, за ним, возможно третий, четвертый и т.д. v Почему так происходит9 Скорее всею, потому, что пользователь, рабо- тающий в областях, где формализация еще не проявила себя в полную силу - сей- час их принято называть плохо структурированными проблемными областями, - просто не ведает о том, какие же знания необходимо сообщить алгоритмисту о своей задаче, ч гобы полностью удовлетворить и его и себя. Возникает идея - убрать из технологической схемы алг оритмиста, сокра тить путь пользователя к ЭВМ: пусть он теперь со своей задачей обращается прямо к программисту. Правда, для этого нужно, чтобы программист повысил свой профессиональный уровень, овладел бы "смежной" профессией алгори гми- ста. Но тогда программисты станут более дефицитными, чем сейчас, ибо требова - ния к ним резко возрастут. А ведь армия программистов и так не успевает обслу- жить всех желающих, и если темпы роста пользователей не уменьшатся, то все население земного шара будет состоять из пользователей и программистов. Ясно, что этот путь тупиковый. К тому же он не решает основной про- блемы - прямого доступа пользователей к ЭВМ и не устраняет непонимания меж- ду пользователем и программистом, возникающим из- ia отсутствия у программи- ста знаний о проблемной области пользователя, а у пользователя - о способах ре- шения задач на ЭВМ А что если и программиста удалить из технологической цепи пользова- тель - ЭВМ? Это можно сдепат ь. если пользователи научатся программировать, станут профессионалами в двух областях - в своей собственной и в программиро- вании. Насколько это возможно? И сейчас существуют специашс гы. овладевшие искусством программирования настолько, что сами свободно работают с вычис- лительной машиной. Но таких специалистов не много, так как овладеть двумя совершенно разными профессиями - дело нелегкое. И, как правило, в одной из них человек остается все-таки полупрофессионалом. Есть ещё один путь приобщения специалиста к современной вычисли- тельной технике - это повышение возможностей самих ЭВМ, повышение уровня их "интеллекта”. Программиста можно убрать из технологической цепи решения задачи лишь тогда, когда в самой ЭВМ появиться "автоматический програм- мист", который будет взаимодействовать с пользователем и помогать ему coci ав- лять программы. Так возникает идея ЭВМ нового - пятого поколения. В отличие от ЭВМ предшествующих поколений новые машины должны иметь средства для интеллектуального взаимодействия с пользователем на его профессиональном естественном языке. Другими словами, не пользователь приближает ся к ЭВМ. а сама ЭВМ становится интеллектуальным собеседником и помощником пользова- теля. 1.7. Индустрия искусственного интеллекта Бум, возникший в конце семидесятых годов в искусственном интеллекте и приведший к созданию новой отрасли промышленности, не случаен. Его вызва- ли три причины:
Bbl С ОКОУРОВНЕВЬЕ Mb Oflol Иг ФОРМАТ ИКИ И ПГОГРАЧМИ 'ОВАШ'Я 9 1. Угроза всеобщей мобилизации насе ыния земного шара в программи- сты привела к идее пятого поколения ЭВМ. Но создание таких ЭВМ требует раз- работки средств автомагическог о выполнения функций алгоритмиста и програм- миста, ю есть интеллектуальных функций по г] ормализации задач и составлению npoi рамм для их решения. А это уже сфера искусственного интеллекта, ибо । >дно из толкований целей этой науки состоит как раз в у гверждении, чтс. она должна создавать методы автоматического решения задач, счи гающихся в человеческом понимании интеллектуальными. Это означает, что создание ЭВМ пятою поколе- ния невозможно без использования достижений, накопленных в искусственном интеллекте. 2. Развитие робототехнических малолюдных или безлюдных произ- водств. На современных промышленны к предприят иях происходит активное вне- дрение автоматических систем, в которых широко используются интеллектуаль- ные роботы. ] Iporpecc в этой области во многом зависит о г того, насколько робо- ты могут храни гь в своей памяти необходимую су мму знаний о профессии, кото- рой они овладевают. 3. Необходимость передавать на ЭВМ задачи из плохо структурирован- ных проблемных облас гей Именно для них нужно автоматизировать труд алго- ритмис га, его способность формализовать то, что с трудом поддается форматиза- ции. Путь решения пой проблемы - форматизация знаний, которые есть у про- фессионаюв в данной проблемной области, но хранятся в их памяти в виде не- формализованных соображений, умений и навыков. Такие профессионалы явля- ются экспер сами своего дела, а получаемые от них знания обычно называю^ экс- пертными. Если в базу знаний системы заложи гь знания подобного типа, то сис- тема будет называться экспертной. ЭВМ пя того поколения, интеллектуа гьные роботы, экспертные системы и многие другие интеллект уалвные системы об задают одним общим свойством: их работа основывается на знаниях, хранимых в базе знаний системы. Их част о так и называют - системами, основанными на знаниях. 1.8. Экспертные системы Экспертные системы могут не только найт и решение той или иной задачи, но и объяснить пользователю, как и почему оно получено. Э го означает, чт о в экспертных системах реагизована возможность ''самоанализа'', в них появилась возможность рассуждать о знаниях и манипу тировать ими. А значит появилась и возможность иметь знания о знаниях, т .е. метазнания С их помощью в эксперт - ных системах стала возможной оценка знаний с точки зрения их по шоты и кор- ректности. а также реализация ''функции любопытства", связанной с активным поиском связей между хранящимися в памяти знаниями, их классификацией и пополнением за счет ра шообразных логических процедур. В экспертных системах сделан важный шат - знания, хранящиеся в сис- теме, стали объект ом ее собственных исследований. Потенциально человек способен к овладению любым видом интеллекту- альной деятельности. Он может научиться играть и в шахматы, и в морской бой, и в любые другие игры, ибо он обладает универсальными мет алроцедурами, позво- ляющими ему создать процедуры решения конкретных инте । актуальных задач Раззитие теории искусственного интеллекта в конце шестидсся гых i одов началось с осоззания именно этого факта. У новой науки появился свой специфи- ческий объект исследований и моделирования - универсальные метапроцеду ры
10 Глава 1. Новейшие направления в области создания технологий программирование. программирования интеллектуальной деятельности. Bih числе имеются мета- процедуры общения, обучения, анали за нос принимаемой системой информации и многие другие. 11о центральное место здесь, несомненно, занимают те метапро- цедуры, которые связаны с накоплением знаний и использованием их при реше- нии интеллектуальных задач. Именно эти метапроцедуры находят свое воплоще- ние в экспертных системах. Существующие сейчас экспертные сис гемы принято делить на два класса, консультационные и исследовательские. Первые призваны давать советы, когда у пользователя возникает необходимость в них, а вторые - помо, ать исследователю решать интересующие его научные задачи. Система общения позволяет вводить в экспертную систему инф^ рмапию на естественном языке, ограниченном рамками профессиональной области, и < ip ганизует ведение диалога с по. шзователем. Эта система сообщает пользователю < непонятных для нее словах, о допущенных им ошибках, предлат ает наборы дей- ствий. которые пользователь при желании может выполни гь. Если пользователь еще не освоил "этику приема", го в дело включается блок обучения, в диалоговом режиме он постепенно обучает пользователя общению с ЭВМ, учит ej о решению задач, используя примеры. Пользователь может обращаться к этому учителю ко гда захочет - система всегда найдет время для пояснения непонятных пользоват е- лю моментов Решатель осу ществляет поиск вывода р. шения, нужного пользоват: тю на основе тех знаний, которые хранятся в ба se зганий системы. Он играет роль моз- гового центра системы. Чтобы функции решателя в консультационной эксперт- ной системе стали более понятными, рассмотрим конкретный пример. Предполо- жим, что в полевых условиях археолог столкнулся с находками, которые постави- ли его перед задачей датировки раскапываемого объекта. Известно, что точная датировка во многих случаях вещь весьма сложная. Она требует тщательного изучения находок, привлечения огромного по объему сравни тельного материала из находок других археологов, требует от археолога умения дета гь правильные логические выводы, выдвиг ать гипот е ты и отвергать их на основании найденно! о. При работах на раскопках рядом може г не быть т ех специалистов, которые moj ти бы оказать квалифицированную помощь. Именно для такой си гуации п] >е. назна- чена консультационная экспертная сис гема. В ее ба те знаний может храниться огромное количество накопленны к ранее фактов и у становленных < вязей между этими фактами, а также мнения (не всегда совпадающие между собой) ведущих специалистов в данной области. Когда археолеч через систему общения обращается к системе за консуль- тацией, то она может начать с того, что потребует ввести описание с.*ех тех нахо- док (на языке, понятном системе), которыми этот археолог располагает. Получив в свое распоряжение пи описания, экспертная система начинает формировать логический вывод. От исходных фактов, введенных в нее, и с помощью тех взаи- мосвязей. которые должны существовать между фактами, она выводит гипотезы, которые не противоречат наблюдаемым фактам. Если эта т ипотеза однозначна, то она сообщается пользователю. Нели имеет альтернативные возможное ги. т о экс- пертная система може г задать археологу дополнительные у гочняющие вопросы, например, о характ ере рисунков на ост а гках найденной керамики, i оторые еще не были сообщены системе. Если археолог не может сообщить системе никаких но- вых дополнительных сведений, то ему будет сообщено несколько гипот ез о дати- ровке. При этом каждая гипотеза может оцениваться некс горым весом дост овер- ности. Например, ответ может иметь вид "Данный объект относится к периоду А
ВЫСОКОУРОВН! ВНЕ * ЕТиДЫ И1 НиРМА'ИКИ И Г РАМ МИРО ВАНИЯ. 11 с достоверност ью 15% и к периоду В с достоверностью 85%". Если при дальней- ших раскопках будет обнаружен другой предмет, то он датируется периодом В, как наиболее вероятным. Д. 1я каждого вновь найденного предмет а могут быт ь получены вероят ноет и датировки, а затем все результ аты могут быть проанализи- рованы совместно. Информация в базе знаний не хранится, как зерно в элеваторе, просто сваленное в бункер. В этом случае база знаний не смогла бы обеспечить эффек- тивную работу решателя. В экспертной системе су шествует специальный ком- плекс средств с помощью которых в базе знаний наводится необходимый поря- док. Информация здесь классифицируется, обобщается, оценивается ее нетроти- воречивость. отдельные информационные единицы объединяются связями раз- личного типа. Другими словами, в базе знаний возникает стр\ кту рированная мо- дель проблемной области, в которой отсажены все ее особенности, закономерно- сти и способы решения задач Всеми этими процедурами заведует система под- держки базы знаний. Система объяснения - важнейшая от шчительная компонента экспертных систем. К ней пользовате ш может обращаться с вопросами типа "Что есть X?", "Как получен У?", "Почему получен У, а не Z?" и "Зачем нужен X?". За каждым таким вопросом скрывается свой комплекс процедур, выполнение кт орых позво- ляет дать пользоватечю интересующий его ответ. Вопрос "Что есть X?" требует выдачи пользователю всей информации о X, которой система располагает, чго может потребовать весьма непростых поисковых процедур в базе знаний. Эти процедуры реализуются в решателе, гак как во многих случаях для отвзта на во- прос пользователя надо из исходных фактов, хранящихся в базе, получить логи- ческим путем новые производные факты. Вопрос "Как получен У?" означает, чго пользователь хочет ознакомиться с гем, как рассуждала сис гема, шаг за шагом выводя из сообщенных ей пользова- телем фактов свое заключение. Для ответа га такой вопрос система объяснения должна обратиться в реша гель, в памяти которого, как на экране электронно- лучевой трубки с послесвечением, должен некоторое время сохраняться "трек" того пул и, кот орый прошел решатель. Вопрос "Почему получен У. а не Z?" требует от экспертной системы уме- ния ибосновыват ь отка з от гипотез. В том же решателе хранится информация об альтернативном выборе между У и Z. который один или не один раз возникал на пути поиска решения. В них "точках разветвления" система выбирала путь, ве- дущий к У. а не тот. который веп к Z. Испо тьзованные в этот момент соображе- ния, определявшие выби] >. выдаются пользователю. Наконец ответ на вопрос "Зачем нужен X?", возникающий в ситуации, ко- гда экспертная система просит пользователя ввести в нее информацию о X- тре- бует выполнения процедур обоснования необходимое ги сведений о X для полу- чения решения. Эти обоснования извлекаются из модели 1 щоблемной области, хранящейся в базе знаний. Возможны и друт ие типы вопросов пользователя к системе объяснения, но и приведенных достаточно чтобы понять сколь важна ее роль: только она де- лае г выдаваемые решения понятными и обоснованными для пользователя. Почти так же, как и консуль гативные. устроены исследовательские экс- пертные системы, но в них имеются еще и блоки, в iвторых выполняются все не- обходимые для специалиста расчеты. Можно сказать, что экспертные системы такого типа - это симбиоз ЭВМ пя того поколения и консультационных эксперт- ных систем.
12 Глава 1. Новейшие направления в области создания технологий программирования. 1.9. Законы эволюции программного обеспечения Проведем ассоциации компьютера с человеком. У компьютера есть орга- ны восприятия информации из внешнего мира - это клавиа гура, мышь, накопите- ли на магнитных дисках. У компьютера есть органы, "переваривающие” получен- ную информацию. - это центральный процессор и оперативная память. И наконец, у компьютера есть органы речи, выдающие результаты переработки. Современ- ным компьютерам, конечно, далеко до человека. Их можно сравнить с существа- ми, взаимодействующими с внешним миром на уровне ограниченного набора безусловных рефлексов. Этот набор рефлексов образует систему машинных ко- манд. На каком бы высоком уровне мы ни общались с компьютером, в конечном итоге все сводится к скучной и однообразной последовательности машинных ко- манд. Каждая машинная команда является своего рода раздражителем для возбу- ждения того или иного безусловного рефлекса. Реакция на этот раздражитель все- гда однозначная и "зашита” в блоке микрокоманд в виде микропрограммы. Эта микропрограмма и осуществляет действия по реализации машинной команды, но уже на уровне сигналов, подаваемых на те или иные логические схемы компью- тера. управляя различными подсистемами компьютера. В этом состоит так назы- ваемый принцип микропрограммного управления. Продолжая аналогию с челове- ком. отметим: для того, чтобы компьютер правильно питался, придумано множе- ство операционных систем, компиляторов сотен языков программирования. Но все они являются по сути лишь блюдом, на котором по определенным правилам доставляется пища (программы) желудку (компьютеру). Только желудок компью- тера любит диетическую, однообразную пищу - подавай ему информацию струк- турированную, в виде строго организованных последовательностей нулей и еди- ниц. комбинации которых составляют машинный язык. Таким образом, внешне являясь полиглотом, компьютер понимает только один язык - язык машинных команд. Программисту не нужно пытаться постичь значения различных комбина- ций двоичных чисел, т.к. еще в 50-е годы программисты стали использован ь для программирования символический аналог машинного языка, который назвали языком Ассемблера. Этот язык точно огражаег все особенное ги машинного язы- ка. Именно поэтому язык Ассемблера для каждого типа компьютера свой. Язык программирования - это специальный язык, на котором пишут ко- манды для управления компьютером. Языки программирования созданы для того, чтобы людям было проще читать и писать для компьютера, но они затем должны транслироваться (транслятором или интерпретатором) в машинный код, который только и может исподня гься компьютером. Языки программирования можно раз- делить на языки высокого уровня и языки низкого уровня. Язык низкого уровня - это язык программирования, предназначенный для определенного типа компьютера и отражающий его внутренний машинный код. Языки низкого уровня часто называют машинно-ориентированными языками. Их сложно конвертировать для использования на компьютерах с разными централь- ными процессорами, а также довольно сложно изуча гь, поскольку для этого 1 ре- буется хорошо знать принципы внутренней работы компьютера. Язык высокого уровня - это язык программирования, предназначенный для удовлетворения требований программиста; он не зависит от внутренних ма- шинных кодов компьютера любого типа. Я зыки высокого уровня использу ют для решения проблем и поэтому их часто называют проблемно-ориентированными языками. Каждая команда жыка высокого уровня эквивалентна нескольким ко-
ВЫСОКОУР.В HI ВЬИ MFl 3 I UH РОВНА ПК И l ПРОГ РДММИРОвАНЦЯ. 13 мандам в машинных кодах, поэт ому прог раммы написанные на языках высоко . > уровня, более компактны, чем аналогичные программы в машинных кодах. Ос- новные языки прог раммирования и об 1аст и их использования приведены в т аб- лице 1. Таблица 1 Язык Основное использование Описание Ада В обороне Высокого уровня Ассемб- лер Работ) . требующие де- тально! с контроля за аппа- раты м обеспечением, бы- строго исполнения и про- грамм ма того размера Быстрый и эффективный, но тре- бующий определенных у си лий и навыков Бейсик В образовании, бизнесе, дома Прост в изучении С Системное прог) >аммиро вание, универсальное про граммирование ] быстрый и эффективный, широко используется как универсальный язык C++ В объектно- ориентированном про- граммировании Основан на языке С Кобол Программирование в биз- несе Жестко орпен тирован на коммер- ческие задачи, легко научит ься. и э очень много операторов Форт Управление приложения ми Использует инверсную польскую запись Фортран Научная работа и вычис- ления О, нован на магемагических фор- мулах Лисп Искусственный интел 1ект Язык символов с репутацией трхдно изучаемого Модула-2 ( истемное программиро- вание и npoi раммирование в режиме реального време- ни, универсальное про- граммирование Высоко структурирован, предна- значен замени гь Паскаль для при- ложений "реально! о мира’’ Оберон Универсальное прог рам мирование Небольшой, компактный язык, соединяющий мног ие черты 11ас- каля и Моду па-2 1 [аскаль Универсальный язык Высоко с грук гурирован Пролог Искусственный инт еллект Символьно-логическая система программирования, в начале пре л- назначенная для решения теорем, но сейчас использующаяся чаще для решения задач, связанных с искусственным инт еллектом J —
14 глава 1 Новейшие направления в области создания технологии программирования Эволюция технических средст в персональных компьютеров привела к по- всеместному вытеснению старой "доброй” ОС MS-DOS значительно более мощ- ными системами Windows, программирование для которых существенно сложнее, чем программирование для MS-DOS. Разработчики систем программирования, и прежде всего такие корпорации, как Microsoft и Borland, не замедлили выпуст ить соответствующие средства: уже в 1991 году, т. е. сразу после появления Windows 3.1. Borland выпускает Turbo Pascal for Windows, а в 1992 - усовершенствованную версию этой системы программирования - Borland Pascal with Objects 7.G. Эти первые специализированные инструменты требовали основательного знания Windows и были сложны в освоении. Но вот в 1993 году Microsoft выпустила пер- вую визуальную среду программирования Visual Basic, и программирование для Windows стаю даже проще, чем npoi раммирование для MS-DOS. В ответ на это Borland в 1995 году' выпустила первую версию Delphi, а за гем, с интервалом в 1 год, - еще 4 версии: 2, 3, 4 и 5. Наконец, в середине 2001 г. выпускается версия 6, которая и положена в основу этой книги. Материал книги можно с некоторыми (часто несущественными) ограничениями использовать для изучения более ран- них версий. Не секрет, что лучшим языком для изучения и освоения программи- рования является Паскаль, а лучшей в мире системой программирования для MS- DOS - Turbo Pascal. Delphi продолжила серию Паскаль-ориент ированных средств программи- рования и является наиболее удобным инструментом для Windows- программирования. Версии Delphi развивались по принципу наращивания своих возможностей. Если с 1-й по 4-ю версии Delphi могла работать с базами данных только с помощью механизма BDE, то в версии 6 таких механизмов у же 4 - BDE, ADO, IBExpress, dbExpress Если 8 компонентов страницы internet версии 2 дава- ли лишь возможность использовать некоторые технологии Интернет в лока шных сетях, то более 100 компонентов версии 6 обеспечивают полноценную возмож- ность Web-программирования, т. е. создания работающих под управлением Web- сервера программ, обеспечивающих интерактивное взаимодействие с клиентом и публикацию по его требованию необходимых данных. Программирование с по- мощью Delphi возможно для начинающих программистов, во всяком случае ос- воение оболочки не требует специальных знаний ни в области программирования, ни в области Windows, хотя умение работать с Windows на уровне пользователя - обязательное условие (если, разумеется, вы захотите создать хотя бы одну из опи- сываемых в учебнике программ). В основе Delphi заложен современный язык программирования Object Pascal, без детального знания которого эффективная работа с Delphi невозможна. Особое значение имеет основополагающий инстру- мент Object Pascal - классы и объекты. Практически все современные языки про- граммирования (в том числе C++ и Visual Basic) поддерживают методику объект- но-ориентированного программирования (ООП), позволяющую резко сократить сроки разработки программ и существенно повысить их качест во.
ВЫСикОУРОВН! ВЫВ г ЕТОДЫ HI СОРНАТИКИи г.р:., раммировангя. 15 ГЛАВА 2. СОЗДАНИЕ МОДУЛЬНЫХ ПРОГРАММ, ЭЛЕМЕНТЫ ТЕОРИИ МОДУЛЬНОГО ПРОГРАММИРОВАНИЯ Модульное программирование основано на понятии моду 1Я. Моду it представляет собой совокупность логически связанных элементов, предназначен- ных для использования други чи мо. iyпями и программами. Модули предназначены для хранения готовых программ. Модуль сам по себе не является выполняемой программой — его объекты используются другими программными единицами процедурами, функциями). Модуль имеет: • один вход I. один выход - на входе программный модуль полу чает оп- ределенный набор исходных данных, выполняет обработку данных и возвращает один набор результатных данных т е. реализует принцип IPO (Input - Ргосеь» - Output) - вход-процесс-выход: • функциональную завершенность - модуль выполняет перечень опера- ций для реализации каждой отдельной функции в полном составе, достаточных для завершения начатой обработки; • лог ическую независимость - результат работь модуля зависит только от исходных данных и не зависит о г работы друз их модулей; • слабые инг] ормацион ные связи с дру гимн программными модулями - обмен информации между модулями должен быть по возможности минимизиро- ван; • обозримый по размеру и сложност и программный элемент Каждый мо 1уль соси ит Из Спецификадии - правила использования мо- дуля и Тела — способа реализации процесса обработ ки. Принцип модульного программирования включает в себя определение со- става и подчиненности функций и определение набора программньгх модулей, реализующих эти функции. При составлении алгоритма модульной программы необходимо учиты- вать следующее; • каждый модуль вызывается на выполнение вышесгоящим модулем и, закончив работу возвращает управление ьызваг тему его моду тю; • принят ие основных решений в алгори гме выносится на максимально «высокий» гго иерархии уровень; • . 1ля ист 1льзования одной и той же фу нкпии в разпы к местах а тп >ри гма создается один моду, гь, который вызывается на выпг глнение по мере необходимо- сти. В результате детализации алг оритма создает ся Функционально-модульная схема алгоритма при поженил, которая является основой для программирования (рис. 3). Функция I и Функция 2 выполняются с помощью одного и т 01'0 же про- граммного модуля. Функция 3 реализуется одним программным модулем. Функция 4 в виде последовательност и выполнения Программных Модулей (2. 3 ... р). Функция 5-е помощью иерархии свя занных модулей. Состав и вид прог раммных модулей, их на значение и харак тер использо- вания в приг рамме р значите гьной степени опреде гяют ся инс тру мен сальными средствами. Капри чер. применительно к средствам СУБД отдельными модулями
16 Г лава 2. Создание модульных программ, элементы теории модульного программирование могут быть: Экранные формы ввода и редактирования информации БД: Отчеты генератора отчетов; Макросы; Стандартные процедуры обработки информации; Меню, обеспечивающее выбор функции обработки и др. Стандартный Паскаль не предусматривает механизмов раздельной ком- пиляции частей программы с последующей их сборкой перед, выполнением Более того, последовательное проведение в жизнь принципа обязательного описания любого объекта перед его использованием делает фактически невозможным раз- работку разнообразных библиотек прикладных программ. Точнее, такие библио- теки в рамках стандартного 11аскаля могут существовать только в виде исходных текстов, и программист, подчас, должен сам вкпючатъ в программу весьма об- ширные тексты различных поддерживающих процедур, таких, как процедуры матричной алгебры, численного интегрирования, математической с гатистики и т.п. Поэтому вполне понятно стремление разработчиков коммерческих ком- пиляторов Паскаля включать в язык средства, повышающие его модульность. Чаще всего таким средст вом является разрешение использовать внешние проце- дуры и функции, тело которых заменяется стандартной директивой EXTERNAL. Разработчики Турбо Паскатя пошли в этом направ гении еще дальше, включив в язык механизм модулей. Рис. 3. Функционально-модульная схема алгоритма приложения Модуль в Паскале - это автономно компилируемая программная единица, включающая в себя различные компоненты ра здела описаний (типы, константы, переменные, процедуры и функции) и, возможно, некоторые исполняемые опера- торы инициирующей части. По своей организации и характеру использования в программе модули Турбо Паскаля близки к модулям-пакетам (PACKAGE) языка программирования Ада. В них так же, как в пакетах Ады, явным образом выделя- ется некоторая «видимая» интерфейсная часть, в которой сконцентрированы опи- сания глобальных типов, конст ан г и переменных, а также приводя гея заголовки
ВЫСОКОУРОВНЕВЕ Е МЕТОД >1 И ФОPHАТОКИ И ПРОПА' ПИРОВАНИЯ. 17 глобальных процедур и функций. I Тоявление объектов в интерфейсной части де- гает их доступными д пя других модулей и основной программы. Тела процедур и функций располагаются в исполняемой части модуля, кот орая может быть скрыта от пользователя. I [асколько сильно изменяются свойства языка I Таскаль при введении ме- ханизма модулей, свиде гельствуе г следующее замечание его автора - Н. Вирта, сделанное им по поводу более позднего языка Модула-2: «Модули - самая важная черта, отличающая язык Модула-2 от его предшественника Паскаля ». Модули представляют собой прекрасный инструмент для разработки биб- лиотек прикладных программ и мощное сре ;ство моду льного программирования. Важная особенность модулей заключается в том, что компилятор Турбо Паскаля размещает их программный код в отдельном сегменте памяти Максимальная длина сег мента не может превышать 64 Кбайта, однако количество одновременно используемых модулей ограничивается лишь доступной памятью, что дает воз- можность создавать весы а г ру пные прог раммы. 2.1. Структура модулей Паскаля Моду гь имеет следующую структуру: UN П шмя>; 1N ГЕШ АСЕ <интерфейсная част ь> IMPLLMENTA DON «исполняемая час гь> BEGIN «инициирую) цая часть> END. Здесь UNIT - зарезервированное слово (единица); начинает заголовок мо дуля; <имя> - имя модуля (правильный идентификатор), INIER1 АСЕ - зарезер- вированное слово (интерфейс); начинает интерфейсную часть модуля; IMPLEMENTATION - зарезервированное слово (выполнение): начинает исполняемую часть; BEGIN - зарезервированное слово; начинает инициирующу ю чаг тъ моду- ля; констру кция BEG IN Инициирующая часть> необязательна; END - зарезервированное слово - признак конца модуля. Таким образом, модуль состоит из заголовка и трех составных частей, любая из которых может быть пустой. 2.2. Заголовок модуля и связь модулей друг с другом Заголовок модуля состоит из заре гервированного с юва 1 ND и следую- щего за ним имени модуля. Для правильной работы среды Турбо Паскаля и воз- можности подключения средств, облегчающих разработку крупных программ (см. п.9.6), аг о имя должно совпадать с именем дискового фай па. в который по- мещается исходный текст модуля. Если, например, имеется зато ювок Unit Globa’. то исходный текст соответствующего модуля должен р умещаться в дисковом фай те GLOBAI TAS основной прог раммой ТмяГмоду гч тужит дчя-ei е Эта связь уст анар гадает сяр h j { '\Л . I связи с другими модул ими и специа тьны м предложением
18 Глава 2. Создание модульных г рсн рамм, элиилты теории -одульнош программирования ( TSES <сп.модулей>. Здесь USES - зарезервированное слово {использует}; <сп.модулей> - список модулей, с которыми устанавливается связь- эле- ментами списка являются имена модулей, отделяемые друг от друга запятыми, например: Uses CRT, Graph, Global. Если объявление US! S .. используется, оно должно открывать ра щел описаний основной про1раммы Модули могут использовать другие модули. Предложение USES в модулях может следовать либо сразу за зарезервированным словом INI FRFACE, либо сразу за словом .MPLEMEN1 АТЮК, либо сразу за первым и вторым словом (г е. допускаются два предложения USE Sj 2.3. Интерфейсная часть Интерфейсная часть о гкрывается зарезервированным словом INT ERF АСЕ. В этой части содержатся объявления всех глобальных <ктов мо- дуля (типов, констант, переменных и подпрограмм), которые должны стать дос- тупными основной программе и/или другим модулям. При объявлении глобаль- ных подпрограмм в интерфейсной части указывается только их за1 оловок, напри- мер: Unix Cmplx; Interface type complex = record re. im : real end; Procedure AddC (x, у : complex; vai z : complex); Procedure MulC (x, у : complex, var z ; complex); Если теперь в основной программе написать предложение Uses ( mplx; в программе станут доступными гиг COMPLEX и две процедуры - ADDC и MUI С из модуля CMPLX. Объявление подпрограмм в интерфейсной части автомат ически сг >прово- ждается их компиляцией с использованием дальней модели памя ги Эт им образом обеспечивается доступ к подпрограммам из основной программы и друг их моду- лей. Следует учесть, что все константы и переменные, объявленные в интерфейс- ной части модуля, равно как и глобальные константы и переменные основной программы, помещаются компилятором Турбо Паскаля в общий сегмен г данных (максимальная длина сегмента 65536 байт). Порядок появ юния разтичных разде- лов объявлений и их количество может быть прои гве гьным. 1 с ли в интерфейсной части объявляются внешние подпро) раммы или подпрог раммы в машинных ко- дах, их тела (т.е. зарезервированное слово EXTERNAL, в первом случае, и ма- шинные коды вместе со с швом 1NLINE - во втором) должны следовать сразу за их заголовками в исполняемой части модуля (не в интерфейсной!). В интерфейс- ной части модулей нельзя использовать опережающее описание. 2.4. Исполняемая часть Исполняемая част ь начинает ся зарезервированным словом IMPLEMENTA1 ION и содержит описания подпро! рамм. объявленных в интер-
ВЫСОКОУРОВНЕВЫЕ МЕТОДЬ И 1ФОРМАТИК1 И ПРО РАММИРОВАНИЯ 19 фейсной части. В ней могут объявляться локальные для модуля объекты - вспо- могательные типы, константы, переменные и блоки, а также метки, если они ис- пользуются в инициирующей части. Описанию подпро"раммы, объявленной в интерфейсной части модуля, в исполняемой части , ц и жен пре, цлсствоват ь заголовок, в 1 отором можно опускать список формальных переменных (и тип результата дл> функции), так как они уже описаны в интерфейсной части. Но если заюловок подпрограммы приводится в полном виде. т.е. со списком t] ормальных параметров и обьявлением результата, он должен совпадать с заголовком, объявленным в интерфейсной части, напри- мер: Unit Cmplx; Interface type complex - i eccrd re. im : real end Procedure AddC (x, у : complex; var z : complex) Implementai ion Procedure AddC; begin z.re := x.re з Y .re; z.im : = x.im3j im end; end. Локальные переменные и константы, а также все программные колы, по- рожденные при компи. 1яции моду 1я. помещаю гея в общий сегмент памяти. 2.5- Инициализирующая часть Инициализирующая часть завершает модуль. Она может от сутсгвовать вместе с начинающим ее словом BEGIN или быть пустой - тогда за BEGIN сразу следует признак конца модут я (слово EN1) и следующая за ним точка). В инициа тизирующей части размешают ся исполняемые операт оры. со- держащие некоторый фрагмент программы. Эти операторы исполняются до пере- дачи управления основной программе и обычно используются для подготовки ее работы. Например, в них могут инициироваться переменные, открываться нуж- ные файлы, устанавливаться связи с другими ПК по коммуникационным каналам и т.п.: Unit File!ext; Interface Procedure Print(s : string) Implementation var f: text; const name = 'output txt’; Procedure Print, begin WriteLn(f, s) end:
Высокоуровневые методе и 1форматикг и про раммирсвания 19 фейсной части. В ней могул объявляться гокальные для модуля объекты - вспо- могательные типы, константы, переменные и блоки, а также метки, если они ис- пользуются в инициирующей части. Описанию подпрсчраммы, объявленной в интерфейсной части модуля, в исполняемой части ,юлжен предвюс-.воват ь заголовок, в котором можно опускать список формальных переменных (и i и i резул т а га для функции), таг как они уже описаны в интерфейсной части. Но если заголовок по программы приводится в полном виде. т.е. со списком t] ормальных параметров и обьявлением результата, он должен совпадать с заголовком, объявленным в интерфейсной части, напри- мер: Unit Cmplx; Interface type complex - record re, im : real end, Procedure AddC (x, у : complex; var z : complex) Implementai ion Procedure AddC; begin z.re := x.re +V .re; z.im : = x.im -t у im end, end Лока ъные переменные и константы, а т акже все программные коды, по- рожденные при компи. 1яции моду 1Я. помещаю гея в общий сегмент памяти. 2.5. Инициализирующая часть Инициализирующая чаегг завершает модуль. Она может отсутствовать вместе с начинающим ее словом BEGIN или быть пустой тогда за BEGIN сразу следует признак конца модуля (слово EN1) и следующая за ним точка). В инициа шзирующей части размешают ся исполняемые операт оры. со- держащие некоторый фрагмент программы. Эти операторы исполняются до пере- дачи управления основной программе и обычно использую гея для подготовки ее работы. Например, в них могут инициироваться переменные, открываться ну'ж- ные файлы, устанав тиваться связи с другими П1. по комму никационным каналам и т.п.: Unit File! ext: Interface Procedure Print(s : string), Implementation var f: text; ci inst name = ‘output txt; Procedure Pi int, begin WriteLn(f, s) end;
20 Глава 2. Создаг ие модульных программ, элементы теории модульного i poi ранжирования. { Начало инициализирующей части’ } begin assign(f, name) rewrite(f); { Конец инициализирующей части } end. Не рекомендуется делать инициализирующую часть пустой, лучше ее опустить: пустая часть содержит пустой оператор, которому будет передано управление при запуске программы. Эти часто вызывает проблемы при разработ- ке оверлейных программ. 2.6. Компиляция модулей В среде Турбо Паскаля имеются средства, управляющие способом компи- ляции модулей и облегчающие разработку крупных программных проектов. В частности, определены три режима компиляции: COMPILE, МАКЕ и BUILD (прил.1). Режимы отличаются только способом связи компилируемого модуля или основной npoi раммы с другими .модулями, объявленными в предложении USES. При компиляции модуля или основной программы в режиме COMPILE все упоминающиеся в предложении USES модули должны быть предварительно откомпилированы и результаты компиляции помещены в одноименные файлы с расширением TPU. Например, если в программе (модуле) имеется предложение Uses Global то на диске в каталоге, объявленном опцией UNIT DIRECTORIES (прил.1). уже должен находиться файл GLOBAL.TPU. Файл с расширением TPU (от англ. I urbo Pascal Unit) создается автоматически в результате компиляции модуля (если ос- новная программа может компилироваться без создания исполняемого ЕХЕ- файла, то компиляция модуля всегда приводит к созданию TPU-файла). В режиме МАКЕ компилятор проверяет наличие 'I PU -файлов для каждо- го объявленного модуля. Если какой-либо из файлов не обнаружен, система пы- тается отыскать одноименный файл с расширением PAS. т.е. файл с исходным текстом модуля, и, если искомый файл найден, приступает к его компиляции. Кроме того, в этом режиме система следит за возможными изменениями исходно- го текста любого используемого модуля. Если в PAS-файл (исходный текст моду- ля) внесены какие-либо изменения, то независимо от того, есть ли уже в кататоге соответствующий TPU-файл или нет, система осуществляет его компиляцию пе- ред компиляцией основной программы. Более того, ес ш изменения внесены в ин герфейсную часть модуля, то будут перекомпилированы также и все доу гие модули, обращающиеся к нему. Режим МАКЕ, таким образом, существенно об- легчает процесс разработки крупных программ с множеством модулей: програм- мист избавляется от необходимости следить за соответствием существующих TPU-файлов их исходному тексту, так как система делает это автоматически. В режиме BUILD существующие TPU-файлы игнорируются, и система пытается отыскать (и компилировать) соответствующий PAS-файл для каждого объявленного в предложении USES модуля. После компиляции в режиме Bl ILD претраммист может быть уверен в том. что учтены все сделанные им изменения в любом из модулей. Подключение модулей к основной программе и их возможная компиля- ция осуществляются в порядке их объявления в предложении USES. При перехо-
высокоуровневые методы инфо 'магики и программирования 21 де к очередном} модулю система предварительно отыскивает все моду ти, на ко- торые он ссылается. Ссылки модулей друг на друга могут обраювывать древо- видную структуру любой сложности, однако запрещается явное или косвенное обращение модуля к самому себе. Например, недопустимы следующие объявле- ния: I Init A; Unit В: Interface Interface Usee В; Uses Л; Implementation Implementation end. end. Это ограничение можно обойти, если «спрягать» предложение USES в исполняемые части зависимых модулей: Unit A; Unit В; Interface Interface Implementation J nplementation Uses B: Uses A, end. end. Дело в том, что Турбо 11аскаль pa трешае г ссылки на частично откомпили- рованные модули, чго приблизительно соответствует опережающему описанию подпрограммы. 1^ли интерфейсные части любых двух модулей независимы (это непременное условие!), 1] рбо 1 Таскаль сможет идент ифт-цироьать все глобальные идентификаторы в каждом из модулей, после чего откомпи тирует тела моду лей обычным способом. 2.7. Доступ к объявленным в модуле объектам Создадим модуль, реализующий арифметику комплексных чисел (такая арифметика ни в стандартном Паскале, ни в Турбо Паскале не предусмотрена) К сожалению, в 1урбо Паскале нельзя испо.тыовать функции, значения которых имели бы структурированный тип (запись, например), поэтому арифметика ком- плексных тисел реализуется четырьмя процедурами: UNI1 Cmplx; {---------- INTERFACE ty pe complex = recoi d re. im.rcal end; Procedure AddC (X. у : complex: var z : complex). Procedure SubC (x.y : complex: var z : complex): Procedure MulC (X. У : complex: var z : complex); Procedure ] )ivC (x. у : complex: var z : complex), const c : complex _ (re : 0.1: im : -11:
22 Глава 2. Созда me моду; ь еыу про гамм, э> еме ,гь itji'wn мод/лзкгэг роггамми-юь/лиу. {---------------} IMPLEMENTATION {---------------} Procedure AddC: begin z.re := x.re + y.re; z. im := x.im + y. im end {AddC}; Procedure SubC; begin z.re := x.re - y. re ; z.im x.im -y.im end {SubL); Procedure MuIC; begin z.re := x.re*y.re - x.im*y. im; z.im := x.re*y.im a x.im*y.re end {MuIC}; Procedure DivC; var zz : real, begin zz := sqr(y.ie) -1- sqr(y.im); z. re := (x.re * y.re 4 x.im * y.im) I zz; z.im := (x.re * y.im - x.im * y.re) / zz end {DivC}; end. Текст этого модуля следует поместить в файл CMPLX.PAS. Можете его откомпилировать, создав TPU-файл, после чего программе станет доступны процедуры из новой библиотеки. Например, в стедующей программе (пример 1 ) осуществляют ся чет ыре арифметические операции над парой комплексных чи- сел. Пример 1. Uses Cmplx; var а, Ь. с : complex; begin a.re := 1; a.im := 1; b.re .= 1; b.im := 2; AddC(a, b. c); \Х'гпеЕп('Сложение: 'c.re:5:l, c.im:5:l.'i') ; SubQa. b, c); WritcLnfBbiHM гание: ‘c.re:5:l, с.пп:5:1.Т); MulC(a. b, c); Write Ln(’Умножение: 'c.re:5:l, c.im:5:l.'i‘): DivC(a. b, c): WriteLnCfleление: 'c.re:5:l. c.im:5:l.T); end. После объявления Uses Cmplx программе стали досту пны все < >б ьекты.
Высокоуровневые методы ина орматики и г рэграммирования. 23 объявленные в интерфейсной части модуля CM PL X. При необходимости можно переопределить побей их этих объект ов как эт о произошло с объявленной в мо- дуле типизированной константой С. Переопределение объекта означает, что вновь объявленный объект «закрывает» ранее определенный в модуле i .дноимен- ный объект. Чтобы получить доступ к «закрытому» объекту, нужно воспользо- ваться составным именем: перед именем объекта поставить имя модуля и точку. Например, оператор WriteLn(cmplx.c.re:5:l, cmplx.c.irri 51, i') выведет на Э1 ран содержимое «закрытой.» типи шрованной констант ы и * преды- ду щего примера. 2. 8. Стандартные модули В Турбо Паскале имеется восемь стандартных модулей, в которых содер- жится большое число разнообразных типов, констант, процедур и функций. Эти- ми модулями являются SYSTEM. DOS. CRT. PRINTER. GRAPH’ OVERLAY. TURBOS и GRAPH3. Модули GRAPH. TURBOS и GRAPHS выделены e отдель- ные FPU-файлы, а остальные входят в состав библиотечного файла TURBO TPL. Лишь один модуль SYSTEM подключается к любой программе автоматически, все остальные становятся доступны только после у казания их имен в списке, сле- дующем за словом USES. 11иже приводится краткая характеристика с гандартных моду пей. Полное описание входящих в них программных средств приведено в при южении 4. а описанию объектно-ориеь тированной био лиотеки Т urbo Vision посвящена вся вторая час гь книги. Модуль SYSTEM В модул ь SYS 1 ЕМ входя г все процс дуры и функции стандарт ноге П аска- ля, а также вс троенные i роцеду ры и функции, кот орые не вот ти в дру гие стан- дартные модули (например, INC. DEC, GTTDIR и т.п.). Как уже отмечалось, мо- дуль SYSTEM подключается i любой программе независимо от того, объявлен ли он в пред, южении I 'SES или нет, поэтому' его глобальные констан гы, переменные и подпрограммы считаются встроенными в Ту рбо 1 Гаскаль. Модуль PRINTER Делает доступным вывод текстов на матричный принтер. В нем определя- ется файловая переменная LST типа TEXT, которая связывается с логическим устройством PRN. После подключения модуля можег быть выполнена, например, такая программа: l Jses Printer; begin writein (LST, 1 урбо 11аскаль') end. Модуль CRT В мо, руле CR1 сосредоточены процедуры и функции, обеспечивающие управление секстовым режимом работы экрана. С помощью входящих в модуль подпрел рамм можно перемещать ку рсор в произвольную позицию экрана, меня гь цвет выводимых символов и окружающего их фона, создавать окна. Кроме т ого, в модуль включены также процедуры «слепого» чтения 1 тавиатуры и управления звуком.
2А Глава 2. Создание модульных программ, элементы теории модульного программирования. Модуль GRAPH Содержит обширный набор типов, констант, процедур и функций для управления графическим режимом работы экрана. С помощью подпрограмм, вхо- дящих в модуль GRAPH, можно создавать разнообразные графические изображе- ния и выводить на экран текстовые надписи стандартными или разработанными программистом шрифтами. Подпрограммы модуля GRAP11 после соответствую- щей настройки могут поддерживать различные типы аппаратных графических средств. Настройка на имеющиеся в распоряжении программиста технические средства графики осуществляется специальными программами - драйверами, ко- торые не входят в файл GRAPH TPU. но пост авляются вместе с ним. Модуль DOS В модуле DOS собраны процедуры и функции, открывающие доступ про- граммам к средствам дисковой операционной системы MS- DOS. Модуль OVERLAY Необходим при разработке громоздких программ с перекрытиями. Как уже говорилось, Турбо Паскаль обеспечивает создание программ, длина которых ограничивается лишь основной оперативной памятью IIK. Операционная система MS-DOS оставляет исполняемой программе около 580 Кбайт основной памяти (без учета резидентных программ и самой системы Турбо Паскаль). Память тако- го размера достаточна для большинства применений. Гем не менее, использова- ние программ с перекрыт иями снимает это ограничение. Два библиотечных модуля TURBO3 и GRAP) IS введены для совместимо- сти с ранней версией 3.0 системы Турбо Паскать. 2.9. Использование стандартного модуля CRT Во многих случаях стандартные для Паскаля возможности ввода'вывода данных с помощью процедур Read, ReadLn, Write, WriteLn оказываются явно не- достаточными для разработки удобных в использовании диалоговых программ. Например, процедуры Read/ReadLn вводят с клавиатуры только типизированные данные, причем с обязательным эхо-повтором набираемых символов на экране. С их помощью нельзя определить факт нажатия какой-либо специальной клавиши (функциональной клавиши, клавиши управления курсором и т.п.). Процедуры Write/WriteLn выводят сообщения, начиная с того места на экране, где в данный момент находится курсор, причем по мере вывода курсор автоматически сдвига- ется на экране, а если очередной символ выводится в самом нижнем правом углу экрана, осуществляется «прокрутка» экрана: его содержимое сдвигается вверх на одну строку. Все это сильно затрудняет создание и обновление различного рода окон, меню и других атрибутов современных диалоговых программ. Разработчики Турбо Паскаля предусмотрели несколько подпрограмм, су- щественно увеличивающих возможности текстового ввода/вывода. Эти подпро граммы сосредоточены в библиотеке (модуле) CRT. входящей в комплект постав- ки Турбо Паскаля. В модуль включены также процедуры Sound, NoSound и Delay, которые позволяют программировать звуковой генератор ПК. В этой главе обсу- ждается использование подпрограмм модуля CRT. Аббревиатура CRT соответствует русскоязычной аббревиатуре ЭЛТ - электронная лучевая трубка. На профессионатьном жаргоне CRT означает уст- ройство визуализации информации (дисплей) даже в том случае, когда вместо
Высокоуровневые методы информашки и пр, граи -iпроба шя. 25 ЭЛТ исполь туются иные физические устройства - плазменные панели, жидкокри- сталлические экраны и т.н 2.9.1. Программирование клавиатуры Дополнительные возможности управления клавиатурой реализуются дву- мя функциями: Key Pressed и ReadKey. Фу нкция KeyPressed Возвращает значение типа ] fvolean, указывающее состояние буфера кла- виатуры: False означае г что буфер пуст, а 1 rue - что в буфере есть хотя бы один символ, еще не прочитанный программой. В MS-DOS реализуется так называемый асинхронный буферизованный ввод с клавиатуры. По мере нажатия на клавиши соотвстствуюшие коды поме- щаются в особый буфер, откуда они могут бьпь затем прочитаны программой. Стандартная длина буфера рассчитала на хранение до 16 кодов символов. Если npoi рамма достаточно дол> о не обращас гея г г тавиатуре, а пользователь нажи- мает клавиши, буфер может оказаться переполненным. В этот момент раздается звуковой сигнал и « шшние» коды теряются. Чтение из буфера обеспечивается процедурами Read/ReadLn и функцией ReadKey. Обращение к фу нкции KeyPressed не задерживает исполнения программы: функция немедленно анали- зирует буфер и возвращает то или иное значение не дожидаясь нажатия клави- ши. Функция ReadKey Возвращает значение типа Char При обращении к этой функции анали ти- руется буфер клавиа гур. если в Нем есть хотя бы один не прочит анный символ, код этого символа берется из буфера и возвращается в качестве значения функ- ции, в противном случае функция бу тет ожидать нажатия на любую клавишу. Ввод символа с и тмощью этой функции не сопровождается эхо-повтором и со- держимое экрана не меняется. Допустим, что в какой-то точке программы необходимо игнорировать все ранее нажатые клавиши, коды которых еше не прочи ганы из буфера, т.е. необхо- димо очист ить буфер Этого можно постичь следующим способом: I ses CRT, var С: Char: begin while KeyPressed do C := ReadKey; end. При использовании процедуры ReadKey необходимо учесть, что в клавиа- турный буфер помещаются так называемые расширенные коды нажатых клавиш. Ес ти нажимается любая алфавитно-цифровая клавиша, расширенный код совпа- дает с ASCII-кодом соответствующего символа. Например, если нажимается кла- виша с латинской буквой «а» (в нижнем регистре'), функция ReadKey вошрашает значение chr (47). а если <<А» (в верхнем регис гое) - значение chr (65). При нажа-
26 Глава 2. Создание модул оных программ, элементы теории модульнсго гуограмм/рова> щ . тии функциональных клавиш FL..F10, клавиш управления курсором, клавиш Ins, 1 lome, Del, End, PgUp, PgDn в бу фор помещается двухбай гная последователь- ность: сначала символ #0, а затем расширенный код клавиши. Таким образом, значение #0, возвращаемое функцией ReadKcy, используется исключительно для того, чтобы указать программе на генерацию расширенного кода. Получив это значение, программа должна еще раз обратиться к функции, чтобы прочитать расширенный код клавиши, т.е. код сканирования клавиш и. Этот код определяет- ся порядком, в соответствии с которым микропроцессор клавиатуры Intel 8042 периодически опрашивает (сканирует) состояние клавиш. Следующая простая программа позволяет определить расширенный код любой клавиши. Для завершения работы программы нажмите клавишу Esc. Uses CRT; var C: Char; begin repeat C := ReadKey; if Co#0 then WriteLn(crd(C)) else WriteLnCOl ,ord(ReadKeyJ :8) until C=#27 {27 - расширенный код клавиши Esc} end. Используя эту программу можно обнаружить, чт о нажатие на некот >рые клавиши игнорируется функцией R.eadKey. Это. прежде всего, так называемые сдвиговые клавиши - Shill Ctrl Al.. Сдвиговые клавиши в MS-DOS обычно ис- пользуются для переключения регистров клавиатуры и нажимаю гея в сочетании с другими клавишами. И менно таким способом раз тичает ся ввод прописных и строчных букв. Кроме т oi о. функция игнорирует переключающие к гавиши Caps Lock, Num. Lock, Scrol1 Lock, а также «. шшние» функциональные клавиши Fl 1 и Fl2 клавиатуры IBM АТ. не имеющие anaioia на клавиатуре ранних моделей IBMPC'XT (в эт их машинах использовалась 84 -клавишная клавиа гура, в то время как на IBM АТ - 101-клавишная). В т аблице 2 приводятся расширенные коды клавиш, возвращаемые функ- цией ord(ReadKey) Для режима ввода кириллицы приводятся коды, соответст- вующие альтернативному вариан гу кодировки Расширенные киды клавиш Таблица 2 Код Клавиша или ком- бинация клавиш Код Клавиша и ш комбинация । лавиш Пер- вый байт Второй байт Первый байт Второй байт Алфавитно-цис )ровые клавиши 8 - Backspace (Забой) 9 - Tab (Табуляция) 13 - 1'nter 32 - ]1робс т 33 - 34 - И 35 - а 36 -
ВЫСОКОУРОРНЕВЬ Е МГ’СДЫ ИНФОРМАТИКИ И ПРОГРАММИРОВАНИЯ. 27 Код Клавиша или ком- бинация клавиш Код Клавиша или комбинация клавиш Пер- вый байт Вт орой байт Первый байт Второй байт 37 - % 38 - & 39 - 40 - гг 41 - ) 42 - 43 - -+ 44 - 45 - - 46 - 47 - 4S...57 - 0...9 58 - 59 - > 60 - < 61 - - 62 - > 63 - *? 64 - 65...90 - A...Z 91 - 92 - 93 - ] 94 - А 95 - 96 - 97..122 - а...7 123 - { 124 - 1 125 - } 126 - "*-• 128 .159 - А.. Я 160... 175 - а...п 224...239 - р...я Управляющие клавиши и их сочет ания со сдвиговыми 0 э С trl-2 0 Shift-Tab 0 16...25 Alt-Q._ All -Р (верх- ний ряд букв) 0 30...38 А11-А... Alt-L (средний ряд букв) 0 44...50 Alt-7...Alt-М (ниж- ний ряд букв) 0 59...68 Fl.. 1 10 0 - 71 Нот е 0 72 Курсор вверх 0 73 75 Курсор влево 0 77 Курсор вправо 79 End 0 80 Курсор вниз 0 81 PgDn 0 82 Ins 0 83 Del 0 84...93 Shift-FL.Shift-F10 0 94...103 Ctrl-Fl.. Ctil- F10 0 104..I13 Alt-Fl.. Ak-F 10 0 114 Ctrl PrtScr 0 115 Ctrl-курсор влево 0 116 Ctrl Курсор вправо 0 117 Ctrl -End 0 118 Ctrl PgDn 0 119 Ctrl -Home 0 120. 131 Al -1. .Alt-= (верхний ряд клавиш) 0 132 Ctrl -PgUp
28 Глава 2. Создание модульных программ, элементы теории модульногс программирования. 2.9.2. Текстовый вывод на экран Используемое в I [К устройство визуа тьного отображения ин<) ормации - дисплей - состоит из двух основных частей: монитора, содержащего экран (элек- тронно-лучевую трубку или жидкокристаллическую панель) с необходимыми компонентами (устройс гвами развертки изображения), и блока у прав гения, кото- рый чаще называют дисплейным адаптером или просто адап гером. Обычно оба устройства согласуются друг с другом, но в отдельных случаях этого согласова- ния может не быть (например, цветной монит ор может не работать с монохром- ным адаптером и наоборот). Считаем, чго оба устройства согласованными, по- этому, говоря о различных дисплеях, можно говорить только о различных адапте- рах, так как именно в них сосредоточены основные <плиния дисплеев друг от дру- га. Исторически первым адаптером (1981 г.), использованным на IBM PC, был так называемый монохромный адаптер (MDA). Его возможности очень скромны: он позволял выводить только текстовые сообщения в одном из двух форматов - 25 строк по 40 или по 80 символов в строке Символы выводились в прямом и юбражении (светлые символы на темном фоне), причем п х ширина ос- тавалась одинаковой в обоих режимах, поэтому при выводе в режиме 40x25 ис- пользовалась то. 1ько левая половина экрана. В MDA применялись два символь- ных шрифта - обычный и с подчеркиванием. В 1982 году фирма Hercules выпустила адаптер HGC (от англ Hercules Graphics Card - графическая карта Геркулес), который полностью эмулировал MDA в текстовом режиме, но в отличие от него мог еще воспроизводит ь и графи - ческие изображения с разрешением 720x350 точек (пикселей). Примерно в это же время 1ВМ выпустила цветной графический адаптер CGA (Color Graphics Adapter) и впервые на экране ПК появился цвет. CGA позво- лял выводить как текстовые сообщения, так и графические изображения (с раз- решением 320x200 или 640x200 пикселей). В текстовом режиме выводились 40x25 или 80x25 символов как в монохромном, гак и в цветном изображениях. При использовании монохромного режима символы, в о гличие от MDA, не могли подчеркиваться, зато их можно был ) выводить в не: а' ивном и юбражении (чер- ные символы на светлом фоне). При выво, те в две гном режиме использовалось 16 цветов для симво юв и 8 - для окружающего их фона. Текстовые возможности CGA стали стандартом де-факто и поддержива- ются во всех последующих разработках IBM - адаптерах EGA. MCG A, VGA и SVGA. Возможности модуля CRT рассматривают ся применительно к адапт ер зм этого типа Процедура TextMode Используется для задания одною из возможных текстовых режимов рабо- ты адаптера. Заголовок процедуры: Procedure TextModc(Mode: Word); Здесь Mode - код текстового режима. В качестве значения этого выраже- ния могут использовал ься следующие константы, опре, теленные в модуле CRT: const ] !W40-0{4epho белый режим 40x25} Со40=1 {Цвет ной режим 40x25} BW8O-2{ Черно -бе. еый режим 80x25} Со8Ь—3 [1 (вст ной режим 80x25}
ВЬСОКОУРОВ! ЕВЫЕ МЕТОДЫ I НООГМАТИКИ I ПРОГРАММИРОЬА! И 1. 29 Мопо=7 [Используется с МЭА} ГогД8х8=256{Используется для зафужаемого шрифта в режиме 80x43 или 80x50 с адаптерами EGA hjihVGA} Код режима, установленного с помощью вызова процедуры Те.» Mi de, за поминается в глобальной переменной LastMode модуля (КТ и может использо- ваться для восстанив. 1ения начального состояния экрана. Следующая программа иллюстрирует использование этой процедуры в различных режимах. При вы юве TextMode сбрасываются все ранее сделанные установки цвета и окон, экран очищается и курсор переводится в его левый верх- ний VI ол. Usee CRT; Procedure l ’i int( S: String); (Выводит сообщение S и ждет инициативы пользователя} begin WriteLn(S); {Выводим сообщение} МгйеЕпРНажмите клавишу Enter..'); ReadLn {Ждем нажатия клавиши Enter} end; {Print} var LM: Word;{I [ача шный режим экрана} begin LM := LastMode, {Запоминаем начальный режим работы дисп гея} 1 extMode(Co40); Printf Режим 40x25"). 1 exfMode(CoSO); РппгСРежим 80x25’); 1 cxtMode(Co40+Font8x8): PrintfРежим Си40+Гont8x8‘); 1 ex)Mode(Co80 »ont8x8); РгпДСРежим Co80+Font8x8’); {Восст анавливаем исходный режим работы } TextModeO М) end. Процедура 1 extColor Определяет цвет выводимых символов. Заголовок процедуры Procedure TextColor(Color. By te); Процедура 1 extBackground Определяет цвет фона. Заголовок. Procedure 1 ext! lackgroundfColor: Byte); Единственным параметром обращения к этим процедурам должно быть выражение типа Byte, задающее код нужного цвета. Этот код удобно определять с помощью следующих мнемонических констант, объявленных в мод» те С RT: const Black - 0,{Черный} Blue ~ 1;{Темно-синий} Green - 2 ; {Темно -зеленый} Cyan - 3;{Бирюзовый} Red - 4 ;{Красный} Magenta = 5; {Фиолетовый}
30 глава 2. Создание модульных программ, элементы теории модульнсгс программирования Brown = 6 ;{Коричневый} LightGray = 7; {Светло-серый} Daj kGray = 8;{Темно -серый} LightBlue = 9;{Синий} LightGreen - 10;{Свстло-зеленый} LightCyan - 11;{Светло-бирюзовый} LightRed = 12;{Розовый} LightMagenta = 13;{Малиновый} Yellow ~ 14;{Желтый} White' _15;{Белый} Blink “128;{Мерцание символа} Следующая программа иллюстрирует цвет овые возможности 1 урбо 1 Тас- кали. Uses CRT; const Col: array [1-15] of String [16] = ('темно-синий', ’темно-зеленый', 'бирюзовый'.'красный', 'фиолетовый', 'коричневый','свет по-серый','темно-серый', 'синий','зеленый'.'светло-бирюзовый'/розовый', 'малиновый','жел гый’, 'белый'); var k: Byte; begin for к := 1 to 15 do begin {Выводим 15 сообщений различными цветами} TextColor(k); WriteLn('L[BeT', к,' - ',Coi[k]) end: TextColor(White+Blink); {Белые мигающие символы} WriteLnfMepnaHHe символов'); {Восстанавливаем стандартный цвет} TextColor(LightGray); WriteLn end. Следует обратить внимание на последний оператор WriteLn: если его уб- рать, режим мерцания символов сохрани гея после завершения программы, не- смотря на то. что перед ним стоит оператор TextColor(LightGray). Дело в том, что все цветовые определения предварительно заносятся в специальную переменную TextAttr модуля CRT и используются для настройки адаптера только при обращении к процедурам Write/WriteLn. Процедура ClrScr Очищает экран или окно (см. ниже процедуру Window). После обращения к ней экран (окно) заполняется цветом фона и курсор устанавливается в его левый верхний угол. Например: Uses CRT; var
ВЫСОКОУРОВНЕВЬ.. Ml ГОДЫ ИНФОРМАТИКИ И ПРО ГР АГ МИРОВАНИЯ. 31 С: Char begin TextBackground(redl; Cl. Str; {Заполняем экран красным цветом} WriteLn('Ha>KMMTe любую к тавишу...'); С := ReadKey; {Ждем нажатия любой клавиши} raxtBackground(Black) ; ClrScr {Восстанавливаем черный фон экрана] end. Процедура Window Определяет текстовое окно - область экрана, которая в дальнейшем будет рассма гриваться процедурами вывода как весь экран. Сразу после вызова проце- дуры курсор помещается ь левый верхний угол окна, а само окно очищается (за- полняется цветом фона). Но мере вывода, курсор, как обычно, смещается вправо и при достижении правой границы окна переходит на новую строк;, а если он к этому моменту находи тся на последней строке, содержимое окна сдвигает ся вверх на одну строку, т.е. осущест вляетея «прокрутка» окна. Заголовок процеду - ры: Procedure Window(XI,Yl.X2,Y2: Byte); 3aecbXl...Y2 - координаты левого верхнего (XI.Y1) и правого нижнего (X2.Y2) углов окна. Они задаются в координатах экрана, причем левый верхний угол жрана имеет координаты (1.1). горизонтальная координата увеличивается слева направо, а верт икадьная - сверху вниз В следующем примере и пыюстрирует ся вывод д< i ст аточно .глинного со- общения в двух разны к окнах. Uses CR'l; var k: integer begin {( оздаем левое окно -же ггые символы на синем фоне:} TextBackground) Blue); W'indow(5.2.35,17); TextC olor(Yellov.) for k = 1 to 100 do Wi itef Нажмите клавишу Entei...'), ReadL n; {Ждем нажатия Enter] ClrScr; {Очищаем окно} {Создаем правое окно - белые символы на красном фоне:} Т extBackground(Red); TextC olor( White); Window(40,2.70,17); for k :- 1 to 100 do Wt itef Нажми re клавишу Enter...'); ReadL n; TextMode(C080) {Сбрасываем все установки} end. Обращение к процедуре Window игнорируется, ести какая-либо из коор-
32 Глава 2. Создание модульных программ, элементы теории модульного программирования. динат выходит за границы экрана или нарушается одно из условий: Х2>Х1 и Y2>Y1 Каждое новое обращение к Window отменяет предыдущее определение окна. I раницы текущего окна запоминаются в двух глобальных переменных мо- дуля CRT: переменная WindMin типа Word хранит Х1 и Y1 (XI - в младшем бай- те), а переменная того же типа WindMax - Х2 и Y2(X2 - в младшем байте). При желании можно изменять их нужным образом без обращения к Window. Напри- мер, вместо операт ора Window (40,2,70,17); можно были бы использовать два операз ора WindMin :~ 39+( 1 shl 8); WindMax := 69+( 16 shl 8); (в отличие от обращения к Window координаты, хранящиеся в переменных WindMin и WindMax, соответствуют началу отсчета 0,0). Процедура GotoXY Переводит курсор в нужное место экрана или текущего окна. Заголовок процедуры: Procedure GotoXY(X,Y: Byte); Здесь X, Y - новые координаты курсора. Координаты задаются относи- тельно границ экрана (окна), т.е оператор GotoXY(l,l); означает указание перевеет и курсор в левый верхний угол экрана (или окна, если к этому моменту на экране определено окно). Обращение к процедуре игнориру- ется, если новые координаты выходят за границы экрана (окна). Функции WhereX и WhereY С помощью этих функций типа By te можно определить текущие коорди- наты курсора: WhereX возвращает его горизонтальную, a WhereY - вертикальную координаты. В следующей npoi рамме сначала в центре экрана создается окно, которое обводится рамкой, затем в окне выводится таблица из двух колонок. Uses CRT; const LU =#218;{Левый верхний угол рамки} RU =#191;{Правый верхний угол)} LD =#192;{Левый нижний} RD =#217;{Правый нижний} Н =#196;{Горизонтальная черта} V =#179;{Вертикальная черта} XI =14;{Координаты окна} Y1 =5; Х2 -66; Y2 =20; Txt = ’Нажмите клавишу Enter...'; var k: integer: begin ClrScr; {Очищаем экран} {Создаем окно в центре экрана - желтые символы на синем фоне:}
Высокоуровневые методы информатики и программирования. 33 Т extBackground(Blue); TextColor( Yellow); Window(Xl,Yl,X2,Y2); ClrScr; {Обводим окно рамкой} Write(LU); {Левый верхний угол} {Горизонтальная линия} for k: = Xl+1 to Х2-1 do Wrile(H); Write(RU);{Верхний правый угол} for к := Y1+1 to Y2-1 do {Вертикальные линии} begin GotoXY(l.k-Yl-Ll);{Переходим клевой границе} Write(V);{JIeBan черта} CotoXY(X2-Xl +1.WhereY)[Правая граница} Write(V){Правая черта} end; Write(LD); {Левый нижний угол} Window(Xl.Yl,X2,Y2+l);{Расширяем вниз на одну строку координаты окна, иначе вывод в правый нижний угол вызовет прокпутку окна вверх} GotoXY(2,Y2-Yl + l); {Возвращаем курсор из левого верхнего угла окна на нужное место} {Горизонтальная рамка} for k;= Xl+1 to X2-1 do Writc(H); Write(RD), {Правый нижний угол} {Определяем вн\т реннюю часть окна} Window(X 1 +1, Y1+1 ,Х2-1. Y2-1); {Выводим левый столбец} fork:=Yl+l toY2-2 do WriteLnf Левый столбец, строка ’,k-Yl);; {Ждем нажатия любой клавиши} Writef! 1ажмите любую клавишу...'); k := ord(ReadKey); if к=0 then к .= ord(ReadKey); DelLine; {Стираем приглашение} {Выводим правый столбец] fork Yl+1 to Y2-2 do begin GotoXY((X2-X1) div 2,k-Y 1); WritefПравый ст олбец, строка ',k-Y 1) end ; {Выводим сообщение и ждем нажатия клавиши Enter} GotoX Y((X2-X 1 -Length(Txt)) div 2, Y2-Y1-1); TextColor( White); Write(Txt); ReadLn; {Восстанавливаем стандартный режим} T extModef СО80) end.
34 Глава 2. Создание модульных программ, элементы угории модуле, огс пюгидммирования. Три следующие процедуры без параметров могут оказаться полезными при разработке текст овых редакторов. Процедура ClrEOL Стирае г част ь ст роки от текущего положения курсора до правой границы окна (экрана). Положение курсора не меняе гея Процедура DelLine Уничтожает всю строку с курсором в текущем окне 1или на экране, если окно не создано). При этом все строки ниже удаляемой (ес. ш они есть) сдвигают- ся вверх на одну с грогу. Процедура InsLine Вставляет строку: строка с курсором и все ст роки ниже ее сдви1 аю гея вниз на одну строку; строка, вышедшая за нижнюю границу окна (экрана), без- возвратно теряется; текущее положение курсора не меняе гея. Процедуры LowVideo, NormVideo и HighVideo С помощью этих процедур без параметров можно уст анавливдть соответ- ственно пониженную, норматьную и повышенну ю яркость символов. Например: Uses CRT; begin I ,ov» Video; ХУгпеипСПониженная яркость'); NormVideo: У/гпе£л1('Нормальная яркость'); HighVideo; ХУгйеЬпСПовышенная яркость') end. Следует отметить, что на практике нет разницы между пониженной и нормальной яркостью и юбражения. Процедура AssignCRT Связывает текстовую фай товую переменную F с экраном с помощью не- посредственного обращения к видеопаМ! ти (т .е. к памяти, используемой адапте- ром для создания изображения на экране). D результате вывод в такой текстовый файл осуществляется значительно быстрее (в 3...5 раз1 чем если бы этот файл был связан с экраном ст андартной процедурой Assign. Заголовок процеду ры: Procedure AssignC RГ (F: Text). ] l следующей программе измеряется скорост ь вывода на экран с помощью стандартной файловой процедуры и с помощью непосредственного обращения к видеопамяти. Вначале файловая переменная Г связывается «медленной» проце- дурой Assign со стандартным устройством CON (т.е. с экраном) и подсчитывается количество N1 циклов вывода некоторого текста за 5*55 = 275 мил писекунд сис- темных часов. Затем фай.ювая переменная связывается с экраном с помощью процедуры быстрого доступа AssignCR.1 и точно так же подсчитывав гея ко тиче- ство N2 циклов вывода. В конце программы счетчики N1 и N2 выводятся на эк- ран. Заметим, что показания системных часов хранятся в опсрат ивной памяти компьютера в виде четырехбайтного слова по адресу f$0040:$006C| и наращива-
ВЫСОКОУРОВНЕВЫЕ МЕТОДЫ L НФОРМАТИКИ И РРОГРАМНИРОВА1 ИЯ. 35 ются на единицу каждые 55 миллисекунд. Uses CRT; var F: Text; t: Longbtt;{Начало отсчета времени] N1,N2: Word;{Счетчики вывода} const txt =' Text'; begin {----fl тандартный вывод в файл----] Assign(F,'CC®'); Rewrite( F); N1 := 0,{ Готовим счет чик вывода} ClrScr;{Очищаем экран} {Запоминаем начальный момен г:} t := MemL[$00 10:$006С]; {Ждем начала нового 55-мс интервала, чтобы исключить погрешнос гь в определении времени:} while MemL [$0040:$C06C]=t do; {Цик i вывода за 5 ин гервалов} while MemL [$0040:$006C]<t+6 do begin inc(N I j; Write(l .txt) end; Close(F); {—Вывод с помощью быст рой процеду ры прямого доступа к экрану —} AssignCRT(l'); Rewrite) F); N2 :=0; ClrScr; t - MemL [$0040.$006C]; while MemL[$O04O:$0O6Cl -1 do; while MemL[$0040:$006C] <t -6 do begin inc(N2); W ritefF.txt) end ; Closet F); {I [ечатаем результат} ClrScr: WriteLn(Nl,N2:10) end. С >едует у честь, что выво i на экран обычным образом - без использования файловой переменной (например, оператором Write (1 xt)) - также осущес "в тяется с помощью непосредст венного доступа к видеопамяти, поэтому ценное гь проце- дуры AssignCRT весьма сомнительна. Прямой доступ I видеопамяти регулирует- ся глобальной логической переменной DirectVideo модуля CRT: если эта пере-
36 Глава 2. Создание модугьных программ, элементы теории модульного программирования. менная имеет значение True, доступ разрешен, если False - доступ к экрану осу- ществляется с помощью относительно медленных средств операционной системы MS-DOS. По умолчанию переменная DirectVideo имеет значение True. 2.9.3. Программирование звукового генератора Звуковые возможности ПК основаны на одноканатьном управляемом зву- ковом генераторе, вырабатывающем электромагнитные колебания звуковой час- тоты. Колебания подаются на встроенный в ПК динамик и заставляют его зву- чать. В модуль CRT включены три процедуры, с помощью кот орых можно за- программировать произвольную последовательность звуков. Процедура Sound Заставляет динамик звучать с нужной час готой. Заголовок процедуры: Procedure Sound(F: Word); Здесь F - выражение типа Word, определяющее частоту звука в герцах. После обращения к процедуре включается динамик и управление немедленно возвращается в основную программу, в то время как динамик будет звучать впредь до вызова процедуры NoSound. Процедура No Sound Выключает динамик. Если он к этому моменту не был включен, вызов процедуры игнорируется. Процедура Delay Обеспечивает задержку работы программы на заданный интервал време- ни. Заголовок процедуры: Procedure Delay(T: Word); Здесь Т - выражение типа Word, определяющее инт ервал времени (в мил- лисекундах), в течение которого задерживается выполнение следующего опера- тора программы. Для генерации звукового сигнала обычно используется вызов описанных процедур по схеме Sound-Delay-NoSound. Следующая программа заставит ПК воспроизвести простую музыкатьную гамму. Используемый в ней массив F со- держит частоты всех полутонов в первой октаве от «до» до «си». При переходе от одной октавы к соседней частоты изменяются в два раза. Uses CRT; const Г: array [1 ..12] ol Real - (130.8' 138 6, 146 8, 155.6. 164.8, 174.6, 185.0, 196.0, 207.7, 220.0, 233.1,246.9);{Массив частот 1-й октавы} Тетр = 100;{Темп исполнения} var k.n- Integer; begin (Восходящая гамма] for k := 0 to 3 do for n :- 1 to 12 do begin Sound(Round(F[n]*(l shl k)));
Высокоуровневые методы информатики .1 пр.траммирова imp. 37 Delay(Temp); NoSound end ; {Нисходящая гамма} for к 3 downto 0 do for n 12 downto 1 do begin Sound(Round(F[n]*( 1 shl k)) ) ; Delay(Temp); NoSound end end. 2.10. Использование стандартного модуля Graph Начиная с версии 4.0, в состав Турбо Паскаля включена мощная библио- тека графических подпрограмм Graph, остающаяся практически неизменной во всех последующих версиях. J >иб тиотека содержи г в общей сложности более 50 процедур и функций, предост„вл тощих программисту самые разнообразные воз- можности управления графическим экраном Для облегчения знакомства с биб пиотекой все входящие в нее процедуры и функции сгруппированы по функцио • нальному принципу. 2.10.1. Переход в графический режим и возврат в текстовый Стандар гное состояние П х после его включения, а также к моменту за- пуска программы из среды 1 у рбо Паскаля, соответствует работе экрана в д eiюто- вом режиме. Поэтому любая программа, исполь тующая графические средства компьютера, должна определенным образом инициировать 1 рафический режим работы дисплейного адаптера. После завершения рабе гы программы ПК возвра- щается в текстовый режим. 2.10.2 Краткая характеристика графических режимов работы дисплейных адаптеров Нас тройка графических процедур на работу с i онкретным адаптером дос- тигается -*а счет подключения нужного i г афическо! о драйвера. Драйвер - это спе- циальная программа, осуществляющая управление геми или иными техническими средствами ПК. Г рафический драйвер, как не тру дно до1 адаться, управляет дис- плейным адаптером в графическом режиме. Графические драйверы разработаны фирмой Borland практически для всех типов адаптеров Обычно пни располага- ются на диске в отдельном подкаталоге BGI в виде файдов с расширением ВС’ (от англ.: Borland Graphics Interface - графический интерфейс фирмы Borland). Например. CGA.BGI - драйвер для СС4-адат ера, EGA VGA BGI - драйвер для адаптеров EGA и VGA и т.п. Выпускаемые в настоящее время ПК оснащаются адаптерами, разрабо- танными фирмой IBM, и ди совместимыми с ними. Если не у читывать монохром - ный адаптер MDA, вес они имеют возможность работы в графическом режиме В этом режиме экран дисплея рассматривается как совокупность очень близко рас- положенных точек - пикселей, светимостью которых можно управлять с помо- щью программы. Графические возможности конкретного адаптера определяются р з]де-
38 Глава 2 Создание модулрНых программ, элементы теории гоцульнсо программирования нием экрана, т.е. общим количеством пикселей, а также количеством цветов (от- тенков), которыми может светиться любой из них. Кроме того, многие адаптеры могул работать с несколькими 1рафическими страницами. Графической страни- цей называют область оперативной памяти, используемой для создания «карты» экрана, т.е. содержащей информацию о светимости (цветет каждого пикселя Ни- же приводится краткая харак геристика графических режимов работы наиболее распрос траненных адаптеров. Адаптер CGA (Color Graphics Adapter - цветной графический адаптер) имеет 5 графических режимов. Четыре режима соответ с гвуют низкой разрешаю- щей способности экрана (320 i жсепей по юризонтали и 200 по вертикали т.е. 320x200) и отличаются только набором допустимых цветив - палитрой. Каждая палитра состоит из грех цветов, а с учетом черного цве га несветящегося пикселя - из четырех: палитра 0 (светло-зеленый, розовый, желтый), палитра 1 (светло- бирюзовый, малиновый, белый), пали гра 2 (зе юный, красш тй, коричневый) и па- ли гра 3 (бирюзовый, фиолетовый, светло-серый). Пят ый режим сое гве гствуе г высокому разрешению 640x200, но каждый пиксель в этом случае может свет ить- ся либо каким-то одним, заранее выбранным и одинаковым для всех пикселей цветом, либо не светиться вовсе, г е. падитра этого режима содержит два цвета. В графическом режиме адаптер CGA использует то тько одну страницу. Адат ер 1 iGA (Enhanced Graphics Adapter - усиленный графический адап- тер) может полностью эмулировать i рафические режимы адаптера CGA. Кроме того, в нем возможны режимы низкого разрешения (640x200, 16 цветов, 4 страни- цы) и высокого разрешения (640x350, 16 цветов 1 страница). В некоторых моди- фикациях используется также монохромный режим (640x350, 1 страница, 2 цве- та). Адаптер MCGA (Multi-Color Graphics Adaptei - многоцветный графиче- ский адаптер) совместим с CGA и имеет еще один режим - 640x480. 2 цвета 1 страница. Такими адаптерами оснащались младшие модели серии 1 IK PS '2 фирмы IBM. Старшие моде, ш этой серии оснащаются более совершенными адаптерами VGA (Video Graphics Array -графический видеомассив. Адаптер VGA эмулирует режимы адат еров CGA и EGA и дополняет их режимом высокого ра решения (640x480, 16 цветов, 1 страница). Cynep-VGA адаптеры (SVGA) с ра решением 800x600 и более, исполь- зующие 256 и более Цветовы к оттенков В настоящее время эти адаптеры получи- ли повсеместное распространение, однако в библиотеке Graph для них нет драй- веров. Поскольку SVGA совместимы с VGA, д. 1я управления современными гра- фическими адаптерами приходится использовать драйвер EGAVGA.BGI и до- вольствоваться его относи гельно скромными возможностями. Несколько особняком стоят достаточно п эпу 1ярные адаптеры фирмы Hercules. Адаптер HGC имеет разрешение 720x348, его пиксели могут свет иться одним цветом (обычно свет по-коричневым) или не светиться вовсе, т .е. это моно- хромный адаптер. Адаптер HGC-*- отличается несущественными усовершенство- ваниями. а адаптер HICC (Hercules In Color Card) предс гав тяе г собой 16-цветчый вариант 1IGC+. 2.10.3 Процедуры и функции Процедура InitGraph Инициирует гра<] ический режим работ ы адапт ера. Заголовок процедуры Procedure InitGraph) var Driver,Mode: Integer; I 'ath: String);
ВЫСОКОУРОВНЕВЫЕ ME ГОДЕ ИНФПРНАИ К.1 И ПРОГРАММ> РОВАНЙЯ 39 Здесь Driver - переменная типа Integer, определяет тип графического драйвера; Mode - переменная toi о же типа, задающая режим работы 1рафического адаптера; Path - выражение типа String, содержащее имя файла драйвера и, воз- можно, маршрут его поиска. К момен гу вызова процедуры на одном из дисковым носителей информа- ции должен находиться файл, содержащий нужный графический драйвер. Проце- дура загружает этот драйвер в опера гивную память и переводит адаптер в графи- ческий режим работы Тип драйвера должен соответствовать типу 1 рафическоги адаптера. Дзя указания типа драйвера в модуле предопределены след} ющие кон- станты: const Detecf=O;{ Режим автоопределения типа} CGA-1; MCGA-2; EGA-3; EG А 64—4; EGA Mono-5; ШМ8514-6; HercMono=7; ATT400-8: VGA-9; PC3270-10; Большинство адаптеров могут работать в различных режимах. Для того, чтобы указат ь адаптеру требуемый режим работы, используется переменная Mode, значением которой в момент обращения к проце/type могут быть такие константы: const { Адап тер CGA : } CGACO - 0; {Низкое разрешение, ли гра па- 0} CGAC1 = 1: {] 1изкое разрешение, ли гра па- 1} CGAC2 = 2; {1 ’ г зкое разрешение, ли гра па- 2} CGAC3 = 3; CGAHi= 4; I Адаптер MCGA:} MCGACO 0; MCGAC 1 = 1; MCGAC2 = 2; MCGAC3-3; MCGAMed = 4; MCG \Н1 = 5; [Адаптер EGA :} EGALo-0, EGAHi = 1; EGAMonoHi = 3; [Адаптеры HGC и {] 1изкое разрешение, ли гра {Высокое разрешение} {Эмуляция CGACO} {Эмуляция CGAC1} {Эмуляция CGAC2} {Эмуляция CGAC3} {Эмуляция CGAHi} {640x480} {640x200, 16 цветов} {640x350, 16 цветов} {640 к.350. 2 цвета} HGC-.} па- 3}
Глава 2. Создание юд/Лвных программ, элементы ~eopjh мод>.1ьногэ прэграммироьания. HercMonoHi = 0; {720x348) {Адапте- рАТТ400.} ATT 400СО = 0; {Аналог режима CGACO} АТТ400С1 = 1; (Аналог режима CG АС1 } AT3400C2 = 2; {Аналог режима CGAC2} АП 400СЗ = 3; {Ан злог режима CGAC3} ATT400Med = 4; {Аналог режима CGAHi} ATT 400Н1 =5; {640x400, 2 цвета} {Адаптер VGA:} VGALo = 0; {640x200) VGAMed = 1; {640x350} VGAHj = 2; {640x480} PC3270HI = 0; {Ана ioi ri .rcMonoHi} {Адаптер 1BM8C14} 1BM8514I О =0; {640x480, 256 цветов] IBM8514H1 = 1; {1024x768, 256 цветов} Пусть, например, драйвер С GA.BGI находится в каталоге TPM3G1 на диске С, и устанавливается режим работы 320x200 с палитрой 2. Тогда обращение к ] процедуре будет таким: Uses Graph; var Driver, Mode : Integer: begin Driver := CGA; [Драйвер] Mode := CGAC2;{Akhm работы} InitGraphi Dri ver, Mooe.' CATP'BGI') ; Если тип адаптера ПК неизвестен или ес ти программа рассчитана на ра- боту с любым адаптером, используется обращение к процед\ ре с т ребованием автоматического определения типа драйвера: Driver := Detect; InitGraphl Driver. Mode. 'CAT P^BGI'); После такого обращения уст анавливается графический режим работы эк- рана. а при выходе из проце, гуры переменные Dri ver и Mode содержат целочис- ленные значения, определяющие тип драйвера и режим ei о работ ы. При этом для адаптеров, способных работать в нескольких режимах, выбирается с гарший ре- жим. т.е. тот, что закодирован максимазьной цифрой. 1 ак. при работе с CG4 - адаптером обращение к проце. type со значением 1 )riv er = Detecl вернет в пере- менной Diiver значение 1 (CGA) и в Mode -значение 4 (CGAH1), а такое же обра- щение к адаптеру VGA вернет Dri ver - 9 (VGA} и Mode = 2 (VGAHi). Функция GraphResult Возвращает значение типа Integer, в кот ором закодирован резул т а г по- следнего обращения к графическим процедурам, t ели ошибка не обнар) жена, значением функции будет ноль, в противном случае - отрицательное часлс, имеющее следующий смысл: const grOk = 0:{ Нет ошибок}
Bb.CC КОУРОВ IFBbtF МЕТОДЫ /Н РОРМАТИКИ И ЯР ГРАММИГОВА 1ИЯ. 41 grlnitGraph—1;{Не инициирован графический режим} grNotDctecled =-2;{ Не определен тип драйвера} grFilcNotFind —3;{Не найден графический драйвер} grlnvalidDriver =-4;{Н .правильный т ип драйвера} grMoLoadMem =- 5;{Нет памяти для размещения драйвера} grNoScanMem = - 6;{11ет памяти для просмотра областей} grNoFloodMetn =- 7;{ Нет памяти для закраски областей} grFontNotFound = -8;{ Не найден файл со шрифтом} grNoFontMem =- 9, [Не г памя ги для размещения шрифта] grlnvalidMode =-10;] Неправильный графический режим] grError =-11: {Общая ошибка} grlOError =-12;{Ошибка ввода-вывода} grlnvalidFont =-13:{Неправильный формат шрифта} grInvalidFontNum=-14: {Неправильный номер шрифта} После обращения к функции GraphResult признак ошибки сбрасывается, поэтому повторное обращение к ней вернет ноль. Функция GraphErrorMsg Возвраг дает значение типа STring. в котором по указанному коду ошибки дается соответствующее текстовое сообщение. Заголовок функции: Function GraphErrorMsg(Code: Integer) String; Здесь Code - код ошибки, возвращаемый функцией GraphResult. Например, типичная последова гельность операторов для инициации гра фического режима с автоматическим определением типа драйвера и уст ан эвкой максимального разрешения имеет следующий вид: var Dri ver, Mode, Error: Integer; begin Driver := Detect/Автоопределение драйвера} InitGraph(Dnver, Mode ''),{Инициируем графику} Error := GraphResult;{l 1олучаем результат} if Error о grOk then (Проверяем ошибку} begin {Ошибка в процг гуре инициации} WriteLn(Graphr.rror.MsgfError)), {Выводим сообщение} end else {Нет ошибки] Чаще всего причиной возникновения ошибки при обращении к процедуре InitGraph является неправильное указание мест опиножения файла с драйвером графического адаптера (например, фаш.а CGAJ *G I для адап гера CG А) 1 '.ас трой- ка на мес гогюложение драйвера осуществ. гяется заданием маршрута поиска нуж- ного файла в имени драйвера при вызове процедура- ] -/Graph. Если, например, драйвер зарегистрирован в подкаталоге DRIVERS г. талога PASCAL на диске D, то нужно использова гь вызов: InitGraph(Driver, Mode, 'd LPascal'Di ivers'); Замечание. Во всех следующих примерах процедура InitGraph вызывается с параметром Driver в виде пустой строки. Такая форма обращения будет кор- ректна только в том случае, ког, га нужный фай i графическо, о драйвера находится в текущем каталоге. Для упрощения повторения примеров необходимо скопиро-
42 Глава 2. Создание модульных программ, элементы теории модульного программирования. вать файл, соответствующий адаптеру ПК, в текущий каталог. Процедура CloseGraph Завершает работу адаптера в графическом режиме и восстанавливает тек- стовый режим работы экрана. Заголовок: Procedure CloseGraph; Процедура RestoreCRTMode Служит для кратковременного возврата в текстовый режим. В отличие от процедуры CloseGraph. не сбрасываются установленные параметры графического режима и не освобождается память, выделенная для размещения графическою драйвера. Заголовок: Procedure RestoreCRTMode; Функция GetGraphMode Возвращает значение типа Integer, в котором содержится код установлен- ного режима работы графического дцап гера. 3ai оловок: Function GetGraphMode Integei; Процедура SetGraphMode Устанавливает новый графический режим работы адаптера. Заголовок: Procedure SetGraphMode) Mode: Integer); Здесь Mode - код ус ганавливаемого режима. Следующая программа иллюстрирует переход из графического режима в текстовый и обратно: Uses Graph; var. Driver, Mode, Error : Integer; begin {Инициируем графический режим} Driver := Detect; lnitGraph(Driver. Mode,"); Error := GraphResult; {Запоминаем результат) i£ Error о grOk then {I (роверяем ошибку} WriteLn(GraphErrorMsg(Error)) {Есть ошибка} else begin {Нет ошибки) Writel n (’Это графический режим'); WriteL n (’11ажмите "Enter"...’.20); ReadLn; {Переходим в текстовый режим} RestoreCRTMode; Writel. n С А это текс говый...’); ReadLn; {Возвращаемся в графический режим} SetGraphMode (GetGraphMode); WriteL п ('Опять графический режим...'); ReadLn; CloseGraph end end.
Высокоуровневые метод, ь инфэрмаи ки и программирование 43 В этом примере для вывода сообщений как в 1 рафическом, так и в тексто- вом режиме используется ci андартная процедура WrireLn. Если ПК оснащен не- русифицированным адаптером CGA, вывод кириллицы в графическом режиме таким способом невозможен, в этом случае необходимо заменить соответствую- щие сообщения так, чтобы использовать только латинские буквы. Процедура DetectGraph Возвращает т ип драйвера и режим его работы. Заголовок: Procedure ] )etectGraph(var Di iver.Mode Integer) Здесь Driver - тип драйвера. Mode - режим работ ы. В отличие от функции GetGraphMode описываемая процедура во $вращает в переменной Mode максима 1ьно возможный д тя данного адаптера номер г рафи - ческого режима. Функция GetDriverName Возвращает значение типа String, содержащее имя загруженного графиче- ского драйвера. Заголовок: Function GetDriverName- String; Функция GctMaxMode Возвращает значение т ипа Integer, содержащее количество возможных режимов работы адаптера. Заголовок: Function GetM„xMode: Integer; Функция GetModeName Возвращает значение типа String, содержащее разрешение экрана и имя режима работы этап гера по его номеру. Заголовок: Function GetMooName(ModNumber: Integer): String; Здесь ModN umber - номер режима. Следующая программа после инициации графического режима выводит на экран строку, содержащую имя загруженного драйвера, а также все возможные режимы его работ ы. Uses Giaph; var a,b. Integer; begin a := Detect; InitGiaph(a, b,"); WriteLn(GetDi iverName); for a := 0 to GetMaxMode do WriteLn(GetModeNamefa): 10) ReadLn; CloseGraph end. Процедура GetModcRange Возвращает диапазон возможных режимов работы за тайного графическо- го адаптера. Заголовок: Procedure GetModeRanget Drv: Integer, var Min. Max: Integer):
44 Глава 2. Создание модульных программ, элементы теории модульного программирования. Здесь Drv - тип адаптера; Mln - переменная типа Integer, в которой воз- вращается нижнее возможное значение номера режима; Мах - переменная того же типа, верхнее значение номера. Если задано неправильное значение параметра Drv, процедура вернет в обеих переменных значение -1. Перед обращением к процедуре можно не уста- навливать графический режим работы экрана. Следующая программа выводи г на экран названия всех адаптеров и диапазоны возможных номеров режимов их ра- бот ы. Uses Graph; var D,L,H: Integer; const N: array [ 1.. 11 ] of String 18] = ('CGA 'MCGA ’, 'EGA ’EGA64 ', 'EGAMono ЧВМ8514 HercMono’. 'ATT400 ', 'VGA 'PC3270', 'Ошибка'); begin Write Ln('Адаптер Мин. Макс.'); for D := 1 to 11 do begin GetModeRange(D. L, 11); WriteLn(N[D], L:7, H:10) end end. 2 10.4. Координаты, окна, страницы Многие 1рафические процедуры и функции используют указатель теку- щей позиции на экране, который в отличие от текстового курсора невидим. По- ложение этого указателя, как и вообще любая координата на графическом экране, задается относительно левого верхнего угла, который, в свою очередь, имеет ко- ординаты 0,0. Таким образом, горизонтальная координата экрана увеличивается слева направо, а вертикальная - сверху вниз. Функции GctMaxX и GetMaxY Возвращают значения типа Word, содержащие максима шные координат ы экрана в текущем режиме работы соответственно по горизонтали и вертикали. Например: Uses Graph; var a,b: Integer; begin a := Detect; InitGraph(a, b,"); Write! n(GetMaxX. GetMaxY:5); RcadLn; CloseGraph end.
Высокоуровневые методы информатики и протамине, вания. 45 Функции GetX и GetY Возвращают значения типа Integer, содержащие текущие координат ы ука- зателя соответственно по i оризонтали и вертикали. Координат ы определяются относительно левого верхнею у i ла окна или, если окн< > не установлено, экрана. Процедура SetViewPort Устанавливает прямоугольное окно на графическом экране. Заголовок: Procedure SetViewPort(XI,Yl ,X2.Y2; Integer ( lipOn: Boolean); Здесь X1...Y2 - координаты левою верхнего (XI,\ 1) и правого нижнего (X2,Y2) углов окна: СНрОп - выражение типа Boolean, определяющее «отсечку» не умещающихся в окне элемен гов и юбражения. Координаты окна всегда задаются от носите тьно левого верхнего угла эк- рана. Если парамегр ClipOn имеет значение True, элементы изображения, не уме- щающиеся в пределах окна, отсекаются, в противном случае границы окна шно- рируются. Для управления этим параметром можно использовать такие опреде- ленные в мо, гуле констант ы const ClipOn = True; {Вк почить отсечку} ClipOff ~ False; {Не включат ь отсечку} Uses Graph,CRT; vai x,y,e: Integer; xll,yll,xl2,yl2, {Координаты 1-го окна} x21,x22, {Левый верхний угол 2-го} R, {Начальный радиус} k: Integer; begin DirectVideo := False (Блокируем прямой доступ к видеопамяти в модуле CRT} {Инициируем графический режим} х := Detect: lnitGraph(x, у. "); {Проверяем результат} е := GraphResult: if е о grOk then WriteLn(GraphErrorMsg (е)) {Ошибка} else begin {Нет ошибки} {Вычисляем координат ы с учетом разр тшения экрана] xl 1 := GetMaxX div 60, xl2:=GetMaxX div 3: у I l :=GetMaxY div 4: v!2:=2*yl 1: R :=(xl2-xl 1) div 4; x21 :=x!2*2; x22:=x21+xl 2-xl 1; {Рисуем окна} Writel .nt’CIipOn:1:10,'ClipOff:’:40); Rectangle(xl 1, у 11, x 12, у 12); Rectangle(x21. у 11 x22. у 12); {Назначаем 1-е окно и рисуем четыре окружное ги] SetView Portt х 11, у 11, х 12. у 12, ClipOn) for k := 1 to 4 do Circle(O,yl l,R*k);
40 Глава 2. Создание модульных программ, элементы теории модульного программирования. s Назначаем 2-е окно и рисуем окружности} SetViewPort(x21, yl 1, х22, у 12, ClipOff), for k := 1 to 4 do Circle(U,yl l,R*k); {Ждем нажат ия любой клавиши ] if ReadKey=#0 then k := ord(ReadKey): CloseGraph end end. Процедура GetViewSettings Возвращает координаты и признак отсечки т екущего графического окна. Заголовок: Procedure GetViewSettingsfvar Viewinfo: ViewPortType); Здесь Viewinfo - переменная типа ViewPortType. Этот тип в модуле Graph определен следующим образом: type ViewPortType = rccoi d xl,yl,x2,y2: Integer; {Координаты окна} Clip : Boolean ; Признак отсечки} end ; Процедура MoveTo Устанавливает новое текущее положение указателя. Заголовок: Procedure Move Го(Х,У: integei); Здесь X, Y - новые координаты у ка за геля соответственно по i оризонтали и вертикали. Координаты определяются относительно левого верхнего yi па окна или, если окно не установлено, экрана. Процедура MoveRel Устанавливает новое положение указателя в относительных координатах. Procedure MoveRelfDX.DY: Integer); Здесь DX.DY- приращения новых координат указа!е зя соот вез с гвенно по 1 оризонтали и вертикаш. Приращения задаются относительно т ого положения, которое занимая указатель к момен гу обращения к процедуре. Процедура ClearDevice Очищает графический экран. I [осле обращения к процедуре ука затель ус- танавливается в левый верхний угол экрана, а сам экран заполняется цветом фона заданным процедурой SetBkColor. Заголовок: Procedure ClearDevice; Процедура ClearViewPort Очищает графическое окно, а если окно не опоедепено к этому момен гу' - весь экран. При очисз ке окно заполняется пьетом с номером 0 из текущей палит - ры. Указатель перемещается в левый верхний угол окна. Заголовок: Procedure ClearViewPort:
Высокоуровневые мы.'ды и .фспматики и программирования 47 Процедура GetAspectRatio Возвра цает два числа, ни шоляющих оцени гь соотношение сторон экрана. Заголовок: Procedure GetAspectRatio(var X,Y: Word). Здесь X, Y - переменные типа Word. Значения, возвращаемые в этих пе- ременных, позволяют вычиелл гь отношение сторон । рафическот о экрана в пиксе- лях. Найденный с их помощью коэффициент может использоваться при построе- нии прави тьных геометрических фигур, таких как окружное! и. квадраты и т.п. Например, если необходимо построить квадрат со стороной L пикселей по верти- кали. нужно использовать операторы GetAspectRatio (Xasp, Yasp), Rectangle(xl, у 1, xHL*round (Yasp/Xasp), yl+L), а если L определяет длину квадрата по горизонтали, то использ) ется опе- ратор Rectangle (xl,y l,xl t L,y 1 L *round(Xasp/Yasp)). Процедура SetAspectRatio Устанавливает масштабный коэффициент отношения сторон графическо- го экрана. Заголовок: Procedure SetAspectRatio()BY: Word). Здесь X, Y- устанавливаемые coo гношения с горой. Процедура SctActivePage Делает активной указанную страницу видеопамяти Зато ювок: ] 'rocedure SetAcm ePage(PageNum: Word); Здесь PageNum - номер с границы. ] 1роцеду ра может использоват ься только с адаптерами, поддерживающи- ми многостраничную работу (EGA, VGA и т.п.) Фактически процедура просто переадресует графи ческий вывод в другу ю область ви теопамяти, однако вывод текстов с помощью Wi ite'WriteL п всегда осущест вляется только на страницу, ко- торая является видимой в данный момент (активная страница может быть неви- димой). Нумерация страниц начинается с нуля. Процедура SetVisualPage Делает видимой страницу с указанным номером Обращение: Procedure SetVisualPAgef PageN am: Word); Здесь PageNurr - номер страницы. Процедура может использоваться только с адаптерами, поддерживающи- ми многостраничную работу (EGA, VGA и т.п.1). Нумерация страниц начинается с нуля. Следующая программа сначала рисует квадрат в видимой странице и ок- ружность - в невидимой. После нажатия на Entet происходит смена видимых страниц. Uses Graph; var d,m,e: Integer s : String; begin
48 Глава 2. Создание модульных программ, элементы теории модулоного программирование. d := Detect; InitGraph(d, m, "); e := GraphResult, if e о grOk then WriteLn (GraphErrorMsg(e)) else {Нет ошибки. Проверяем, поддерживает ли драйвер многостранич- ную работу с видеопамятью:} if d in |HercMono,EGA.EGA64.MCGA.VGAl then begin {Используем многостраничный режим} if doHercMono then SetGraphMode( m -1); {Заполняем видимую страницу} Rectangle(10,10,GetMaxX div 2,GetMaxY div 2); OutTextXY(0,0,'Page 0. Press Enter...’); {Заполняем невидимую} SetActivePage (1); Circle(GetMaxX div 2, GetMaxY div 2, 100); OutTexiXY(O.GerMaxY-10,'Page 1. Press Enter...'); {Демонстрируем страницы} ReadLn; SetVisualPage(l); ReadLn. SetVisualPage (0); ReadLn; CloseGraph end else begin {Драйвер не поддерживает многостраничный режим} s := GetDriverName; CloseGraph; WriteLnfАдаптер использует только 1 страниц}'1) end end. Следует обратить внимание на оператор if doHercMono then SetGraphMode(m-l). С его помощью гарантированно устанавливается многостраничный режим работы на адаптерах EGA. MCGA, VGA. Как уже говорилось, после инициации графики с Driver=Detect устанавливается режим работы с максимально возмож- ным номером; перечисленные адаптеры в этом режиме могул работать только с одной графической страницей, чтобы обеспечить работу с двумя страницами, следует уменьшить номер режима. 2.10 5. Многоугольники Процедура Rectangle Вычерчивает прямоугольник с указанными координатами углов. Заголо- вок: Procedure Rectangle(Xl,Yl.X2.Y2: Integer); Здесь XI... Y2 - координаты левого верхнего (XI, Y1) и правого нижнего (Х2, Y2) углов прямоугольника. Прямоугольник вычерчивается с использованием текущего цвета и текущего стиля линий.
ОБА IИЯ. 'ранич- [ режим циации юзмож- олько с тицами, Заголо- [ижиего >ванием Высокоуровневые методы hi форнатики и npoi рампирования 'тУ В следующем примере на »кране вычерчиваются 10 вложенных друт l друга прямо) тельников. 1 ses Graph, С RT; var d,r,e,xl,yl, x2,y2,dx dy: Integer; begin {Инициируем графику} d := Detect; InitGraphfd, r, "); e . UraphResult; if e о grOK then WriteLn(GraphErrorMsg(eJ) else begin {Определяем приращения сторон} dx := GetMaxX div 20; dy := GetMaxY div 20; {Чертим вложенные прямоуго. 1ьники] for d := 0 to 9 do Rectangle(d*dx.d*dy.GetMaxX-d*dx.GetMaxY-d *dj); if ReadKey=#0 then d := ord(ReadKey); CloseGraph end end. Процедура DrawPoly Вычерчивает произвольную ломаную линию, заданную координатами то- чек излома. Procedure DrawPoly iN: Word; var Points) Здесь N - количество точек излома, включая обе крайние точки; Points - переменная типа PointType. содержащая координаты точек излома. Координаты точек излома задаются парой значений типа Word: первое определяет горизонтальную, второе - вертикальную координаты. Для них можно использовать следующий определенный в моду ле т ип: type PointType - record х, у : Word end; При вычерчивании использует ся текущий цвет и текущий стиль линий. Вот как, например, можно с помощью этой процедуры вывести на экран i рафик синуса: Uses Graph; const N = 100; {Количество точек рафика} var d. г. с: Integer; m : array [О. ЬЛ 1] of PointType- k : Word; begin {Инициируем графику’ d .= 1 )etect; InitGi aphtd, r,");
Вь OK 50 Глава 2. Создание модульных программ, элементы теории модульного программирование. е := GraphResult: if е о grOk then WriteLn(GraphErrorMsg( el) else begin (Вычисляем координаты графика} for k := 0 то X do with m[k| do begin x := trunc(k*GeiMaxX'X), у := trunctGetMaxV *(-sin(2*Pi*k/N 1 )/2) end; {Замыкаем 1рафик прямой линией} m|succ(N)}.x ~m[0] .x; m|succ(n)|.y :=tn[0] .y; Drav\Poly(N + 2, m); Readl ,n, CloseGraph end end. В этом примере для проведения горизонтальной прямой используете; «замыкание» ломаной - первая и последняя координаты ее точек излома совпада- ют. Следует о' метить, что хот я количество течек излома N - выражение типа Word, на самом деле внутри процедуры на этот параметр накладываются ограни- чения, связанные с конечным размером используемой буферной памяти. Можно . убедиться в этом с помощью изменения N в предыдущем примере: при К =078 график перестане г выводиться на экран, а функция GraphResult будет возьращато значение - 6 (не хватас г памя ги для просмотра областей). Таким образом, для этой протраммы пороговое значение количества точек излэма составляет 679. В то же время для программы Uses Graph, const N=510; {Предельное значение, при котором на экране еще видна диаго- ? нальная линия} var d,k: Integer; Coo: array [1 -N] ol PointType; begin d := Detect: InitGraph(d.k.'') : for k := 1 to N do with C oo| k] do if ndd(k) then begin X := 0; Y =0 end else begin X := GetMaxX; Y := GetMaxY end; это з Mh< n 2.10J гекуи драв! симо ТОУ 1. CTBO I няюи бую I
ЮВАНИЯ. ьзуе гея овпада- ие типа ограни- Можно N-678 гращать О’Я этой В го же i диаго- ВЫСО.хОУРОВНЕВЫЕ Ml ГОДЫ ИНФОРМАТИКИ И ПРОГРАММИРОВАНИЯ. -*1 DrawPo ly( N .Соо); ReadLn; CloseGraph end. это значение равно 510. В представтенной программе ломаная задается в виде многокра гно накладывающихся друг н а друг а диагона гьных линий. 2.10.6. Дуги, окружности, эллипсы Процедура Circle Вычерчивает окружность. Заголовок: Procedure Circle(X,Y: Integer; R: Word) 3, геев X. Y- координаты центра; R - радиус в пикселях. Окружност ь выводится текущим цветом. Толщина линии устанавливает ся текущим стилем, вид линии всегда SohdLn (сплошная). Процедура вычерчивает правильную окружное гь с учетом изменения линейного размера радиуса в зави- симости от его направ гения относительно сторон графического экрана, т.е. с уче- том коэффициента GelAspectRatiu. В связи с этим параметр R определяет количе- ство пикселей в г оризонта гьном н травлении. В следующем примере в цен гре экрана создается окно, постепенно запол- няющееся случайными окружност ями. Для выхода из программы нажмите на лю- бую клавишу. Uses Graph, CRT; var d ~ e.x.y: Integer; begin. {Инициируем "рафику} d i= Detect; InitGraph(d. r,'); e := GraphRcsult; if e о grOK then Write I n(GraphErrorMsg(e)) else begin {Создаем окно в центре экрана} х := GetMaxX div 4; у GetMaxY div 4; Rectangle(x,y.3 *x,3*y); SetViewPort( x+1 ,y+1,3 *x-1,3 *y-1 ,C lipOn); {Цикл вывода случайных окружностей} repeal SetColorfsucc(Random(vvhite))); {Случайный цвет} SetLineStjle(0,0.2*Random(2)-t1); {и стиль линии} х := Random(GetMaxX); {Случайное положение} у ;= Random(GetMaxY); {центра окружност и} Ctrcle(x,y,Randoml GetMaxY div 4)); until KeyPressed; if ReadKey=#0 men x := ord( ReadKey); CloseGraph end end.
Глава 2. Создание модулы ь к программ, элеменп теории модулрЫ го программирования. Процедура Аге Чертит дугу окружности. Заголовок: Procedure ArefX.Y: Integer: BegA.EndA.R: Word): Здесь X. Y координа гы центра; BegA, EndA - соответственно начальный и конечный углы дуги; R - радиус. Углы отсчитываются против часовой стрелки и указываются в градусах. Нулевой угол соответствует горизонтальному направлению вектора слева направо. Если задать значения начального угла О и конечного - 359, то будет вы- ведена полная окружность. При вычерчивании дуги окружности используются те же соглашения относительно линий и радиуса, ч го и в процед) ре С ircle. Процедура GetArcCoords Возвращает координаты т рех точек: центра, начала и конца дуги. Заголо- вок: Procedure GetArcCoordsfvar Coords: ArcCoordsType); Здесь Coords - переменная типа ArcCoordsType, в которой процедура воз- вращает координаты центра, начала и конца ду ги. Тип ArcCoord .Туре определен в модуле Graph следующим образом: type ArcCoordsType = record X,Y : Integer; {Координаты центра} XstartYstart: Integei; {11ачало дуги} Xend,Yend : Integer; {Конецдуги] end; Совместное использование процедур Arc и GetArcCoords позволяет вы- черчивать сопряжения двух прямых с помощью ду г. С ледует обратить внимание ‘' на коррекцию длины радиуса в с тедующем примере, где вычерчивается прямо- угольник со скругленными углами. Uses Graph,CRT; const RadX = 50; {I оризон гальный радиус] lx = 400; {Ширина} ly = 100; {Высота} var d,r,e: Integer; coo : ArcCoordsType; xl.yi: Integer; xa,ya: Word; RadY : Integer; {Верт икальный радиус} begin {Инициируем графику} d := Detect; lnitGraph(d. r, ; e : = GraphResult; if e о grOK then W riteLn(GraphErrorMsg(e)) else begin GetAspectRatio(xa.ya); {Получаем отношение сторон} {Вычисляем вер' икальный радиус и по южение фигуры с у чет ом отногпе- I ния сторон экрана]
ВЫСОКОУРОВНЕВЫ(: МС"ОДЫ Ht ФОРМАТИКИ И ПРОГРАММИРОВАНИЯ. 53 RadY := round (RadX *( ха /уа)); xl ;= (GetMaxX-lx) div 2; yl := (GetMaxY-2*RadY-ly) div 2, {Вычерчиваем фигуру} Line (xl,) l,xl+lx,y 1), {Верхняя горизон гальная} Arc (xl+1 х.у 1 +RadY.0.90,RadX): {Скругление} GetArcCoords(coo); w irh coo do begin Linet Xstart,Ysiart,Xstart,) starl Чу); [Правая верт икальная} Arc(Xstart-RaaX,Ystart4y,270,0,RadX); GetArcCoords (coo); Linet X start, Y start,Xstart-lx, Y start); {Нижняя горизонтальная Arc(Xstart-lx, Y start-Rad Y, 180,270,RadX); GetArcCoords! coo), 1 dne(Xstart,Ystart,Xstart,Ystart-ly); Arc(XstarH RadX Ystart-ly,90,180,RadX) end ; if ReadKey~#0 then d oid( ReadKey); CloseGraph end end. Процедура Ellipse Вычерчивае г эллипсную дугу. Заголовок: Procedure Elhpse(X,Y: Integer; BegA,EndA,RX,RV : Word); Здесь X, Y - координат ы центра; BegA, 1 ndA - соответственно начальный и конечный углы дуги, RX. RY- горизонтальный и вертикальный радиусы эллип- са в пикселях. При вычерчивании дуги эллипса используются те же соглашения относи- тельно линий, что и в процедуре Circle, и те же соглашения относительно у глов, что и в процедуре Аге Если радиусы согласовать с учетом масштабного коэффи- циента GetAspcctRatio, будет вычерчена правильная окружность. 2.10.7. Краски, палитры, заполнения Процедура SetColor Устанав тиваел текущий цвет для выводимых линий и символов. Заюло- вок: Procedure SeiColor(Color: Word), Здесь Color - текущий цвет. В модуле Graph опре, te лены т очно такие же консган гы для за, гания цвета, как и в модуле СИГ (см. п.13.2). Функция GetColor. Возвращает значение типа Word, содержав ее код теку щегс цвета. 3ai о го- вок: Function GetColor: Word,
54 Глава 2. Созданы моду/ ь -imx программ, элементы геории модулрього программирования. Функция GetMaxCofor Возвращает значение типа Word, содержащее максимально доступный код цвета, который можно использовать для обращения к SetColor Заголовок: Function GetMaxColor: Word; Процедура SetBkCoIor Ус ганавливает цвет фона. Заголовок: Procedure SetBkColorfColor: Word); Здесь Color - цвет фона. В отличие от текстового режима, в котором цвет фона может бьп ь только темного оттенка, в графическом режиме он может быть любым. Установка нового цвета фона немедленно изменяет цвет графического экрана. Это означает, что нельзя создать изображение, два участка которого имели бы разный цвет фона. Для CGA -адаптера в режиме высокого разрешения установка цвета фона изменя- ет цвет активных пикселей. ПОосле замены цвета фона на любой, отличный от О (Black) цвет, нельзя более использовать цвет 0 как черный, он будет заменяться на цвет фона, т.к. процедуры модуля Graph интерпретируют цвет с номером 0 как цвет фона. Это означает, в част пости, что уже невозможно вернуть фэну черный цвет! Если ПК оснащен цветным экраном, следующая программа продемонст- рирует работу процедуры SelBkColor. Про1рамма выводит десять вложенных друг в друга прямоугольников, после чего циклически меняет цвет фона. Для вы - хода из программы достаточно нажать на любую клавишу. Uses Graph, CRT; const NC: array [0..15] of String [12] = ('Black'.’Blue','Green','Cyan,'Red'.'Magenta'. ' Brown','LightGray'.'DarkGray'.'LightRlue', *L ightGreen 1 ,'I ightCyan 1 ,'LightRed', 'LightMagenta', 'Yellow', 'White'); var d, r, e, k, color, dx, dy: Integer; begin {Инициируем графику} d := Detect: InitGraph(d, r, ") ; e := GraphResult; if e о grOK then WriteLn(GraphErrorMsg(e)) else begin {Выводим текст в центре экрана) GutTextXY(200.GetMaxY div 2,'BACKGROUND COLOR’); dx := GetMaxX div 30; {Приращение длины} dy := GetMaxY div 25; {Приращение высоты} for k := 0 to 9 do{BbiBOflHM 10 прямоугольников} Rectangle(k*dx,k*dy,GetMaxX-k*dx,GetMaxY-k*dy); color := black; {Начальный цвет фона} repeat {Цикл смены фона} SetBkColorf color); SetF illStyle(O,Color);
Высокоуровневые методы информатик» и трограммирования. 55 Bar(3 45.GetMaxY div 2,440,GetMaxY div 2+8), Out! extXY(345.GetMa.vY div 2,NC[color]); delay( 1000); inc(color); if color > White then color Black until Key Pressed if ReadKey=#0 then к := ord( ReadKey); CloseGraph end end. Функция GetBkColor Возвращает значение типа Word, содержащее текущий цвет фона. Загото- вок: Function GetBkColor: Word; Процедура SctPalcttc Заменяет один из цветов палитры на новый цвет Заголовок: Procedure SetPalette(N: Word; Color: S^ort nt), Здесь N - номер цвета в палитре; Color - номер вновь устанавливаемого цвета. Данная процедура может работать только с адаптерами EGA или VGA. Она не должна исполь юват1 ся с IBM8514 или 256- цветным вариантом VGA - для этих адап геров i ,ре. ща шатена особая процедура SetRGBPalette (см. ниже). Пер- воначальное размещение цветов в палитрах EGA/VGA соответствует последова- тельности их описания константами Black,.. .White, г.е. цвет с индексом 0 - чер- ный, 1 - синий, 2 - зеленый и т.д. После обращения к процедуре все фрагменты изображения, выполненные цве сом с индексом N и т палитры цветов, получат цвет Color. Например, если выполнить оператор SetPalette(2, White); то цвет с индексом 2 (первоначально это - бирюзовый цвет Су ап) будет заменен на белый 1 (вет с индексом 0 отождествляет ся с цвет ом фона и может изменят, с я наряду с любым другим цветом. Следующая программа выводи- на экран ряд прямых разного цвета и за тем, случайным образом меняет цвета палитры. 1 'ses Graph, CRT; var d,r,e,N,k,color: Integer; Taleno: PaletteTyper begin {Инициируем графику} d := Detect; InitGraph(d, r,''); e := Gra] hResuli, il e о grOK then WriteLn(GraphEi rorMsg(e)) else be^ln {Выбираем толстые сплошные линии} SetLineStyle(Sohdl ,n 0.1 hickWidth): GetPalettef Palette); {1 екушая палитра}
Глава 2. Создание модульных программ, элементы теории модульного программирования. for Color := 0 to Palette Size-1 do begin SetColort, Color); Line(GetMaxX div 3, Color* 10,2*GetMaxX di v 3 Color*! 0) end; {Меняем пали гру и ждем инициативы пользователя} while not KeyPressed do for e := 0 to P< letie.Size-1 do SetPalette(e.RandomCPalette.Size)); if ReadKey=#O then d := ord(ReadKey); Clo seGraph end end. Процедура GetPalette Возвращает размер и цвета текущей палитры. Заголовок: Procedure GetPalette(var Paletteinfo: PaletteType), Здесь Paletteinfo - переменная типа PaietreType, возвращающая ра шер и цвета палитры В модуле Graph определена константа const MaxColors =15; и тип type PaletieType = record Size : Word; {Количесгво цветов в палитре} Colors array [O..MaxColors] of Shortlnt {Номера входящих в палитру цветов} end; С помощью следующей программы можно вывести на экран номера всех возможных цветов из текущей нал^ тры. Lses Graph; var Palette: PaletteType; d,r,e,k: Integer begin {Инициируем графику} d := Detect; InitGraph(d. r ' ’); e := GraphResult; й e о grOk tl ien Write Ln( (iraphErrorMsg(e)) else begin GetPalette( Palette); {Получаем палитру'} CloseGraph; {Возвращаемся в текс говый режим] with Palette do {Выводим номера цветов] for к := 0 to pred(Size) do Write(Colors[k] :5); end end.
Высокоуровневые МЕТОДЫ ИНФСРИАП Kt И ПРОГРАММ, рования 57 Процедура SetAlIPalette Изменяет одновременно несколько цветов палитры. Заголовок процеду- ры: Procedure SetAllPalettet var Palette); Параметр Palette в заголовке процедуры описан как нетипизированный параметр. Первый байт этого параметра должен содержать длину К палитры, ос- тальные N байты - номера вновь устанавливаемы?, цветов в диапазоне от -1 до MaxColors. Код -1 ошачает. что соответствующий цвет исходной палг гры не ме- няется. В следующей программе происходит одновременная смена сразу всех цветов пали гры. Uses Graph. CRT; var Palette: array [0..MaxColors] ofShortint; d,r,e,k: Integer; begin {Инициируем графику} d := Detect; InitGraph(d, r, "); e GraphResult; if e о grOk then WriteLnf GraphErrorMsg(e)) else begin {Выбираем толстые сплошные линии) SetLineStyWSolidLn, 0.1 hick Width); {Выводим линии всеми доступными цветами} for k := 1 to GetMaxColor do begin SetColorfk): Line(GetMaxX div 3,k*10,2*GetMaxX div 3,k* 10) end: PalcttcfO) := Ma <( j dors; {Размер палитры) repeal {Пикл смены палитры} for k := 1 to MaxColors do 1 ’alette[k]Random(succ( MaxCoLors)); SetA llPalettc(Palette) until KeyPressed, if ReadKey =#0 then k .= ord(ReadKey); CloseGraph end end. Функция GetPaletteSize Возвращает значение типа Integer, содержащее размер палитры (макси- мальное количество доступных цветов). 3ai оловок: Function GetPaletteSize: Integer; Процедура GetDefaultPalette Возвращает структуру палитры, устаг ав тиваемую по умо. тчанию (в ре-
58 Глава 2. Создание модульных программ, элементы теории модульного программирования. жиме автонастройки). Заголовок: Procedure GetDefaultPalettefvar Palette: PaletteType); Здесь Palette - переменная типа PaletteType (см. процедуру GetPalette), в которой возвращаются ра шер и цвета палитры. Процедура SetFillStyie Устанавливает стиль (тип и цвет) заполнения. Заголовок: Procedure SetFillStylefFill,Color: Word); Здесь Till - тип заполнения; Color - цвет заполнения. С помощью заполнения можно покрывать какие-либо фрагменты изобра- жения периодически повторяющимся узором. Для указания типа заполнения ис- пользуются следующие предварительно определенные константы: const Empty Fill = 0;{3аполнение фоном (узор отсутствует)} SolidFill = 1;{Сплошное заполнение} LineFill = 2;{3аполнение------] LtSlashFill = 3;{3аполнение ///////} SlashFill = 4;{3аполнение утолщенными ///} BkSlashFill = 5;{3аполнение утолщенными \\\} LtBkSlashFill = 6: {Заполнение \\\\\\\} HatchFill = 7;{3аполнение +-Н ++++} XHatchFill = 8;{3аполнение ххххххх} InterleaveFill= 9;{3аполнение прямоугольную клеточку} WideDotFill - 10;{ Заполнение редкими точками} CloseDotF ill = 11 ;{3аполнение част ыми точками} OserFill = 12;{Узор определяется пользователем} Г 1рограмма из следующего примера продемонстрирует Вам все стандарт- ные типы заполнения I Ises Graph, CR1; var d,r,e,k,j,x,y: Integer; begin {Инициируем графику} d := Delect; InitGraph(d, r, ") ; e := Gt aphResult; if e <> grOk then WriteLn(GraphErrorMsg(e)) else begin x GetMaxX div 6;{Положение графика} у := GetMaxY div 5;{на экране} for j := 0 to 2 do {Два ряда} for k := 0 to 3 do{no четыре квадрата} begin Rectangle((k+1 )*x,(j+l )*y,(k+2)*x,(j+2)*y); SetFillStvle(k+j*4,j+l); Bar((k+1 )*x H,(j+1 )*y+l ,(k+2)*x-l,(j+2)*y-1) end; if ReadKey=#0 then k := ord(ReadKey); CloseGraph end end.
Высокоуровневые методы информатики к программирования. 59 Если параметр Fill имеет значение 12 (L'serFill). то рисунок узора опреде- ляется программистом путем обращения к процедуре SetFillPattern. Процедура SetFillPattern Устанавливает образец рисунка и цвет штриховки. Заголовок: Procedure SetFillPatternfPattem: FillPauernTypeiColor: Word); Здесь Pattern - выражение типа FillPattemType; устанавливает образец ри- сунка для Fill - UserFill в процедуре SetFillSty le; Color - цвет заполнения. Образец рисунка задается в виде матрицы из 8x8 пикселем и может быть представлен массивом из 8 байт следующего типа: type FillPattemType = array [1 .SJofByle; Каждый разряд любого из этих бай гов у правляет светимостью пикселя, причем первый байт определяет 8 пикселей первой строки на экране, второй байт - 8 пикселей второй строки и т.д. Если при обращении к процедуре у казан недопустимый код цвета, вызов процедуры игнорируется, и сохраняется ранее установленный образен заполне- ния. В частности, если в предыдущем примере убрать оператор if d=CG A then SetGraphMode(O); устанавливающий цветной режим работы CGA-адаптера, на экран ПК, оснащен ного адаптером этого типа, будут выведены два одинаковых прямоугольника, так как обращение SetFillPattern(patt2, 2): содержит недопустимо большой для данного режима код цвета, и обращение иг- норируется. Сказанное, однако, не относится к процедуре SetFillSty 1е для значе- ния параметра Fill в диапазоне от 0 до 11: программа будет нормально работа гь и в режиме высокого разрешения CGA-адаптера, причем все цвета палитры, кроме цвета фона, при этом заменяются на белый. Проце гура GetFillPattern Возвращает образец заполнения, установленный ранее процедурой SetFillPattern Заголовок: Procedure GetFillPattern(var Pattern: FillPattei nType); Здесь Pattern - переменная типа FillPattemType, в которой возвращается образен заполнения. Если программа не устанавливала образец с помощью процедуры SetFillPattern, массив Pattern заполняется байтами со значением 255 (SFF). Процедура GetFillSettings Возвращает теку щий ст иль заполнения. Заголовок: Procedure GetFillSettings(var Pattlnfo: FillSeti ingsTy ре); Здесь Pattlnfo - переменная типа FillSettingsType, в которой возвращается текущий стиль заполнения В модуле Graph определен тип: type FillSettingsType = record Pattern: Word; (Образец) Color: Word {Цвет} end;
60 Гг.ЛВА ? СОЗДАГИГ МОДУГЬнЫХ ПРО РАНИ, ЭЛЕМЕНТЕ ТЕОРИИ МОДУЛЬНОГО . РОГРАММИсО ТАПИЯ, 1Толя Рапегп и Coloi в этой записи имеют то же назначение, что и анал э- гичные параме гры при обращении к процедуре SetFillStyle Процедура SctRGBPalette Устанавливает цветовую гамму при работе с дисплеем IBM 8514 и адап- тером VGA. 3ai оловок: Piocedure SetRGBPalette(ColNum,RedVal GreenVal,Blue Val:liiteger); Здесь ColNum - номер цвета; RedVal, GreenVal, 1 SlucVal - выражения типа Integer, устанавливающие ин генсивность соотвстс гвенно красной, зеленой и си- ней составляющих цвета. Эта процедура может работать только с дисплеем IBM 8514, а также с адаптером VGA, использующим видеопамять объемом 256 Кбайт. В и .рвом слу- чае параметр ColNum задается числом в диапазоне 0...255, во ь юром - в диапазо не 0...15. Для установки интенсивности используются 6 старших разрядов м 1ад- шею байта любого из парамет ров RedVal, GreenVal, BlueVal. В следующей npoi рамме в це* тре экрана выводится прямоугольник бе- лым цветом, после чего этот цвет случайно изменяется с помощью процедуры SctRGBPalette. Для выхода из программы нужно нажать побую клавишу. Uses Graph.CRT: var 1 )river. Mode. Err. xl, yl: Integer; begin {Инициируем графический режим { Driver = Detect; InitGraph(Driver, Mode."); ] rr := GraphRe suit; if ErroO then Write Lnt GraphErrorMsgf E rr)) else if Driver in | IBM8514 VGA ] then begin {Выводим прямоугольник в центре экрана] х 1 := GetMaxX div 4; у I := GetMaxY div 4; SetColor( IS); Bar(xl,yl,3*xl,3*yl); {Изменяем белый цвет на случайный} while not KcyPressed do SetRGBPa,.ctte(15,Rar>Iom{256 ),Random(256),Random(256tj CloseGraph end else begin CloseGraph;. WriteLn!'Адаптер не поддерживает', RGB-режим управления цве гами') end end. Процедура FloodFill Заполняет произвольную замкнутую фигур}, используя текущий стиль
Высокоуровневые методы ишрС-рммт ки и программ рования. 61 заполнения (у и ip и цвет) 3ai оливок: Procedure FloodFill(X,Y: Integer Border. Word); Здесь X. Y- координаты любой точки внутри зал. к ну той фигуры- Border - цвет граничной линии. Если фигура незамкнута, заполнение «разольется» по всему экрану. Следует учесть, что реа шзованный в процедуре а торизм просмотра гра- ниц замкнутой фигуры не оз пичается совершено! вом. В часз нисзи, если выводят- ся подряд две пустые строки, заполнение прекращается. Такая ситуация обычно возникает при заполнении небо зьших фигур с использованием типа Lt^lashFill 1 “ фирменном руководсзве по Турбо Паскалю рекомендуется, по возможности, вме- сто процедуры FluodFill использовать EillPoly (заполнение прямоугольника). Следующая программа демонстрирует заполнение случайных окружно- стей. Сначала в ценз ре экрана со щается окно, в которой зал злняется небольшой прямоугольник. Часть прямоугольника останется незаполненной. Профамма в этот момент приостанавливает работу, ожидая нажатия на клавишу Enter. За гем осуществляется вывод и запо знение случайных окружностей до тех пор, пока в. будет нажата любая клавиша. Прямоугольник заполняется полностью, если вме- сто типа LtSlashFill (косая штриховка линиями обычной толщины) используезся SlashFill (штриховка утолщенными линиями). Если программа будет работать достаточно долго, она може г «зависнуть», чзо лишний раз свидетельствуе г о не- совершенстве реализованно! о в ней алгори гма. Uses Graph, CRT, з ar d, r, e, x, у, c : Integer; begin {Инициируем графику} d := Detect, InitGraph) d, i,I ’); e := GraphResult; if e о grOk then . . Wr teLnfGi aphErroi Msg(eJ) else begin [Co iдаем прямоугольное окно} x := GetMaxX div 4; у. := GetMaxY div 4; Rectangle(x.y,3 *x,3*y); SctVicvvPort(x+l,y+1, 3*x-l,3*y-l,ClipOn); {Демонстрируем заливку маленького прямоугольника} SetPillStyle(LtSlashFill,GeiMaxColor): Rectangle(0.0.8.20); FloodFill( 1.1 .GetMaxColor). OutTextXYl 10,25,'Press Enter...'); Readl n; {Ждем нажатия Enter} (Выводим окружности до тех нор, пика не будет нажата любая 1 тавиша} repeat {Определяем случайный стиль заливки} SetFillStyler Random} 12),Randorr.iGetMaxColor- 1)); {Задаем координаты центра и цвет окружности} х := Random (GetMaxX div 2); у := Random (GetMaxY div 2); c := Random (succ(GetMaxC oloi));
62 Глава 2. Создание модульных программ, элементы теории модульного программирования, SetColor(c); {Выводим и заливаем окружность} Circle(x, у, Random(GetMaxY div 5)): FloodFill (x, у, с) until KeyPressed, if ReadKey=#O then x := ord(ReadKey); CloseGraph end end. Процедура Bar Заполняет прямоугольную область экрана. 3ai оловок: Procedure Bar( X LY1.X2.Y2: Integer); Здесь XJ...Y2 - координаты левою верхнего (XI, Y1) и правого нижнего (Х2. Y2) углов закрашиваемой области. Процедура закрашивает (но не обводит) прямоугольник текущим образ- цом узора и текущим цветом, которые зстанавливаются процедурой SetFillStyie. Следующая программа дает красивые цветовые эффекты (закраска слу- чайных прямоугольников). Uses Graph. CRT; var d, г, e : Integer; begin {Инициируем i рафику} d : - Detect; InitGraph(d, r, "); e := GraphResult; if e о grOk then WriteLn(GraphErrorMsg(e)) else begin {Создаем окно в цен гре экран} d := GetMaxX div 4; r := GetMaxY div 4; Rectangle(d,r,3*d,3*r); SetVievvPort(d+l,rH,3*d-l,3*r-l,ClipOn); {Цикл вывода и закраски случайных многоугольников} repeat SetFillStyle(Random(12),Random(succ(GetMaxColor))); Bar(Random(Ge tMaxX),Random! Ge tMaxY), Random(Ge tMaxX),Random(Ge tMaxY)); until KeyPressed, if ReadKey=#O then d := ord(ReadKey); CloseGraph end end. Процедура Bar3D Вычерчивает трехмерное изображение параллелепипеда и закрашивает его переднюю грань. 3ai оловок: Procedure Bar3D (X1.Y1,X2,Y2,Depth: Integer; Top: Boolean):
ВЫСОКОУРОВЧЕВЫ МЕТОЮ > Н ЮРМАТИКИ И ПРОГРАММИРОВАНИЯ. 63 Здесь XI... Y2 - координаты левою верхнего (XI, Y1) и правого нижне^, (Х2, Y2) углов передней 1 рани; 1 Jepth - трет ье измерение трехмерного и зображе- ния («г тубина») в пикселях; Тор - способ изображения верхней грани Если параметр Тор имеет значение True, верхняя грань параллелепипеда вычерчивается в противном случае - не вычерчивается тот вариант использует- ся для изображения поставленных дру1 на друз а параллелепипедов. I см. еле зую ший пример). В качестве значения эт ого параметра может использоваться одна из следующих констант, определенных в моду ле Graph const TopOn = True; TopOfl False; При вычерчивании используется текущий стиль линий (SetLineSryle) и текущий цвет (SetColor). Передняя грань заливается текущим ст илем заполнения (SetFillStyle). Процедура обычно применяется при построении столбиковых диа!рамм. Следует учесть что пара тлелепипед «прозрачен», т.е за его незакрашенными i ра- нями могут быть ви цны дру гие элементы изображения < ледующая программа иллюстрирует различные аспекты применения процедуры Bar3D Uses Graph.1 R1; var d, r, e: Integer; begin {Инициируем графику} d Detect; Ini-tGraph(d, r, "); e := GraphResult; it' e <-> grOk then WriteLn(GraphErrorMsg(e)) else begin {Столбик с верхней гранью } Bar3D (80, 100. 120, 180, 15. TopOn); {Столбик без верхней грани;] Bar3D(15O, 150, 190. 180, 15, TopOff): {Этот столбик "стоит” на следующем и прозрачен:} Bar3D (230. 50. 250 150, 15.1 opOnl; Bar3D (220, 150, 260, 180, 15, TopOn): {У этого столбика нет верхней грани, и поз гому' он не мешает поставлен- ному на него сверху:} ВагЗП (300^ 150. 340, 180. 15. 1 opOff); Set! ineStyle(3,0,l); SetColor(Yellow); Setl iliSty le(LtSlashFill. Yellow); Bar3D (300. 50. 340. 150, 15. TopOn); ifReadKey=#Othend := ord(ReadKey); CloseGraph; end end.
64 Глава 2. Создание модульных программ, элементы теории модульного програмиирова1 hi . Процедура Fill Foly Обводит линией и закрашивает замкнутый многоугольник. Заголовок: Procedure FillPolyl N: Word; var Coords); Здесь N - количество вершин замкнуто! о многоугольника; Coords - пере- менная типа PointType, содержащая координаты вершин. Координаты вершин задаются парой значений типа Integer: первое опре- деляет горизонтальную, второе - вертикальную координаты. Для них можно ис- пользовать следующий определенный в модуле тип. type PointType = record х, у : Integer end; Стиль и цвет линии контура задаются процедурами SetLineStyle и SetColor, тип и цвет заливки - процедурой SetFillStyle. В следующем примере на экран выводятся случайные закрашенные мно- гоугольники. Uses Graph, CRT; var d, r, e: Integer; p : array [1 ..6] of PointType; n, k : Word, begin {Инициируем iрафику} d :- Detect; InitGraph} d, r,"); e GraphResult; if e о grOk then WriteLn(GraphErrorMsg(e)) else begin {Создаем окно в центре экрана} d := GetMaxX div 4; г := GetMaxY div 4; Rectangle(d,r,3*d,3*r); SetVievvPort(dH l,r H,3*d-I,3*r-1,ClipOn); {Цикл вывода случайных закрашенных многоугольников} repeat {Выбираем случайный цвет и узор) SetFillStyle(Random( 12),Ranaom(succ(GetMaxColor))); SetColor ( Random(succ(GetMa\Color))); {Назначаем случайные координат ы} n := Random (4) + 3 ; for k := 1 to n do with p[k | do begin x : = Random (GetMaxX div 2); у := Random (GetMaxY div 2) end; FillPoly (n. p) {Выводим и закрашиваем} until KeyPressed; if ReadKey=#0 then k := ord(ReadKey); CloseGraph end end.
ВЫСОКОУРОВНЕВЫЕ МЕТОДЫ ИНФОРМАТИКИ И ПРОГРАММИРОВАНИЯ 65 Процедура FillEUipse Обводит линией и заполняет эллипс. Заголовок: Procedure FillEllipse(X,Y,RX,RY Integer); Здесь X, Y - координаты центра; RX, RY- горизонтальный и верт икаль- ный радиусы эллипса в пикселях. Эллипс обводится линией, заданной процедурами SetLineStyle и SetColor. и заполняется с использованием параметров, установленных процедурой SetFillStyie. Процедура Sector Вычерчивает и заполняет эллипсный сектор. Заголовок: Procedure Sec- tor(X,Y: Integer; BegA,EndA,RX,RY: Word); Здесь BegA, EndA - соответственно начальный и конечный углы эллипс- ного сектора. Остальные параметры обращения аналогичны параметрам процеду- ры FillEUipse. В следующей программе на экран выводятся случайные закрашенные эл- липсы и секторы. Для выхода из программы нажмите любую клавишу. Uses Graph, CRT; var d. г, e : Integer: begin {Инициируем графику} d := Detect; InitGraphfd, r, "); e := GraphResult; if e <> grOk then Write Ln(GraphErrorMsg( e)) else begin {Создаем окно в центре экрана} d := GetMaxX div 4; г := GetMaxY div 4; Rectangle(d.r,3 *d,3 *r); Set ViewPort(d f-1 ,r+1,3 *d-1,3 *r-1 .ClipOn); {Цикл вывода} repeat SetFillSty le(Random( 12), Random(succ(GetMaxColor))); SetColor (Random(succ(GetMaxColor))); Sector(Random(GetMaxX div).Random(GetMaxY div 2), Random(360),Random(360).Random(GetMaxX div 5), Random(GetMaxY div 5)); FillEl. lipse (Random (GetMaxX div 2), Random(GetMaxY div 2) Random(GetMaxX div 5). Random(GetMaxY div 5)) until KeyPressed, if ReadKey-#0 then d := ord(ReadKey); CloseGraph end end. Процедура PieShce Вычерчивает и заполняет сектор окружности. Заголовок:
66 Глава 2. Создание модульных программ, элементы теории модульною программирования. Procedure PieSlice(X,Y: Integer; BegA,EndA,R: Word); В отличие от процедуры Sector, указывается лишь один горизонтальный радиус R. остальные параметры аналогичны параметрам процедуры Sector. Сектор обводится линией, заданной процедурами SetLineStyle и SetColor. и заполняется с помощью параметров, определенных пропеду рой SetFillSty 1е. 2.10.8. Сохранение и выдача изображений Функция ImageSize Возвращает размер памяти в байтах, необходимый для размещения пря- моугольного фрагмента изображения. Заголовок: Function ImageSize(Xl,Yl,X2,Y2: Integer): Wrord, Здесь XI... Y2 - координаты левого верхне! о (XI, Y1) и правого нижнего (Х2, Y2) углов фрагмента изображения. Процедура Getlmage Помещает в память копию прямоугольного фрагмента изображения. Заго- ловок: Procedure Getlmage(Xl.Y1 ,X2,Y2: Integer- var But) Здесь XI ...Y2 - координаты углов фрагмента изображения; Buf- перемен- ная или участок «кучи», куда будет помещена копия видеопамяти с фрагментом изображения. Размер Buf должен быть не меньше значения, возвращаемого функцией ImageSize с теми же координатами XI....Y2. Процедура Put Image Выводит в заданное место экрана копию фрагмента изображения, ранее помещенную в память процедурой Getlmage. Заголовок: Procedure Putlmage(X,Y: Integer; var Buf; Mode: Word); Здесь X,Y- координаты левого верхнего угла того места на экране, куда будет скопирован фрагмент изображения; But - переменная или участок кучи, откуда берется изображение; Mode - способ копирования. Как видно, координаты правого нижнего угла не указываются, так как они полностью определяются размерами вновь выводимой на экран копии изображе- ния. Координат ы левого верхнего угла могут быть какими угодно, лишь бы толь- ко выводимая копия уместилась в пределах экрана (если копия не может размес титься на экране, она не выводи гея и экран остается без изменений). Парамето Mode определяет способ взаимодействия вновь размещаемой копии с уже имеющимся на экране изображением. Взаимодействие осуществля- ется путем применения кодируемых этим параметром логических операций к ка- ждому биту копии и изображения Для указания применяемой логической опера- ции можно использовать одну из следующих предварительно определенных кон- стан г: const NonnalPut= 0;{Заменасуществующего изображения на копию} XorPut = 1 ^Исключительнее Hj 1И} OrPut = 2;{Объединительное ИЛИ} AndPut = 3;{Логическое И} NotPut = 4;{Инверсия изображения} Наиболее часто используются операции NormalPut. XORPut и NotPut.
Высокоуровневые методе1 информ ап кт и программирования 67 11ервая из них преет о ст ирает час гь экрана и на это место помещает копию и з на мяти в том виде, в каком она там сохраняется. Операция NotPut делает ти же са- мое, но копия выводит ся в инверсном виде. Для монохромного режима это озна чает замену свет ящихся пикселей на темные и наоборот. В цветном режиме опе- рация NotPut применяется к коду цвета каждо 'о пикселя. Например, для White (код 15 или в двоичном виде 1111) эта операция дас г код 0000 = 0 = 1 Lack, для Red - 4 ~ 0100 получим 1011 - 11 - LightQan и т.д. Операция XORPut, приме- ненная к тому же месту экрана, от куда была получена копия, сотрет эту часть эк- рана. Если операцию применить дважды к одному и тому же участку, вид изо- бражения на экране не изменится. Таким способом можно довольно лро(то пере- мещать изображения по экрану, создавая иллюзию движения. 2.10,9. Вывод текста Описываемые ниже стандартные процедуры и функции и одерживают вывод текстовых сообщений в 1 рафическом режиме. Эт о не одно и го же, ч го ис- пользование процедур Write или Writel лт. Дело в гом, что специально для графи - ческого режима разработаны процедуры, обеспечивающие вывод сообщений раз- личными шрифтами в 1 сризонтальном или верти' альном направлении, с измене- нием размеров и т.д. Однако в стандартных шрифта^, разработанных для этих целей фирмой Borland, отсу гствуе г кириллица, что исключает вывод г. сскоязыч - ных сообщений. С другой стороны, процедуры Write и WriteLn. после загрузки в память второй половины таблицы знакогенерат эра (а э га операция легко реализуется в адап герах EGA и VGA), способны выводи гь сообщения с использованием нацио- нального алфавита, но приэтом они не обладают мощными возможностями спе- циальных процедур Ниже описываются стандарт ные средства модуля Graph для вывода тек- ста. Процедура OutText Выводит текс говую строку, начиная с текущего положения указа геля. За- 1оловок: Procedure OutText(Txt: String); Здесь Txt - выводимая строка. При горизонтальном направлении вывода указатель смещается в конец выведенного текста, при вертикальном - не меняет своего положения. Строка вы- водится в соответствии с установленным сти тем и выравниванием. Если текст выходит за границы экрана, то при использовании штриховых шрифтов он отсе- кается, а в случае стандартного шрифта не выводится. Процедура OutTextXY Выводит строку, начиная с заданного мест а Заголовок: Procedure OutTextXY (X,Y: Integer, Txt: String); Здесь X. Y - координаты точки вывода: Txt - выводимая строка. Отлича- ется от процедуры OutText только координатами вывода. Указатель не меняет своего положения. Процедура SetTextStyle Устанавливает стиль текстового вывода на графический экран. Загс товок:
68 Глава 2. Создание модульных программ, элементы теории модульного программирования Procedure SetTextStyle(Font,Direct,Size: Word), Здесь Font - код (номер) шрифта; Direct - код направления; Size - код раз- мера шрифта. Для указания кода шрифта можно использовать следующие предвари- тельно определенные константы: const DefaultFont = 0;{Точечный шрифт 8x8} TriplexFont = 1;{Утроенный шрифт TRIP.CHR} SmallFont = 2;{Уменьшенный шрифт LITT.C HR} SansSerifFont = 3;{Прямой шрифт SANS.CHR} GothicFont = 4;{Готический шрифт GOTH.CHR} Эти константы определяют все шрифты для версий 4.0. 5.0, 5.5 и 6.0. В версии 7.0 набор шрифтов значительно расширен, однако для новых шрифтов не предусмотрены соответствующие мнемонические константы. В этой версии, по- мимо перечисленных, при обращении к SetTextStyle возможно использовать сле- дующие номера шрифтов: 11омер Файл Краткое описание 5 scri.chr «Pj кописный» шрифт 6 simp.chi Одноштриховый шрифт типа Courier 2: tscr.chr Красивый наклонный шрифт типа Times Italic 8 Icom.chr Шрифт типа Times Roman 9 euro . chr Шрифт типа Courier увеличенного размера 10 boid.chr Крупный двухштриховый шрифт Шрифт DefaultFont входит в модуль Graph и доступен в любой момент. Это единственный матричный шрифт, т.е. его символы создаются из матриц 8x8 пикселей. Все остальные шрифты - векторные: их элементы формируются как совокупность векторов (штрихов), характеризующихся направлением и размером. Векторные шрифты отличаются более богатыми изобразительными возможно- стями. но главная их особенность заключается в легкости изменения размеров без существенного ухудшения качества изображения. Каждый из этих шрифтов раз- мещается в отдельном дисковом файле. Если необходимо использовать какой- либо векторный шрифт, соответствующий файл должен находиться в каталоге, в противном случае вызов этого шрифта игнорируется и подключается стандарт- ный. Шрифт DefaultFont создается графическим драйвером в момент инициа- ции графики на основании анализа текстового шрифта. Поэтому, если ПК спосо- бен выводить кириллицу в текстовом режиме, тогда с помощью этого шрифта можно выводить русскоязычные сообщения и в графическом режиме. В осталь- ных шрифтах эта возможность появляется только после их модификации. Для задания направления выдачи текста можно использовать константы: const I lorizDir - 0;{Слева направо} VertDir - 1; {Снизу вверх} Стандартные процедуры OutText и OutTextXY способны выводить сооб- щения лишь в двух возможных направлениях - слева направо или снизу вверх. Зная структуру векторных шрифтов, нетрудно построить собственные процедуры вывода, способные выводить сообщения в любом направлении.
Высокоуровневые методы информатики и программирования. 69 Каждый шрифт способен десятикратно изменять свои размеры. 1 азмер выводимых символов кодируется параметром Size, который может иметь значе- ние в диапазоне от 1 до 10 (точечный шрифт - в диапазоне от 1 до 32 j Если зна- чение параметра равно 0. устанавливается размер 1, если больше 10 - размер 11 Минимальный размер шрифта, при котором еще отчетливо ра сличаются все его детали, равен 4 (для точечного шрифта - 1) Следующая программа демонстриру ет различные шрифты. Их размер вы- бран так, чтобы с [роки имели приблизительно одинаковую высоту. (Перед ис- полнением программы следует скопировать все шрифтовые файлы с расширени- ем CHR в текущий каталог.1! Uses Graph, CRT; const FontNames: array [1..10] ofString[4J - ( 'TRIP', 'LIFT" SAN S',' GOTH '. 'SCRI' , 1 SIMP ’ ,'TSCR 1 , ' LOOM ', ' EURO',' BOLD'): Tabl - 50; Tab2 = 150; Tab3 =220; var d. r. Err,{Переменные для инициации графики) Y.dY.{Ордината вывода и ее приращение} Size.{Pa3Mep символов) МахГош.{ Максимальный номер шрифта} k: Integer;{Номер шрифта) NT. Si Яг. SynibT: Si ing; [Строки вывода} с: Char: {--------------} Procedure OuiTextWithTab( SI, S2. S3, S4: String); {Выводит строки SI ..S4 с учет ом позиций табуляции Tabl. ТаЪЗ} begin MoveTo( <1 ab’.-TextWidth(Sl)) div2 Y); OutTexi (SI); Move Го(Т abl ИТ ah2-Tabl-TextWidth,'»2)) div2,Y); Out! ext (S2j; MoveTo(Tab2i-(l ab3-Tab2-TextWidth(S3)) die 2,Y); OutTcxt(S3); if S4='Symbols’then {Заголовок колонки Symbols} Movelo((Tab3 T-GetMaxX-FextWiddi(S4)) div 2,Y) else {Остальные строки) MoveTol 1 ab3 <-3, У), OutText(S4) end; {---------} begin {Инициируем графику} InitGraph(d,r,''); Err GrapFResult; if F.rrogrOk then Write! ,n(GraphErrorMsg(Err)) else
70 ГЛАВА 2. СОЗДАНИГ МСДуЛьНЫХ ПРОГРАММ, ЭЛЕМЕНТ! ТЕОРИИ МОДУЛЬНОГО ПРОГРАММИРОВАНИЯ. begin {Определяем количество шрифтов:) {S1FD1 1 VER70'} MaxFont := 10; . {SF.LSE) MaxFont := 4; {$] NDIF) SelTextStyle(l,0.4); Y := 0; OutTextWi th I ab('N','Name',Size',’Symbols'); {Определяем высоту Y линии заголовка} Y := 4* TextHeightf Z') di v3; Line(0,Y,( relMaxXY); {Определяем начало Y таблицы и высоту dY каждой строки } Y := 3*TextHeight('Z') div 2; dY (Ge MaxY-Y) div (MaxFont); {Готовим строку символов} SymbT :="; for c 'a' to 'z' do SymbT := Sy ml >T+c; {Цикл вывода строк таблицы] for k := 1 to MaxTont do begin Size 0; {Увеличиваем размер до тех пор, пока высота строки не станет приб шзи- гельно равна dY) repeat incfSize); Set fextStyle(k.O, Size t-1): until (TextHeight(‘Z')>=dY) or (Size=10) or (Textwidth(FoniNamec [k])>(Tab2-Tabl)) {Готовим номер NT и размер SizeT шрифта} Str(k.NT): Str(Size,Si <eT); {Выводим строку таблицы* SetTextStyle(kWorizDir.Size): OutTextWithTabiNT.Fonl Names[k] SizeT, Sy mol) inc(Y.dY) end; {Рисуем линии рамки} Rectangle(0,0,GelMa <X,GetMaxY); Lined abl,0, fabkGetMaxY); Lined ab2,0,Tab2.GetMaxY)’ Lined ab3,0,Tab3,GetMaxY); {Ждем инициат ивы пользователя} ReadL n; CloseGraph end end
ВЫСОКОУ ’ОВНЕВЫЕ МЕТОДЬ ИНС. РМАТИКИ И ПРОГРАММИРОВАНИЯ. 71 Процедура SetTextJustify Задас г выравнивание выводимого текст а по отношению к текущему по- ложению указат еся или г заданным координатам. 3 irо ювок: Procedure SetTextJustify(Horiz,Vert: Word); Здесь 1 loriz - горизонтальное выравнивание; Vert - вертикальное выравни- вание. Выравнивание определяет, как будет размещаться текст - левее или правее указанного места, выше ниже или по центру. Здесь можно использовать такие константы: const LeftText - 0; £ Указатель слева от текст а} CenterText= 1:{Симметрично слева и справа,верху и снизу} RightText = 2; {Указа гель справа от текста} Bottom! ext- 0;{Указатель сни зу or текста) Top! exl = 2; {Указат ель сверху от текста} Следует обрати гь внимание на неу дачные имена мнемонических кон- стан г: если, например, задать LeftText, ч го в переводе означает «Левый Текст», сообщение будет расположено справа от текущего по юженмя указателя (при вы- воде процедурой OutTextXY - справа от заданных координат). Также «наоборот» трактуются и остальные константы. Следующая программа иллюстрирует различные способы выравнивания относительно центра i рафическо! о экрана. Uses Graph, CRT; vai d, г, e : Integer; begin {Инициируем графику) d := Detect, InitGraphl d„ r,'') ; e := GraphResult: if e о grOk then WriteL n(Gi aphErroi Msg(e)) else begin {Выводим перекрестие линий в центре экрана) I .ine(0,GetMaxY div 2 GetMaxX,GetMaxY div 2); Line(GetMaxX div 2,0 GetMaxX div 2,GetMaxY); {Располагаем текст справа и сверху от цент ра) SetTextStyle(lriplexFont.HorizDir,3); SetTcxtJust ify(Lcftl exl 1 lottom Г ext) OutTextXY (GetMaxX div 2, GetMaxY div 2, '1 ,eftText,Bottom1 exf); {Располагаем текс г слева и снизу) SetTextJustify (Right! ext, Тир lext) Out fextXY (GetMaxX div 2, GetMaxY div 2,'Right I ext, TopText'); if ReadKey=#0 then d := ord(ReadKcy); CloseGraph end end. Процедура SetUserCharSize Изменяет размер выводимых символов в соответствии с заданными про- порциями. Заголовок:
72 Глава 2. Создание модульных про, рамь , элементы геол и ходульно о программирования Procedure SetL'serCharSize(XI.X2,Yl,Y2: Word): Здесь X1...Y2 - выражения гига Word, опреде 1яющис пропорции по юри- зонтали и вертикали. Процедура применяется только по отношению к векторным шрифтам. Пропорции задают масштабный коэффициент. покашгвающий во сколько раз увеличится ширина и высота выводимых символов по отношению к стандартно заданным значениям. Коэффициент по гориюнтали находится как отношение XI к Х2, по вертикали - как отношение Y1 к Y2. Чтобы, например, удвоить ширину символов, необходимо задать Х1=2 и Х2=1 Стандартный размер символов уста- навливается процедурой SetTextStyle, которая отменяет предшеству ющее ей об- ращение к SetUserCharSize. В следующем примере демонстрируется изменение пропорций умень- шенного шрифта. Uses Graph CRT; var d, г, e : Integer; begin {Инициируем графику} d := Detect, .InitGraph (d, r, "); e := GraphResult; if e о grOk then Writel n(GraphE.rrorMsg(e)) else begin Move! о (0, GetMaxY div 2); Sei TextSty le I SmallFont HorizDir, 5); SetTextJustify (LeftText, Bottom Text); {Выводим сообщение стандартной высотой 5} OutText ('Normal Width,'); {Удваиваем ширину шриф га} SetUserCharSize (2, 1, 1, 1); OutText (' Double Width,'); {Удваиваем высоту, возвращаем стандартную ширину} SetUserCharSize (I. 1, 2. 1), OutText (’Double 1 leight,'); SetUserCharSize (2, 1,2, 1) ; OutText (’ Double Width and Height'); if ReadKey-#0 then d := ord(ReadKey); CloseGraph end end. Функция TextWidth Возвращает длину в пикселях выводимой текстовой строки Заголовок: Function TextWidth (Txjt: String): Word; Учитываются текущий стиль вывода и коэффициент ы изменения разме- ров символов, заданные соответственно процедурами SetTextStyle и SetUserCharSize. Функция TextHeight Возвращает высоту1 nipt ф га в пикселях. Заголовок:
Высокоуровневые методы и форменки .1 npoi раммирования. 73 Function TexiHeight(Txt: String) Word: Процедура GetTextSettings Возвращает текущий стиль и выравнивание текста. Заги ювок: Piocedure Gel IextSettins(var 1 extlnfo: lextSettine slype); Здесь Textinfo - переменная типа TextSetting <Ty ре, который в модуле Graph определен следующим образом: type Text^uttingsType - record Font: Word, {Номер шрифт a} Direction: Word; {Направление} CharSize : Word; {Код размера} Horiz : Word; {Горизонтальное выравнивание] Vert: Word, {Вертикальное выравнивание} end; Функция InstallUserFont Позволяет программе использовать нестандартный векторный шрифт. За- головок ф\ нкции: Function InstallLherFontt F ile\ame: String): Integer; Здесь 1 ileName - имя файла, содержащего векторный шрифт. Как уже говорилось, в стан цартную поставку Турбо Пас каля версий 4.0 - 6.0 включены три векторных шрифта, для версии 1.0 - 10. Функция InstallUserFont позволяет расширить этот набор Функция возвращает и центификационный но- мер нестандартного шрифт а, который может использоват ься при обращении к процс, type SelTextStyle. Функция InstallUserDriver Включает нестандартный графический драйвер в систему BG 1-драйверов. Заголовок функции: Function InstallUserDriverfFileName: String; A utoDetectPtr. Pointer): Integer, Здесь FileName - имя файла, содержащего программу драйвера; AutoDetectPtr - адрес т эчки входа в специальную процедуру автоопределения си- па дисплея, которая в числе прочих процедур должна входить в состав драйвера. Эта функция расширяет и без toi о ,гостагочно обширный набор стандарт- ных графических драйверов и предназначена в основном, для разрабс гчиков ап- паратных средств. 2.10.10. Включение драйвера и шрифтов в тело программы В 1 у рбо 11аскалс имеется возможность вклю юния графического драйвера и штриховых шрифтов непосредственно в тело программы. Такое включение де- лает программу независимой от местоположения и наличия на диске драйверов и шрифтов, а также ускоряет подготовку графических программ к работе (шрифты и драйвер загружаются вместе с программой). Включение драйвера и шрифтов осу щестк тяется по с юдующей общей схеме. Сначала с помощью вспомогательной программы BINOBJ.EXE, входящей в комплект поставки 1’урбо Паскаля, драйвер и шрифты преобразуются в OBJ- файл (файл с расширением .OBJ). Для этого вне среды Турбо Паскаля необходи- мо вызвать утилиту BINOBJ с тремя параметрами: именем преобразуемого файла,
74 Глава 2 Создание модульных программ, элементы теории модулььогс программирования, именем получаемого OBJ-файла и глобальным именем процедуры. Эта имена, в принципе. могут быть произвольными, правильными для MS-DOS именами. На- пример: c:\tp'binobj cga.bgi cga cgadrv В результа ге такого обращения из каталога ТР на диске С будет вызвана программа BINOBJ, и ей будут переданы следующие параметры; CG A.BGI - имя файла с преобразуемым драйвером; CGA - имя файла с расширением .OBJ, т.е. CGA.OBJ, который будет по- лучен в результате исполнения программы BINOBJ; CGADRV- глобальное имя, под которым этот драйвер будет известен программе. После этого можно написать следующий фра! мент программы: Use., Graph; Procedure С G ADRV; external; {$! CGA.OBJ} var d, r, e : Integer; begin if RegisterBGIDriver (@CG ^DRV) < 0 then begin WriteLn (’Ошибка при регистрации драйвера’); halt end; d := CGA; r := CGAHi; InitGraph (d, r,"); Как видно из этого примера, в программе объявляется внешняя процедура с именем CGADRV (i лобальное имя, указанное при обращении к BINOBJ). при- чем дается директива компилятору отыскать в текущем каталоге и загрузить файл CGA.OBJ, в котором находится эта процедура Затем осуществляется регистрация драйвера путем обращения к функции RegisterBGIDriver. Единственным парамет- ром этой функции является адрес начала драйвера в памя ги (@CGADRV). Функ- ция возвращает значение типа Integer, которое служи г для контроля правильности завершения процедуры регистрации драйвера: если это значение меньше нуля - обнаружена ошибка, в противном случае функция возвращает номер зарегистри- рованного драйвера. В примере контролируется правильность регистрации драй- вера и, если ошибка не обнаружена, инициируется графический режим работы экрана. Аналогичным образом можно присоединить к программе стандартные штриховые шрифты (матричный шрифт 8x8 входит в состав модуля Graph и по- этому присоединять его не надо). Присоединение шрифта строится по описанной схеме за тем исключением, что для ею регистрации вызывается функция RegisterBGIFont. Например, после преобразования c:\Pascal\binobj litt.chr lift htt можно использовать операторы Procedure 1 ,itt;External; {$L Litt.obj} if RegisterBGU ont (@htt) < 0 then ...
ВЫСОКОУРСВНЕВЫ» МЕТОДЫ I НФОРМАТИКЙ I Г₽ОГ₽АММИРОВАТ ИЯ. 75 Следует обратите внимание: регистрация драйвера (шрифтов) должна предшествовать инициации i рафического режима. Регистрировать можно также драйверы (шрифты), которые не компили- руются вместе с программой, а загружаются в динамическую память. Н апример: Uses Graph; var р: Pointer; f: file; begin Assign(f'Litt.chr'); {Открываем <] айл} Reset(f.l); {LITT .CHR для чтения} GetMcmfpJileSizel f)); {Резервируем для него область кучи нужного раз- мера} BlockK.ead(f,pA,FilcSUe(f)){4HTaeM файл} Writel n(Registerl IGIFont (р)){Рсгис грируем шрифт} end 2.11. Стандартный модуль SYSTEM Мо.цуль SYS! LM является основной библиотекой Турбо ] 1аскаля Он реализует подпрограммы д тя всех встроенных возможностей, таких как ввод/вывод, обработка строк, эмуляция арифметического сопроцессора, j правле- ние оверлеями и динамическое распределение памяти Модуль S\ STEM исполь- зуется автоматически любым модулем или программой и никогда не указывается в предложении USES. 2.11.1. Константы модуля SYSTEM const ErrorAddr Pointei = NIL;{ Адрес ошибки времени выполнения} ExitProc Pointei = NIL; {Процедура выхода} ExitCode Integer 0;{ Выходной код} FileMode Byte — 2;{ Режим открытия файла} Freel.ist Pointer — П1Е;{Список свободных блоков кучи} HeapEnd Pointer NIL; [Конец кучи} HeapError Pointer — МЕ;{Функция обработки ошибок кучи} HeapOrg Pointer — NIL; {Начато кучи} HeapPtr Pointer — NIL; (Указатель кучи} InOul R.es Integer = 0; {Буфер результата ввода'вывода} OvrCodeL ist Word = 0;{Список оверлейных сегментов кода} OvrDebugPtr Pointer — Nil,; {A. ipec отладчика оверлеев} OvrDosHandle Word — 0;{Обработчик DOS оверлеев} Ovi EmsHan die Word — 0, [Обработчик EMS оверлеев} OvrHeapEnd Word — 0,{Конец буфера оверлеев} OvrHeapOrg Word = 0;{ Начало буфера оверлеев} OvrHeapPrt Word = 0,{Указатель буфера оверлеев} OvrHcapSize Word = 0,{Начальный размер буфера оверлеев} OvrLoadl .ist Word 0,{Список загруженных оверлеев} RandSeed Longlnt — 0,{Опорное значение генератора случ. чисел} PrefixSeg Word — 0,{ Префикс программного сегмента} Seg0040 Word — $0040{Cei мент $0040}
76 Глава 2. Созданиг модульных программ, элементы теории модульного прсм рамчирования. SegAOOO Word = $A000 [Сегмен г SA000) SegBOOO Word = SBOOO {Сегмен г SBOOO} SegB800 Word = SB800 {Сегмен г SB800} Selectorinc Word = $1000{Шаг наращивания селекторов} = 0;{Указагель на нижнюю границу стека} = 0;{11ризнак наличия процессора 80x86] StackLimit Word Test8086 Byte Test8087 Byte = 0;{Признак наличия сопроцессора} OvrCodeList, OvrHeapSize, OvrDebugPtr, OvrHeapOrg, OvrHeapPti, OvrHeapEnd, OvrlfeapList, OvrDoslIandle и OvrEmsHandle используются модулем Overlay для реализации администратора оверлеев. Буфер оверлеев размещается между сегментом стека и кучей, и OvrHeapOrg и OvrHeapEnd содержат адреса начала и конца сегмента. Размер буфера оверлеев по умолчанию соответствует размеру максимального оверлея в программе; если в программе нет оверлеев, то размер оверлейного буфера равен нулю. HeapOrg. IleapPtr, HeapEnd, FreeList. HeapError используются админист- ратором кучи для реализации распределения динамической памяти Переменные ExitProc, ExitCode и ErrorAddi реализуют процедуры выхода. PrefixSeg содержит сегментную часть адреса префикса программного сегмента (PSP). StackLimit содержит смещение от нижней границы сегмента стека, соот - ветствующее наименьшему допустимому значению регистра SP. Обычно StackLimit равен нулю; если программа откомпилирована с опциями {SN+.E+}, компилятор будет устанавливать его равным 224 для резервирования рабочего пространства на нижней границе сегмента стека, используемого для эмуляции сопроцессора. InOutRes используется встроенными программами ввода/вывода для за- поминания значения, возвращаемого при последующем вызове стандартной функции lOResult. RandSeed содержит опорное число генератора случайных чисел. При при- сваивании конкретного значения этой переменной функция Random будет гене- рировать строго определенную последовательность псевдослучайных чисел. Про- цедура Randomize заносит в переменную RandSeed текущее системное время и. тем самым, обеспечивает новую псевдослучайную последовательность при оче- редном прогоне программы. FileMode позволяет изменить режим доступа, с которым открываются ти- пизированные и нетипизированные файлы стандартной процедурой RESET. Тек- стовые файлы этой процедурой открываются только для чтения Seg0040 хранит сегмент участка памяти, который MS-DOS использует для размещения своих переменных. SegAOOO содержит сегмент начала видеопамяти для графического режима работы, a SegBOOO и SegB800 -cei менты видеопамяти для текстового режима. Selectorinc используется как шаг наращивания т.н. селекторов - указате- лей, обеспечивающих линейную модель памяти. Test8086 хранит результат теста автообнаружения процессора Intel 80x86, a Test8087 - сопроцессора. 2.11.2. Переменные модуля SYSTEM var Input; Text;{Стандартный файл ввода}
ВЫСОКОУРОВНЕВОЙ МЕТОДЫ ИНФОРМАТИКИ и г PCI РАММИРОВАНИЯ. 77 Output: Text;{Стандартный файл вывода} SavelntOO: Pointer;{Сохранение вектора $00} Savelnt75: Pointer; I Сохранение вектора $75} Input и Output - стандартные файлы, необходимые в каждой реализации языка Паскаль. По умолчанию они ссылаются на стандартные входные и выход- ные файлы ДОС: Input - на клавиатуру, Output - на экран. В момент загрузки среда Турбо Паскаля изменяет значения 18 векторов прерывания (векторы $00. $J2, $1N, $21, $23, $24, $35, $36, $37, $38. $39, $ЗА, $ЗВ, $ЗС, $3D, $3E. $3F и $75). В переменных SavelntXX сохраняются старые значения этих векторов (XX - номер вектора: SavelntOO - для вектора $00, SavelntlB - для вект ора $ 1В и т.д.) 2.11.3. Стандартные процедуры и функции модуля SYSTEM Процедуры управления Procedure Break обеспечивает немедленный выход из операторов повто рения. Procedure Continue завершает очередной итерационный цикл операторов повторения. Procedure Exit позволяет немедленно выйти из текущей подпро!раммы. При вызове из тела основной программы завершает ее работу. Procedure Halt [ 1 ExitCode: Word)} осганав швает выполнение программы и возвращает управление в операционную систему. Необязательный параметр ExitCode определяет код завершения программы. Procedute RunEnor | (ErrorCode: Byte)] останавливает выполнение про- граммы и генерирует ошибку периода выполнения программы. Необяза гелъный параметр 1 rrorCode определяет код ошибки. Процедуры (инамического распределения памяти Procedure Dispose(var Р: Pointer [.Destructor]) уничтожает динамическу ю переменную, связанную с указателем Р. Необязательный парамет р Destructor оп- ределяет метод-десгруктор для динамического объекта. Procedure FreeMemfyar Р: Pointer. Size: Word) уничтожает динамическую переменную Р размером Size байт. Procedure GerMemtvar Р: Pointer: Size: Word) создает новую динамиче- скую переменную Р заданного ра 1мера Size. Procedure Mark(var Р: Pointer) записывает в у ка sa геле Р текущее состояние кучи Procedure New(var Р: Pointei [.Constructor]) создает новую динамическую переменную, связанную с указателем Р. Необязательный параметр Constructor определяет метод-конструкгор для динамического объекта. Procedure Release (var Р: Pointer) возвращает кучу в сост ояние. которое было сохранено в указателе Р проце. ;урой Mark. Функции динамического распределения памяти Function MaxAvail: Longlnt возвращает оазмер наибольшего непперывно- го свободно! о б. юка ку чи, соот ветствующий размеру наибольшей динамической переменной, которая может быть помещена в кучу.
'о Глава 2. Создание модульных программ, элементы теории модульного программирования. Function MemAvail; Longlnt возвращает количество имеющихся в куче свободных бай г памяти. Функции преобразования 11роцедуры Раск и I пРаск. определенные в стандартном Паскате. в Ту рбо Паскале не реализованы. Function Chr(X: Byte): Char возвращает символ с заган- ным порядковым номером X. Function Ord(X) : Longlnt возвращает порядковый номер, соответствую- щий значению X порядкового типа Function Round (R: Real) : Longlnt округляет значение R вещественного типа до ближайшего целого Function Trunc(R. Real): Lpnglnl усекает значение вещественного типа до значения типа I onglnt путем отбрасывания дробной част и. Арифметические функции При компи гяции в режиме использования сопроцессора или его эмуляции арифметические функции возвращают значение типа EXTENDED в противном случае - типа REAL. Function Ab:и R: Real): Real во (вращает абсолютное значение аргумента. Function ArcTantR: Real): Real возвращает арктангенс api умен га. Function Cos(R: Real): Real возвращает косинус аргумен га. Function Exp(R: Real): Real во (вращает экспоненту api у мента. Function Frac(R. Real): Real возвращает дробную часть аргумента Function Int(R; Real): Real возвращает целу ю часть аргумента. Function LnCR: Real) : Real возвращает натуральный логарифм аргумента. Function Pi: Real возвращает значение числа pi=3.1415926535897932385. Function S.n(R: Real) Real возвращает синус аргумента. Function Sqr(R: Real): Real возвращает аргумент в квадрате. Function Sqn(R; Real): Real возвращает квадратный корень аргумен га. 11роцедуры порядкового типа Procedure Dec (car X [; DX: Longlnt] ) уменьшает значение переменной X на величину DX, а если параметр DX не задан - на 1. Procedure Inc (саг X f; DX: Longlnt]) увеличивает значение переменной X на величину DX, а если параметр DX не задан - на 1. Функции порядкового типа Function Odd(X) : Boolean проверяет, является ли аргумент нечетным чис- лом. Function Pred(X) возвращает предшествующее значение аргумента. Тип результата совпадает с типом аргумента. Function Si>(X) возвращает последующее значение аргумента. Тип ре- зультата совпадает с типом аргумента. Строковые процедуры Procedure Delete (var S: String: Index, Count: Integer) удаляет C ount симво лы из строки S, начиная с позиции Index. Procedure Insert (SubS: String; var S: String: Index Integer) вставляет под- строку SubS в строку 5, начиная с позиции Index. Procedure Sti(X [ width |: Decimals]], var S: String) преобразует численное
Bt СОКОУРОВНЕВЫЕ МЕТОДЫ ИНФО ’МАТИКИ И 1РОГРАММИРОВАНИЯ. 79 значение X в его строковое представление S. Procedure ValtS. String: var X; var Code: Integer) преобразует строковое значение S в его численное представ, гение X. Параметр Code -содержит признак ошибки преобразования (0 - нет ошибки) Строковые функции Function Concat(Sl [, S2,....SN]): String выпо шяет конкатенацию последо- вательности строк Function CopyfS: String; Index, Count: Integer): String возвращает подстро- ку из строки S. начиная с позиции Index и длиной Count символов Function Length! S: String): By te возвращает текущую длину с сроки S Function PostSubS. S. String): Byte возвращает позицию, начиная с кото- рой в строке S распола! ается подстрока SubS (О - S не содержит SubS). Функции для работы с указателями и адресами Function Add. (X): Pointer возвращает адрес заданного объекта X. Function Assigned: (var PI : Boolean проверяет, хранит ли ли указатель Р значение, отличное от NII.. и возвращает TR 1'Е в этом с 1учае. Function CSeg: Word возвращает текущее значение pet истра CS Function DSeg: Word во (вращает текущее значение регистра DS. Function 01 s (X) . Word возвращает смещение заданного объект а. Function PtrfSeg, 0£s: Word)’ Pointer преобразует сегмент Seg и смещение Ofs в значение типа указатель. Function Seg (X): Word возвращает сегмент для заданной объек га X. Г unction SPtr: Word возвращает текущее значение pei истра SP. Function SSeg: Word во 1вращает текущее значение регистра SS. Процедуры разного назначения Procedure Exclude (var S: set of T; 1:1) исключает элемент 1 из множес гва S. Procedure FillChar(var X; Count: Word; Value) заполняет заданное количе- ство Count последовательных байт переменной X указанным значением Value (выражение любого порядкового типа). Procedure Include (х ar S: set of Т; I 1) включает элемент Т во множество S. Procedure Move (var X. Y; Count: Word) копирует заданное количест во по- следовательных бай г из источника X в переменную Y. Proced tre Randomize инициали тирует случайным значением (текущим системным временем) в» троенный генератор псевдослучайных чисел. Функции разного назначения Function 1 h(X: Word): Byte возвращает старший бай г аргумен га X. Function High (X) во тврашает максимальное значение порядкового типа. Fund ion Lo(X: Word): Byte возвращает младший байт аргумента X. Funci inn Loxv(X) возвращает минимальное значение порядкового типа. Fund ion ParamCouni: Word возвращает число параметров, переданных программе в командной строке (с гроке вызова). Function ParamStr(N: Byte): string возвращает N-ый параметр командной строки. Function Random [ (Ranee: Word)] возвращает псевдослучайное число. Ес-
80 Глава 2. Создание модулы >ix программ, элементы теории гот.ульно о этограммироьания ти параметр Range опущен, функция возвращает вс шественное число в диапазоне от 0 до 1, если указан - целое чис то в диапазоне от 0 до Range-1. Function SizeOf(X): Word возвращает чисто байт, занимаемых аргумен- том. Function Svap(Kj производит перестановку старших и младших байт двухбайтного аргумента X. Тип функции соответс гвует титр аргумента. Function СрС ase(C: char): Chai' преобразует латинскую букву в заглавную. Процедуры ввода/вывода Procedure Assign (var F; Name: String) связывает внешний файл Name с файловой переменной F. Procedure ChDir(S: String) j станавливает текущий каталог. Procedure Close (var F) закрывает открыт ый файл. Procedure Erase (\ai F) удаляет внешний файл Procedure GetDir (D- Byte; var S: String) во шращает каталог по умолчанию S на заданном диске D. Procedure MkDirt (S: String) создает подкатало! S. Procedure Rename (var F) переименовывает внешний файл. Procedure Reset (var I) от крь вает сущест вующий файл для чтения или из- менения. Procedure Rewrite (var F) создает и открывает новый файл Procedure RmDir(S: String) удаляет пустой подкаталог. Procedure Seek (var F, N: Longlnt) устанавливает текущу ю позицию файла на указанный элемент (не используется с текстовыми файлами). Procedure Truncate (var F) усекает размер файла до текущей позиции в фай. ie (не используется с т екстовыми файлами) Функции ввода/вывода Function FOF (var I) : Boolean возвращает для файла F признак конца файла. Function FilePos (var Г) : Longlnt возвращает текущую позицию в файле (не используется с текстовыми файлами) Function FileSize(vat F) : Longin' возвращает текущий размер файла (не используется с т екстовыми файлами). Function IQResult: Integer возвращает целое значение, яв тяющееся с< >ст оя- нием последней выполненной операции ввода/ьывода. Процедуры для текстовых файлов Procedure Append (var F Text) открывает существующий файл д. тя р зеши рения. Procedure Flush (var F: Textt выта ткивает буфер файла выво ia. Procedure Read фаг F: Text;] VI [, V2....,VN]'l считывает одно или более значений из текстово! о файл з в одну или более п гременных. Procedure Readle выполняет те же деист вия, ч го и Read, а п этом делает пропуск до начала следующей строки файла. Procedure SetTextBuf (var F: Text: vat Buf [; Size: Word]) назначает бу фер ввода/вывода для текстового файла Параметр Size определяет длину буфера в байтах (если Size опушен, длина буфера равна 12Я байтам). Procedure Write([vai F: Text;] VI [, V2,...,VN|1 записывает в текстовый
ВЫС0К0УР0Вг1ЕВо1с МЕТОДЫ ИН ЮРМАТйкИ И ПРОГРАММИРОВАНИЯ. 81 файл одно или более значений. Procedure WriteLn выполняет те же действия, что и Write, а затем добавля- ет к файлу маркер конца строки. Функции для текстовых файлов Function Eolnt (var F: 1 ext): Boolean возвращает признак конца строки. Function SeekEof [ (var F: Text)]: Boolean во шрашает признак конца файла. Предварительно пропускает все пробелы, символы t абуляции и признаки конца строк. Function SeekEoln | (var F: Text)]: Boolean возвращает признак конца стро- ки. В отличие от Eoln предвари гельно пропускает все пробелы и символы табуля- ции. Процедуры для нетипизированных файлов Procedure BlockReadfvar F: File; vai Buf; Count; Word [;var Result; Word]) Считывает в переменную Buf Count записей из файла F. Необяза гельный пара- метр Result содержит истинное количество считанных записей. Procedure BlockWi ite(var F; File; var Buf; Count: Word [;var Result: Word]) Передает Count записей из переменной Bufe файл F Необязательный параметр Result содержит истинное количество переданных записей. 2.12. Модуль DOS Модуль Dos реализует ряд очень полезных программ операционной сис- темы и обработки файлов. Ни одна из программ модуля Dos не определена в стандартом Паскале, и поэтому они размещены в собственном модуле. 2.12.1. Константы модуля DOS Константы регистра флагов Следующие константы используются для проверки отдельных битов фла- га в регистре Flags после вызова Intr или MSDOS: const FCarrv= $0001; FAuxiliary = $0010; FSign = $0080, FParity= $0004; FZero = $0040; FOverFlow - $0800; Константы режима доступа к файлу const fmClosed =$D7BO. {Маска режима файл закрыт] fmlnput =$D7B 1; {Маска режима открыт для чтения] fmOutput =$D7B2; {Маска режима открыт дтя записи] fmlnOut =$D7B3; {Маска режима открыт для чтения и записи] Констант ы атрибутов файла const Readonly = $01;{Маска только для чтения] Hidden = $02;{Маска скрытого файла] SysFile = $04;{Маска системного файла] VolumelD = $08.{ Маска заголовка тома) Directory- $10;{Маска каталога] Archive = $20.{Маска архивного, файла] AnyFile = $ЗР;{Маска любого файла)
82 Глава 2. Создание модульных программ, элементы теории модульного программирования. 2.12.2. Типы модуля DOS type {Типизированные и нетипизированные файлы] FileRec = record Handle : Word; Mode : Word; RecSize : Word; Private : array [1 -6| of Byte; L'serData : array 11.. 16] of Byte; Name : array [0..79] of Char; end; {Текстовые файлы} TextBuf= array [0.. 127] of Char; TextRec - record Handle Word; Mode Word; BufSize Word; Private Word; BufPos Word, BufEnd Word; BufPtr TextBuf; OpenT unc Pointer; InOutFunc Pointer; FlushFunc Pointer; CloseFunc Pointer; UserData array [1.. 16] of Byte; Name array [0..79] of Char; Buffer TextBuf; end; Registers = record case Integer of 0: (AX. BX, CX, DX. BP. SI, DI, DS. ES. Flags: Word); 1: (AL. AH, BL, BH, CL, CH, DL, DH: Byte); end; DataTime = record Year. Month. Day, Hour, Min, Sec: Integer; end; SearchRec = record File: array [ 1..21 ] of Byte; Attr: Byte; Time: Longlnt; Size: Longlnt; Name: String [ 12]; end; DirStr = String [67];{Диск и каталог} NarneStr = String [8]; [Имя файла] ExtStr = String [4]:{Расширение файла} ComStr = String [127];{ Командная ст рока} PathStr = String [79] .{Полный маршрут поиска файла}
ВЫСОКОУРОВНЕВЫЕ Ml ГОД >1 ИНФОРМАТИКИ И ПРОГРАММИРОВАНИЯ. 83 2.12.3. Переменные модуля DOS var DnsFrror: Integer; Значение, запомненное в 1 )osEi ror, представляет собой кол ошибки опе- рационной системы: О - нет ошибки 2 - файл не найден 3 - путь не найден 5 - доступ запрещен 6 - неверный обработчик 8 - нет памяти 10 - неправильная среда 11 - неправильный формат 18 - больше нет файлов 2.12.4. Процедуры и функции модуля DOS Процедуры даты и времени Procedure GetDate (var Year, Month, Day, DayOfWeek: Word) возвращает текущую дату. Procedure Get! Time (var F, vai Time: 1 .onglnt) возвращает дат; и время по- следнею обновления файла. Procedure Get! ime(var Hour. Minute. Second. Se» 1 Ou Vv ord) возвращает те- кущее время. Procedure PackTime(var Pack: Data! ime; var rime: Longlnt) преобразует за- пись Pack в, 4-байтовое упакованное значение дат ы и времени типа Longlnt, ис- пользуемое процедурой Set! Г ime. Полл записи DateTime не проверяются на диа- пазон. Procedure SetData (Year Mont1.., Day; Woid) устанавливает текущую дату. Procedure SetTTime (var F, rime; Longlnt) у с ганавливает время и дату по- следнего обновления фай ia Procedure SetTime(Hour, Minute. Second. SeclOO: Word) устанавливает те- кущее время. Procedure LnpackTimei 1 ime: Longlnt; vai Pack: Data! ime) преобразует 4- байтовое упакованное значение даты и времени, возвращаемое Getr Time, Find • First или TindNext. в распакованную запись типа Date! ime. Процедуры обслуживания прерываний Procedure Getlntyec (IntNo: Byte; var Vec: Pointer) возвращает адрес, хра- нящийся в указанном векторе прерывания. Procedure Intr (IntNo: Byte; var R: Registers) выполняет указанное про- граммное прерывание. Proceduie MSDos (var R: Registers) выполняет функцию операционной системы. Procedure SetlntVec (IntNo: byte; P: Pointer) устанавливает адрес для ука • занного век гора прерывания. Функции статуса диска Function DiskFreelDisk: Word). Longlnt возвпащает число свободных байт на указанном диске; Function DiskS;ze(Disk: Word): Longlnt возвращает полный объем указан-
84 Глава 2. Создан иг модульных программ, элементы геории модульного программирования. него диска в байтах Процедуры обработки файлов Procedure FindFirst(Path String; Attr: Byte; var Search; SearchRec) ищет в указанном или текущем каталоге первый файл, соответствующий заданному име- ни файла и набору атрибутов. Procedure FindNext (var Search: SearchR.ec) возвращает следующий файл, соответствующий имени и атрибутам, указанным в предыдущем вызове FindFrst. Procedure GetFAttrt (var F; var Attr: Byte) возвращает атрибуты файла. Procedure SetFAttr (var F; Ann Byte) устанавливает атрибуты файла Procedure FSpht(Path: PathStr; var Dir. DirStr; var Name: NameStr; var Ext: ExtStr) разбивает имя файла Path на 3 составные части (катален, имя файла, рас- ширение). Функции обработки файла Function FExpand(Name; PathStr) : PathStr берет имя файла Name и воз- вращает полное имя файла (устройство, каталог, имя и расширение). Function FSearchf Name: PathStr; DirList: String): PathStr ищет файл Name в списке DirList катало! ов. Элементы списка разделяются точкой с запятой. Процедуры обработки процессов Procedure Exec(Name: PathStr, CmdLine: String) выполняет заданную про- грамму Name с указанной командной строкой CmdLine. Proceuure Keep (Code: Word) завершает программу и оставляет ее рези- дентной в памяти. Procedure SwapVectors обменивает сохраненные векторы прерываний из переменных SavelntXX с текущими векторами. Функции управления программой Function DosExitCode: Word возвращает код завершения подпроцесса. Функции управ тения средой Function EnvCount: Integer возвращает число переменных окружения, со- держащихся в среде ДОС. Function EnvStr (Index: Integer): String возвращает указанну ю переменную окружения ДОС. Function GetEnv(RGV' String): String возвращает значение указанной пе- ременной окружения ДОС. Дополнительные процедуры Procedure GetCBreak (var CBreak: Boolean) возвращает состояние провер- ки Ctrl-Break. Procedure SetCBreak(CBreak- Boolean) устанавливает состояние проверки Ctrl-Break в ДОС. Procedure GetVerify(vai Verify: Boolean) возвращает состояние флага ве- рификации в ДОС. Procedure SetVerify (Verify: Boolean) устанавливает состояние фла: а ве- рификации в ДОС. Дополнительные функции Function DosVersion: Word возвращает номер версии ДОС.
Bt СОКОУРОВНЕВЫЕ МЕТОДЫ ИНФОРМАТИКИ И f РОГРАММИРОВАНИЯ. 85 ГЛАВА 3. ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В основе того или иною языка программирования лежит некоторая руко- водящая идея, оказывающая существенное влияние на стиль соответствующих npoi рамм. Исторически первой быта идея процедурною структурирования про грамм, в соответствии с которой программист до тжен быт решить, какие именно процедуры он будет использовать в своей программ^ а затем выбрать наилучшие алгоритмы для реализации этих процедур. Появление этой идеи было следы вием недостаточной изученности алгоритмической стороны вычислительных процес- сов, столь характерной для ранних программных разработок (сороковые - пят иде- сятые годы). Типичным примером процедурно-ориенти-рованно! о языка являете» Фортран - первый и, до сих пор, один из популярнейших языков программирова- ния. 1 (оследовательное использование и цеи пропсд' рно1 о структурирования про- грамм привело к созданию обширных библиот ек программирования, содержащих множество сравнительно небольших процедур, из которых, как из кирпичиков, можно строит ь «здание» программы. По мере прогресса в области вычислительной математики акцент в про • граммировании с тал смещаться с процедур в ст орону организации данных. Ока залось, что эффективная разработка сложных npoi рамм нуждается в действенных способах контроля правильности использования данных. Контроль должен осу- ществляться как на стадии компиляции, так и при прогоне программ В против- ном случае, как показала практика, резко возрастают трудности создания круп- ных программных проектов. Отчетливое осознание этой проблемы привело к соз- данию Алгола-60, а позже - 11 аскаля, Модулы-2, Си и множест ва других языков про, раммирования, имеющих более и пи менее развитые ст руктуры тил зв данных. Логическим следст вием развития этого направления ста i модульный подход к разработке программ, характеризующийся стремлением «спрятать» данные и процедуры внутри модуля. Начиная с языка Симула-67, в программировании наметился новый под- ход. который по 1учил название объектно-ориен гиоованнсто npoi раммиоования (ООП). Его руководящая идея заключается в стрем тении связать данные с обра- батывающими эти данные процедурами в единое целое - объект. Характерной чертой объектов является инкапсуляция (объединение) данных и алгоритмов их обработки, в результате чего и данные, и процедуры во многом теряют самое гоя тельное значение. Фтктически. объектно-ориентированное npoi раммирование можно рассмат ривать как модульное программирование нового уровня, когда вместо, во многом случайного, механического объединения процедур и данных акцент делает ся на их смысловую связь. Какими мощными средствами располагает объектно-ориентированное программирование на, лядно демонстрирует библиотека Turbo Vision, входящая в комплект пос гавки Турбо П аскаля. В ттой 1 гаве рассматриваются основные идеи ООП и способы их использования. Следует заметить, что преимущества ООП в полной мере проявляются лишь при разработке достаточно сложных программ. Более того, инкапсуляция придает объектам совершенно особое свойство «самостоят ельнос ги», максималь- ной независимости от оста 1ьных частей программы. Прави шно сконструирован-
86 Глава 3. Объектно-ориентирова иное про 'раммированйе. ный объект располагает всеми необходимыми данными и процедурами их обра ботки, чтобы успешно реализовать требуемые от него действия 11опытки исполь- зовать ООП для программирования несложных алгоритмов, связанных, например, с расчетными вычислениями по ютовым формулам, чаще всего вьплядят искус- ственными нагромождениями ненужных языковых конструкций. Такие програм- мы обычно не нуждаются в структуризации, расчленении алгоритма на ряд отно- сительно независимых частей. Их проще и естественнее разрабатывать традици- онными способами Паскаля. При разработке сложных диалоговых программ про- граммист вынужден структурировать npoi рамму, так как только в этом случае он может рассчитывать на успех: «критической массой» неструктурированных про- грамм является объем в 1 000 1200 строк исходного текста - отладка неструктури- рованных программ большего объема обычно сталкивается с чрезмерными труд- ностями. Структурирование программы ведет, фактически, к разработке собст- венной библиот еки программирования - вот в этот момент на помощь и приходят новые средства ООП. 3.1. Основные принципы ООП Объектно-ориентированное программирование основано на «трех китах» - трех важнейших принципах, придающих объектам новые свойства. Этими принципами являются инкапсуляция, наследование и полиморфизм. Инкапсуляция Инкапсуляция есть объединение в единое целое данных и алгоритмов об- работки этих данных. В рамках ООП данные называются полями объекта, а алго- ритмы - объектными методами. Инкапсуляция позволяет в максимальной степени изолировать объект от внешнего окружения. Она существенно повышает надежность разрабатываемых программ, т.к. локализованные в объекте алгоритмы обмениваются с программой сравнительно небольшими объемами данных, причем количество и тип этих дан- ных обычно тщательно контролируются. В результате замена или модификация алгоритмов и данных, инкапсулированных в объект, как правило, не влечет за собой плохо прослеживаемых последствий для программы в целом (в целях по- вышения защищенности программ в ООП почти не используются глобальные переменные). Другим немаловажным следствием инкапсуляции является легкость об- мена объектами, переноса их из одной программы в другую. Можно сказать, что OOII «провоцирует » разработку библиотек объектов. Наследование Наследование есть свойство объектов порожда гь своих потомков. Объект- потомок автоматически наследует от родителя все поля и методы, может допол- нять объекты новыми полями и заменять (перекрыва гь) методы родителя или до- полнять их. Принцип наследования решает проблему модификации свойств объекта и придает ООП в целом исключительную гибкость При работе с объектами про- граммист обычно подбирает объект, наиболее близкий по своим свойствам для решения конкретной задачи, и создает одного или нескольких потомков от него, которые «умеют» делать то, что не реализовано в родителе. Последовательное проведение в жизнь принципа «наследуй и изменяй»
Высокоуровневые методы информатика и программирования 87 хорошо согласуется с поэтапным подходом к разработке крупных программных проектов и во многом стимулирует такой подход. Полиморфизм Полиморфизм - это свойство родственных объектов (т.е. объектов, имею- щих одного общего родителя) решать схожие по смыслу проблемы разными спо- собами. В рамках ОО11 поведенческие свойства объекта определяются набором входящих в него ме годов. Изменяя алгоритм того или иного метода в потомках объекта программист может придавать этим потомкам отсутствующие у родите- ля специфические свойства. Для изменения метода необходимо перекрыть его в потомке, т.е. объявить в потомке одноименный метод и реализовать в нем нуж- ные действия. В результате в объекте-родителе и объекте-потомке будут действо- вать два одноименных метода, имеющих разную алгоритмическую основу и. сле- довательно, придающих объектам разные свойства. Это и называется полимор- физмом объектов. В Турбо Паскале полиморфизм достигается не только описанным выше механизмом наследования и перекрытия методов родителя, но и их виртуализа- цией (см. ниже), позволяющей родительским методам обращаться к методам по- томков. 3.2. Создание объектов В Турбо 11аскале для создания объектов используются три зарезервиро- ванных слова: object, constructor, destructor и три стандартные директивы: private, public и virtual Зарезервированное слово object используется для описания объекта Опи- сание объекта должно помещаться в разделе описания типов: type MyObject = object (Поля объекта} {Методы объекта} end ; Если объект порождается от како1 о-либо родителя, имя родителя указы- вается в круглых скобках сразу за словом object: type MyDescendantObject = object(MyObject) end; Любой объект может иметь сколько угодно потомков, но только одного роди геля, что позволяет создава гь иерархические деревья наследования объектов. Создадим объект-родитель TGraphObject, в рамках которого будут инкап- сулированы поля и методы, обшие для всех остатьных объектов: type TGraphObj = object Private {Поля объекта будут скрыты от пользователя} X.Y: Integer; {Координаты реперной точки} Color: Word; {Цвет фигуры} Public {Методы объекта будут доступны пользователю}
88 Глава 3. Объектно-ориентированное программирование. Constructor Init(aX,aY: Integer; aColor; Word); {Создает экземпляр объекта} Procedure Draw(aColor. Word); Virtual; {Вычерчивает объект заданным цветом aColor] Procedure Show; {Показывает объект - вычерчивает ei о цветом Color) Procedure Hide; {11рячет объект - вычерчивает его цветом фона} Procedure Move! o(dX,d Y: Integer); {Перемещает объект в точку с координатами X+dX и Y+dY} end; {Конев описания объекта TGrapliObj} В дальнейшем предполагается создать объекты потомки от TGraphObj, реализующие все специфические свойства точки, линии, окружности и прямо- угольника. Каждый из этих графических объектов будет характеризоваться поло- жением на экране (поля X и Y) и цветом (поле Color). С помощью метода Draw он будет способен отображать себя на экране, а с помощью свойств «показать себя» (метод Show) и «спрягать себя» (метод Hide) сможет перемещаться по экрану (метод MoveTo). Учит ывая общность свойств графических объектов, объявляем абстрактный объект TGraphObj. который не связан с конкре гной графической фи- гурой. Он объединяет в себе все общие поля и методы реальных фигур и будет служить родителем для других объектов. Директива Private в описании объекта открывает секцию описания скры- тых полей и методов. Перечисленные в этой секции элемент ы объекта «не видны» программисту, если этот объект он получил в рамках библиотечного ТР(/-модуля. Скрываются обычно те поля и методы, к которым программист (в его же интере сах!) не должен иметь непосредственного доступа. В данном примере он не мо- жет произвольно менять координаты реперной точки (X Y). т.к. это не приведет к перемещению объекта. Для изменения полей X и Y предусмотрены входящие в состав объекта методы Init и MoveTo. Скрытые поля и методы доступны в рамках той программной единицы (программы или модуля), где описан соответствую- щий объект. В дальнейшем предполагается, что программа будет использовать модуль GraphObj с описанием объектов. Скрытые поля будут доступны в модуле GraphObj, но недоступны в использующей его основной программе. Разумеется, в рамках реальной задачи создание скрытых элементов объекта вовсе необязатель- но В данном случае они введены в объект TGraphObj лишь д 1я иллюстрации возможностей ООП. Директива public отменяет действие директивы pi ivate, поэтому все сле- дующие за public элементы объекта доступны в любой программной единице. Директивы private и public могут произвольным образом чередоваться в пределах одного объекта. Вариант объявления объекта TGraphObj без использования механизма private...public: type TGraphObj = object X,Y: Integer; Color Word; Constructor Init(aX.aY: Integer: aColor: Word); Procedure Draw(aColor: Word); Virtual, Procedure Show ;
Высокоуровневые методы информатики и пpoi раммирования. 89 Procedure Hide: Procedure MoveTo(dX,oY: Integer); end; Описания полей ничем не отличаются от описания обычных переменных. Полями могут быть любые структуры данных, в том числе и дру1 ие объекты. Ис- пользуемые в примере поля X и Y содержат координату реперной (характерной) точки графического объекта, а поле Color - его цве г. Реперная i очка характерна} - ет текущее положение графической фигуры на экране и, в принципе, может быть любой ее точкой. В данном примере она совпадает с координатами точки в описываемом ниже объекте TPoint. с центром окружности в объекте TCircle, первым концом прямой в объекте TLine и с левым верхним углом прямоугольника в объекте TRect. Для описания методов в OOII используются традиционные для Паскаля процедуры и функции, а также особый вид процедур - конструкторы и деструкто- ры. Конструкторы предназначены для создания конкретного экземпляра объекта, ведь объект - это тип данных, т.е. «шаблон», по которому можно создать сколько угодно рабочих экземпляров данных объектного типа (типа TGraphOhj, напри- мер). Зарезервированное слово constructor, используемое в заголовке конструкто- ра вместо procedure, предписывает компилятору создать особый код пролога с помощью которого настраивается, так называемая, таблица вирту альных методов (см. ниже). Если в объекте нет виртуальных методов, в нем может не быть ни од- ного конструктора, наоборот, если хотя бы один метод описан как виртуальный (с последующим словом Virtual, см. метод Draw), в состав объекта должен входить хотя бы один конструктор, и обращение к конструктору должно предшествовать обращению к любому виртуальному методу. Типичное действие, реализуемое конструктором, состоит в наполнении объектных полей конкретными значениями. Следует заметить, что разные экзем- пляры одного и того же объекта отличаются друг от друга только содержимым объектных полей, в то время как каждый из них использует одни и те же объект- ные методы. В данном примере конструктор Init объекта TGraphObj получает все необходимые для полного определения экземпляра данные через параметры об- ращения аХ, aY и aColor. Процедура Draw предназначена для вычерчивания i рафического объект а. Эта процедура будет реализовываться в потомках объекта TGraphObj по-разному. Например, для визуализации точки следует вызвать процедуру PutPixel, для вы- черчивания линии - процедуру Line и т.д. В обьекте TGraphObj процедура Draw определена как виртуальная («воображаемая»). Абстрактный объект TGraphObj не предназначен для вывода на экран, однако наличие процедуры Draw в этом объекте говори г о том, что любой потомок TGraphObj должен иметь собственный метод Draw, с помощью которого он может показать себя на экране. При трансляции объекта, содержащего виртуальные методы, создается, так называемая, таблица виртуальных методов (’ТВМ), количество элементов ко- торой равно количеству виртуальных методов объекта. В этой таблице будут хра- ниться адреса точек входа в каждый виртуальный метод. В приведенном примере ТВМ объекта TGraphObj хранит единственный элемент - адрес метода Draw. Пер- воначально элемен гы ТВМ не содержат конкретных адресов. Если бы был создан экземпляр объекта TGraphObj с помощью вызова ei о конструктора Init, код про- лога конструктора поместил бы в ТВМ нужный адрес родительского метода
90 Глава 3. Оеън Tt о-сгиевтироза ii ое программирование Di aw. Далее мы со щадим несколько потомков объекта TGraphObj. Каждый из них будет иметь собственный конструктор с помощью которого ТЕК' каждого потомка наст раивается т ак, чтобы ее единственный элемент содержал адрес нуж- ного метода Draw. Такая процедура называется по щним связыванием объекта. Позднее связывание позволяет методам родителя обращаться к виртуальным ме- тодам своих потомков и использовать их д ля реализации специфичных для п >- гомков действий. Наличие в объекте TGraphObj виртуального мет ода Draw позволяет легко реализовать три других метода объекта: чтобы показать объект на экране в методе Show', вызывается Draw с цвет ом aColor, равным значению поля Color, а чтобы спрята гь графический объект, в методе Hide вызывает ся Draw со значением цвета GerBkColor, т.е. с текущим цветом фона. Рассмотрим реали тацию перемещения объекта. Гели пот эмок 1 GraphObj (например. TLine) хочет переместить себя на экране, он обращается к родитель- скому методу MoveTo. В этом методе сначала с помощью 1 Tide объект стирас гея с экрана, а затем с помощью Show показывается в другом месте. Для реализации своих действий и Hide, и Show обращаются к виртуаъному методу Draw. По- скольку вызов Move!о происходит в рамках объекта TLine, используется ТВМ этого объекта и вызывается его метод Draw', вычерчивающий прямую. Если бы перемешалась окружность, IBM содержала бы адрес метода Draw' объекта TCircle, и визуализация-стирание объекта осуществ 1я лась бы с помощью эт ого метода. Чтобы описать все свойства объекта, необходимо раскрыть содержимое объектных методов, т.е. описать сиот вел с гвующие процедуры и функции. Описа- ние методов производится обычным для Паскаля способом в любом месте разде- ла описаний, но после описант я объекта. Например: type TGraphObj - ol ject end; Constructor TGraphObj. Init; begin X := aX; Y := aY, Color := aColor end; Procedure TGraphObj-Draw; begin ; Э га процедура в родительском объекте ничего не делает, поэтому экзем- пляры TGraphObj не способны отображать себя на экране. Чтобы потомки объек- та TGraphObj были способны отображать себя они до. окны перекрывал ь эл от ме- тод} end: Procedure TGraphl )bj.Show. begin Draw(C olor) end: Procedure TGrapht )bi.H ide; begin 1 )raw(GetBkC oloi)
ВЫСОКОУРОВН1 ВЬ,С МЕТОДЫ ИН РОРМАТИКИ И ПРЭГРАММИРОВАНИЯ. 91 end; Procedure TGraphObj.Move Го; begin 1 lide; X X+dX; Y :-Y+dY; Show end; Следует отметить два обстоятельства. Во-первых, при описании методов имя метода дополняется спереди именем объекта, т е. используется составное имя метода. Это необходимо по той простой причине, что в иерархии родственных объектов любой из методов может быть перекрыт в потомках. Составные имена четко указывают принадлежность конкретной процедуры. Во-вторых, в любом объектном методе можно использовать инкапсулированные поля объекта почти так. как если бы они были определены в качестве глобальных переменных. На- пример, в конструкторе TGraph.ini! переменные в левых частях операторов при- сваивания представляют собой объектные поля и не должны заново описываться в процедуре. Более того, описание Constructor TGraphObj. Init; var X,Y: Integer; {Ошибка!} Color: Word; {Ошибка!} begin end, вызовет сообщение о двойном опреде. тении переменных X. Y и Color (в этом и состоит отличие в использовании полей от глобальных переменных: глобальные переменные можно переопределять в процедурах, в то время как объектные поля переопределять нельзя). Следует обратить внимание: абстрактный объект TGiaphObj не предна- значен для вывода на экран, поэтому его метод Draw ничего не делает. Однако методы Hide, Show и MoveTo «знают» формат вызова этого метода и реализуют необходимые действия, обращаясь к реальным методам Draw своих будущих по- томков через соответствующие ТВМ. Это и есть полиморфизм объектов. Создадим простейшего потомка от TGraphObj - объект TPoint, с помощью которого будет визуализирова гься и перемеша гься точка. Все основные действия, необходимые для этого, уже есть в объекте TGraphObj. поэтому в объекте TPoinl перекрывается единственный метод - Draw. type TPoint = object(TGraphObj) Procedure Draw(aColor); Virtual; end; Procedure 1 PointDraw; begin PutPixel(X,Y,Color) {Показываем цветом Color пиксель с координатами X и Y} end; В новом объекте TPoint можно использова гь любые методы объекта- родителя TGraphObj. Например, вызвать метод MoveTo. чтобы переместить изо- бражение точки на новое место. В этом случае родительский метод
92 I -1ABA 3 OLjCKTHO ОРИЕНТИРОВАННОЕ ЛГОГ1 АРМИРОВАНИЕ TGraphObj.Move!о будет обращаться к методу FPoint.Draw, чтобы спрягать и затем показать изображение точки. Такой вызов станет доступен после обраще- ния к конструктору lair объекта TPoint, который нужным образом настроит ТВМ объекта. Если вызвать TPoint.Draw до вызова Init, его ТВМ не будет содержать правильного адреса, и программа «гависнет». Чтобы создать объект -линию, необходимо ввести два новых поля для хранения координат второго конца. Дополнительные поля требуется наполнить конкретными значениями, поэтому нужно перекрыть конструктор родительского объекта: type TLine = object(l Gi aphObj) dX,dY; Integer; {Приращения координат второго конца? Constructor Init(Xl,Yl,X2,Y2: Integer; aColor: Word); Procedure Drawfat olor: Word) Virtual; end;, ( onstructor TLine.Init; {Вызывает унаследованный конструктор TGraphObj для инициализации полей X Y и Color. Затем инициализирует по. [я <1Х и dY} begin {Вызываем унаследованный конструктор} Inherited Init(Xl,Yl,aColor); {Инициируем почя dX и dY} dX Х2-Х1; dY Y2-Y 1 end; Procedure Draw, begin SetColor(Coloi); {Устанавливаем цвет Color} Line(X,Y.X-'-dX.Y+dУ В Вычерчиваем линию ; end; В конструкторе ILine.Init для инициализации полей X. Y и Color, унасле- дованных от родительского объекта, вызывается унаследованный конструктор TGraph.lnit, для чего использует ся зарезервированное слово inherited tani л.- у нас- ледованный): Inherited Init(Xl.Yl,aColor); С таким же успехом можно использовать и составное имя метола: TGraphObj.Init(Xl,Yl,aColor); Для инициализации полей dX и dY вычисляется расстояние в пикселах по горизонтали и вертикали от первого конца прямой до ее второго конца. Это по- зволяет в методе TLine.Draw вычислить координаты второго конца по координа- там первого и смещениям dX и dY. В результате простое изменение координат реперной точки X. Y в родит е тьском ме годе TGraph.MoveTo перемещает всю фи- гуру по экрану Теперь нетрудно реализовать объект TCircle тля созтания и перемещения окружности: type TCircle = ubjectITGraphObj) R: Integer: {Радиус} Constructor InitiaX.aY.aR: Integer:
Высокоуровневые методы информатики и программ и ровакия. 93 Procedure Draw( aColor: Virtual); end ; Constructor TCircle.lnit; begin Inherited Init(aX,aY,aColor); R:= aR end ; aColor: Word) Procedure TCircle Draw; begin SetColorf aColor); {Устанавливаем цвет Color} Circle(X.Y R) {Вычерчиваем окружность} end; В объекте TRect, с помощью которого создается и перемещается прямо- угольник, учитывается го обстоятельство, что для задания прямоугольника требу- ется указать четыре целочисленных параметра т .е столько же, ско тько для зада- ния линии. Поэтому объект ] Rect удобнее породить не от TGraphObj, а от TLine. чтобы использовать его конструктор Init: type TRect = object(TLine) Procedure Draw(aColor: Word); end; Procedure TRect.Draw; begin SetColor( aColor); RectanglefX.Y.XH dX,Y+dY) {Вычерчиваем прямоугольник} end; Чтобы описания графических объектов не мешали созданию основной программы, нужно оформить эти описания в отдельном модуле GraphObj: Unit GraphObj; Interlace {Интерфейсная часть модуля содержит только объявления объектов} type TGraphObj = object end; TPoint = object( rCranhObj) end; TLine = object(TGraphObj) end; TCircle = object(T GraphObj) end; TRect = object( П ine) end; Implementation {Исполняемая часть содержит описания всех объектных методов} Uses Graph;
94 Глава 3. Объектно-с,ригнти₽ованно! прэграммирова im Constructor TGraphObj.Init: end. В интерфейсной части модуля приводятся лишь объявления объектов, по- добно тому как описываются другие типы данных, объявляемые в модуле дос- тупными для внешних пршраммных единиц. Расшифровка объектных методов помещается в исполняемую часть implementation, как если бы это были описания обычных интерфейсных процедур и фу нкций. 11ри описании методов можно опускать повторное описание в за1 оловке парамет ров вызова. Если они все же повторяются, они должны в точности соответствовать ранее объявленным пара- метрам в описании объекта. Например, заюловок конструктора TGraphObj. In it может быть таким Constructor TGraphObj. Init; или таким: Constructor TGraphObj.lnit(aX,aY: Integer; aColor: Word ); 3.3. Использование объектов Идею инкапсуляции полей и алгоритмов можно применить не то 1ько к графическим объектам, но и ко всей npoi рамме в це юм. Ничто не мен ает создат ь обьект-программу и «научить» его трем основным действиям: инициации (Init). выполнению основной работы (Run) и завершению (Done). На этапе инициации ж-ран переводится в графический режим работы, и создаются и отображаются графические объекты (100 экземпляров TPoint и по одному экземпляру TLine. TCircle, TRecf). На этапе Run осуществляется сканирование кшвиатуры и пере- мещение графических объектов. Наконец, на этапе Done жран переводится в тек- стовый режим, и завершается работа всей программы. Размест им объект -npoi рамму TGraphApp в модуле Graph Арр. не обращая внимание на точки, скрывающие содержате. 1ьную част ь модуля - позднее будет представлен его полный т екст: Unit GrapnApp; Interface type TGraphApp = object Procedure Init, Procedure Run; Destructor Done; end: Implementation Procedure TGi aphApp.lnit; end; end. В этом случае основная программа будет преде тьно простой: Program Graph Objects; Uses GraphApp; var Арр: TGraphApp; begin App.lnit;
ВЫСОКОУРСВНЕВЫЕ МЕТОДЫ ИНФОРМАТИКИ И ПРОГРАММИРОВАНИЯ 95 Арр.Run; App.Done end. В ней создается единственный экземпляр Арр объекта-программы TGrahpApp и происходи г обращение к трем его методам. Создание экземпляра объекта ничуть не отличается от создания экземп тя- ра переменной любого другого типа. Просто в разделе описания переменных мы указываем имя переменной и ее тип: var Арр: TGraphApp; Получив это указание, компилятор зарезервирует нужный объем памяти для размещения всех полей объекта TGiaphApp. Чтобы обратиться к тому или иному объект ному методу или полю, используется составное имя, причем первым указывается не имя объектного типа, а имя соответствующей переменной: App.Init; Арр.Run; App.Done; Переменные объектного типа могут быть статическими или динамиче- скими, т.е. располагаться в сегменте данных (статические) или в куче (динамиче- ские). В последнем случае можно использовать такую программу: Program Graph Objects; Uses GraphApp; type PGraphApp = TGraphApp; var App: PGraphApp; begin App := New(PGraphAppJnit) App.Run; App.Done end; Для инициали зации динамической переменной Арр используется вызов функции New. В этом случае первым параметром указывает ся имя типа иниции- руемой переменной, а вторым - осуществляется вызов мегода-конструктора, ко- торый нужен для настройки таблицы виртуальных методов. Такой прием (распре- деление объектов в динамической памяти с одновременной инициацией их ТВМ) характерен для техники ООП. Ниже приводи гея возможный вариант модуля GraphApp для учебной про- граммы: Unit GraphApp; Interface Uses GraphObj: const NPoints= 100; {Количество точек} type {Объект-программа} TGraphApp = object Points: array [L.NPoints] of TPoint; {Массив точек} Line’ TLine; {Линия}
96 Глава 3 Обьектно-ориечтироват ное программирование Rect: fRect; { 11рямоугольник} Circ; (Circle; {Окружность} ActiveObj : Integer; {Активный объект} Procedure Init; Procedure Run; Procedure 1 tone; Procedure ShowAll; Procedure MoveActiveObj (dX.JY: Integer); end; Implementation Uses Graph. CRT. Procedure TGraphApp.Init; {Инициали тирует графический режим работы жрана . Создает и отобра- жает NPoints экземп тяров объекта 1 Point, а также экземпляры объект ов TLine, TCircle и FRect} var D.R.Err.k: Integer; begin {Инициируем i рафику} D := Detect; {Режим автоматического определения типа графического адаптера} InitGraphfl ),R, 'Mptogi') ; {Инициализируем графический режим. Текстовая строка должна задавать 1 тут ь к каталогу с граф1-1 ческими драйверами} Err := GraphResult; {Проверяем успех инициализации i рафики} if ErroO then begin GraphErrorMsg (Err); Halt end; {Создаем точки} for k : = 1 to NPoints do Points [k] .Init (Random(GetMaxX).Random(GetMaxY) Random(15 )+l); {Создаем другие объек гы} Line. Init (GetMaxX div 3, GetMaxY div 3,2*GetMaxX div 3, 2*GetMaxY div 3.LightRed); Circ. Init (GetMaxX div 2, GetMaxY div 2 GetMaxY div 5, White); Rect.Init(2*GetMaxX div 5,2*GetMaxY div 5 , 3*GctMaxX div 5, 3*GetMaxY div 5, Yellow); ShowAll; {Показываем все графические объекты} ActiveObj := 1 {Первым перемещаем прямоугольник} end ; { TGraphApp .Init} {-------} Procedure TGraphApp .Run; {Выбирает объект с помощью Tab и перемещает его по экран) } var Stop: Boolean; {При шак нажатия Esc} const D = 5; {Шаг смешения фигур} begin Stop - False; {Цикл опроса клавиатуры} repeal case ReadKey of {Чи гаем код нажатой клавиши}
BblCOKOVPOBHtBbiE МЕТОДЫ ИН'ЮГМАТйкИ И ПРОГРАММИРОВАНИЯ. 97 # 27: Stop := 7 rue; {Нажата Esc} # 9:begin {Нажата Tab} inc( ActiveObj); if ActiveObj>3 then ActiveObj := 3 end; # 0: case ReadKey of #71 :MoveActiveObj(-D,-D); {Влево и вверх} #72:MoveActiveObj( 0,-D); {Вверх} #73:MoveActiveObj( D,-D); {Вправо и вверх} #75:MoveActiveObj(-D, 0); {Влево} #77:MoveActiveObj( D, 0); {Вправо} #79:MoveActiveObj(-D, D); {Влево и вниз} #80 MoveActiveObj( 0, D); {Вниз} #81 :MoveActiveObj( D. D); {Вправо и вниз} end end; ShowAll; Until Stop end, {TGraphApp. Run} {--------} Destructor TGraphApp . Done ; } Закрывает графический режим} begin CloseGraph end. {TGraphApp. Done} Procedure TGraphApp . ShowAll; {Показывает все графические объекты} \ai k: Integer; begin for k := 1 to NPoints do Points [k]. Show. Line. Show; Rect. Show ; i Circ.Show end, {--------} Procedure TGraph App. Move ActiveObj; {Перемещает активный графический объект} begin case ActiveObj of 1. Rect.MoveTo(dX,dY); 2: Circ.MoveTo(dX,dY); 3: Line.MoveTo(dX,dY) end end; end В реали шции объекта TGraphApp используется деструктор Done. Следует иметь в виду, что в отличие от конструктора, осуществляющего настройку 1ВМ, деструктор не связан с какими-то специфическими действиями: для компилятора
98 Глава 3. Объектно-ориентитованног программирование. слова destructor и procedure - синонимы. Введение в ООП деструкторов носит, в основном, стилистическую направленность - просто процедуру, разрушающую экземпляр объекта, принято называть деструктором. В реальной практике ООП с деструкторами обычно связывают процедуры, которые не только прекращают работу с объектом, но и освобождают выделенную для него динамическую па- мять. И хотя в примере деструктор Done не освобождает кучу, придерживаясь общепринятой стилистики рассмотрим последнее зарезервированное слово тех- нологии ООП. В заключении следует сказать, что формалистика ООП в рамках реализа- ции этой технологии в Турбо Паскале предельно проста и лаконична. Введение лишь шести зарезервированных слов, из которых дейс гвительно необходимыми являются три (object, constructor и virtual), весьма небольшая плата за мощный инстру мент создания современно! о программного обеспечения. 3.4. «Нетрадиционные» возможности Турбо Паскаля 3 4.1. Внешние процедуры (функции) С помощью внешних процедур (функций) можно осуществить вызов из программы процедур или функций, написанных на языке Ассемблера. Ассемблер обеспечивает компиляцию программ, написанных на машинно-ориентированном языке программирования низкого уровня. В Турбо Паскале есть собственный встроенный Ассемблер. В этом разделе речь идет о программах, написанных и откомпилированных с помощью внешнего Ассемблера, такого как. например. Ас- семблер фирмы Microsoft или Turbo Assembler фирмы Borland. Машинно-ориентированный язык Ассемблера предоставляет квалифици- рованному программисту' ooi атейшие возможности использования всех особен- ностей архитектуры ПК. Ассемблерные программы выполняются значительно быстрее и занимают меньший объем памяти, чем программы, написанные на Тур- бо 11аскале. Однако низкий уровень языка Ассемблера существенно снижает про- изводительность труда программиста и резко усложняет отладку программ. Как правило, на языке Ассемблера пишутся сравнительно небольшие фрагменты про- грамм, в которых используются недоступные из Турбо Паскаля особенности ар- хитектуры ПК. Внешняя процедура (функция) в программе, написанной на Турбо Паска- ле, объявляется своим заголовком- за которым следует стандартная директива EXTERNAL например: Function LoCase (ch : char):char; external; Procedure Swapping (var a.b, N:word), external; Как видно из этих примеров, тело внешней процедуры (фу нкции) отсут- ствует - его заменяет директива EXTERNAL Для подключения Ассемблерной программы необходимо предварительно ее от компилировать и получить объект- ный файл с расширением OBJ, содержащий перемещаемый код Ассемблерной программы. Непосредственно перед описанием внешней процедуры (функции) в тело основной программы вставляется директива компилятора {$Е<имя файла>}, где <имя фата> - имя OBJ -файла. Диск и каталог, в котором следует искать этот файл, если он не обнаружен в текущем каталоге, указываются опцией OPTIONS/D1RECTORIES/OBJECT DIRECTORIES (см.прил ’1). Перед передачей управления внешней процедуре (функции) программа помещает параметры обращения в программный стек в гом порядке, как они пе-
Высокоуровневые методы информатики и программирования. 99 речислены в заголовке процедуры (функции). Ассемблерная процедура должна сохранить регистры BP, SP, SS и DS центрального процессора в самом начале своей работы и восстановить содержимое этих регистров перед возвратом управ- ления в программу. Остальные регистры можно не сохранять и, соответственно, не восстанавливать Параметры могут передаваться по ссылке или по значению. Если пара- метр передается по ссылке, в стек помещается указатель, содержащий абсо гют- ный адрес параметра, если по значению - в стек помещается сам параметр, точнее - его значение. Все параметры-переменные, т е. параметры, объявленные в заго- ловке с предшествующим словом VAR, всегда передают ся по ссылке. Параметры- значения могут передавят ься по ссылке или по значению в зависимост и от длины внутреннего представления соответствующего параметра. В общем случае ис- пользуется следующее правило- если длина внутреннего представления парамет- ра-значения составляет 1, 2 или 4 байта, он передается своим значением, т.е. его значение помещается в стек. Точно так же через стек передаются и все вещест- венные данные длиной в 4, 6, 8 и 10 байт (в версии 4.0 эти данные передаются через стек сопроцессора 8087/80287, начиная с версии 5.0 -через стек центрально- го процессора 8086/80486) Во всех остальных случаях, если длина внутреннего представления больше 4 байт, соответствующий параметр передается по ссылке. Ассемблерные функции, в зависимости от длины внутреннего представ- ления результата, должны возвращать его через регистры центрального процессо- ра или сопроцессора по следующим правилам: • длиной в 1 байт - в регистре AL; • длиной в 2 байта - в регистре АХ: • длиной в 4 бай га - в регистрах DX:AX (старшее слово в DX); • тип REAL (6 байт) - в регистрах DX:BX:AX; • типы SINGLE, DOUBLE, EXTENDED и COMP - через стек сопроцес- сора 8087/80486, • указатели - в регистрах DX:AX (сегмент в DX); • строки возвращаются по ссылке: адрес начала строки помещается в DX:AX (сегмент в DX). Все Ассемблерные процедуры должны размещаться в сегменте с именем CODE или CSEG, или с именем, оканчивающимся на TEXT; инициализирован- ные локальные Переменные помещаются в сегмент с именем CONST или с име- нем, оканчивающимся на DATA Все друт ие локальные переменные необходимо размещать в cei менте с именем DATA или DSEG, или с именем, оканчивающим- ся на _BSS. Любые другие объявления сегментов игнорируются. Все имена, объ- явленные в интерфейсной части модулей программы, написанной на Турбо Пас- кале, становятся доступны Ассемблерной процедуре (функции) после их объяв- ления директивой EXTRN. Точно так же все имена Ассемблерных процедур и функций, которые должны быть доступны программе на Турбо Паскале, следует объявлять директивой PUBLIC. 3.4.2. Использование встроенных машиных кодов В Турбо Паскале имеется возможность непосредственного включения в программу небольших фрагментов, написанных в машинных кодах Для этого используется стандартная директива INLINE, за которой в круглых скобках сле- дует один или несколько элементов машинного кода, разделяемых косыми черта- ми. Элемент кода, в свою очередь, строится из одного или более элементов дан-
100 Глава 3. Объектно-ориентированное программирование. ных, разделенных знаками «4 » или «-». В качестве элемента данных может использоваться целая константа, идентификатор (переменной, константы или функции) или ссылка на счетчик ад- реса («*»). Каждый элемент данных вызывает генерацию 1 или 2 байт кода про- граммы. Значение этого кода получается сложением или вычитанием элементов данных в соответствии с разделяющим их знаком. Значением идентификатора переменной, константы, функции служит адрес соответствующего объекта, зна- чением ссылки на счетчик адреса является тот адрес, по которому будет разме- щаться следующий байт кода. Элемент кода будет генерировать 1 байт кода, если этот элемент состоит только из целых констант и значение результата не превышает мощности одного байта, т.е. находится в диапаюне от 0 до 255. Если значение превышает 255 или элемент кода содержит ссылку на счетчик адреса, генерируются 2 байта. Знаки «<» и «>» могут использоваться для отмены автоматического выбора размера ге- нерируемого кода. Если элемент кода начинается со знака «<», в код заносится только 1 байт (с младшей значимостью), даже если само значение занимает 2 бай- та. Наоборот, если элемент начинается со знака «»>, в код заносятся 2 байта (старший байт может оказаться нулевым). Значением идентификатора является смещение соответствующего объек- та. Если переменная - глобальная, смещение задается относительно сегмента дан- ных, хранящееся в регистре DS, если это локальная переменная относительно сегмента стека регистр SP. Базовым сегментом типизированной коне ганты явля- ется сегмент кода регистр CS. В следующем примере приводятся две короткие процедуры, с помощью которых можно ввести или вывеет и данные через любой порт ПК. Function InPort(Port; Word): Word; var pp: Word; cc:Char; egin pp:=port; inline ( $8b/$96/pp/ { mov DX,pp[bp] } SEC/ { IN AX,DX } $88/S86/cc); {mov cc[bp],AX} InPoi1:=ord(cc); end; Procedure OuiPort(Port,Br Word); var pp: Word; cc:Char; begin pp^port; cc:=chr(Bt); inline ( $8a/$86/cc/ { mov AX.cc [bp | } $8b/$96'pp/ { mov DX,pp[bp] } SEE) { OUT DX,AX } end;
Высокоуровневые методы информатики и программирования. 101 Операторы INLINE могут произвольным образом смешиваться с другими операторами Турбо Паскаля, однако при выходе из процедуры (функции) содер- жимое регистров BP, SP, DS и SS должно быть таким же, как и при входе в нее. С помощью директивы INLINE можно также за;авать последователь- ность машинных кодов, которую необходимо несколько раз вс гавгп ь в програм- му. Для этого используется описание INLINE-процеду ры, например: Procedure Disable Interrupts; inline ($FA), {CL1} INLINE-процедура имеет обычный для Турбо Паскаля заголовок, в то время как тело процедуры пишется целиком с помощью оператора INLINE. Вся- кий раз, когда в программе будет встречаться оператор вызова INLINE- процеду ры, компилятор Турбо Паскаля будет вставлять на это место не код вызо- ва процедуры, а нужные машинные коды. Например, вместо вызова процедуры в операторе Disablelnterrupt; компилятор вставит команду запрета прерываний CLI. Таким образом, INLINE-процедуры служат своеобразным средством расширения возможностей стандартного компилятора Турбо Паскаля и подобны макросам Ассемблера. Ис- пользование JNLlNE-процедур увеличивает скорость исполнения программы, так как не осуществляется генерация (и исполнение) команд передачи управления в процедуру. По этой причине в INHNE-процедурах не следует использовать ко- манды выхода из подпрограммы. INLINE-процедура может иметь параметры, од- нако на них нельзя ссылаться в INLINE-директивах (на другие символы Турбо Паскаля ссьлаться можно). В следующем примере перемножаются два числа типа INTEGER, результат имее с тип LONG IN Г: FUNCTION LongMul(X.YImeger) : Longint; inline ( $5 А/ {POP AX; получить в AX число X } $58/ { POP DX; получить в DX число Y } SF7/SEA); { IMUL DX; DX:AX ;= X * Y } Следует отметим, что в силу упоминавшегося сходства с макросами Ас- семблера, имена INLlNE-подпрограмм не могут использоваться в качестве аргу- ментов в операторах @ или служить параметрами функций ADDR. OFS и SEG. 3.4.3. Обращения к функциям операционной системы Турбо Паскаль предоставляет программисту' практически неограниченные возможности использования любых функций стандартной операционной системы MS-DOS. Язык Паскаль весьма прост и лаконичен, что, по мнению многих спе- циалистов, и послужило одной из причин его широкого распространения. Биб- лиотечные же процедуры и функции, в своей значительной части, являются, по существу, своеобразным интерфейсом между языковыми средствами Турбо Пас- каля и функциями операционной системы. Разумеется, можно только приветство- вать усилия разработчиков Турбо Паска гя по созданию мощных библиотек TURBO.TPL и GRAPH.TPU. однако ясно, что таким способом невозможно запро- граммироваз ь все допустимые обращения к средствам ДОС. Вот почему в Турбо 11асказь включены две процедуры, с помощью которых программист может сам сформировать вызов той или иной функции дисковой операционной системы (ДОС). Следует учесть, что единственным механизмом обращения к функциям
102 Глава 3. Объектно-ориентированное программирозание. ДОС является инициация программного прерывания. Прерывание - это особое состояние вычислительного процесса. В момент прерывания нарушается нор- мальный порядок выполнения команд программы, и управление передается спе- циальной процедуре, которая входит в состав ДОС и называется процедурой об- работки прерывания Каждое прерывание характеризуется в рамках ДОС поряд- ковым номером и связано со своей процедурой обработки. В архитектуре цен- трального процессора ПК предусмотрены прерывания двух т ипов - аппара гные и программные. Аппаратные прерывания создаются схемами контроля и управле- ния Г1К и сигнализируют операционной системе о переходе какого-либо устрой- ства в новое состояние или о возникновении неисправности. Программные пре- рывания инициируются при выполнении одной из двух специальных команд мик- ропроцессора (INT или INTO) и служат для обращения к среде гвам ДОС. Описываемые ниже процедуры входят в состав библиотечного модуля DOS.TPL' и становятся доступными после объявления USES DOS. При возникно- вении про!раммного прерывания в большинстве случаев необходимо передать процедуре обработки прерывания некоторые параметры, в которых конкретизи- руется запрос нужной функции. Эти параметры, а также выходная информация (результат обработки прерывания) передаются оз программы к процедуре и об ратно через регистры центра зьного процессора. В сосз аве модуля DOS.TPU для этих целей определен специальный тип: । type Resisters = record case integei of 0 : (AX, BX, CX, BP. SI. DI. DS, ES, Flags : word); 1 : (AL, AH, BL, BI I. CL, CH. DL. DH byte) end ; Этот тип имитирует pei истры центрального процессора и дает возмож- ность обращаться к ним как к 16-би гным или 8-битным регистрам. Процедура INTR. С помощью этой процедуры инициируется программное прерывание с требуемым номером. Обращение: IN 1 R (<Й>,<регистры>) Здесь <N> - выражение типа BYTE; номер прерывания; <регистры> - переменная типа REGISTERS; в этой переменной процедуре обработки прерывания передается содержимое регистров, и в ней же возвращает- ся выходная информация Например, прерывание с номером 18 ($ 12) возвращает в регистре АХ объ- ем оперативной памяти ПК. Короткая программа, представленная в примере 2, выведет на экран сообщение об этом объеме. Пример 2. Uses DOS; var г: registers; begin Intr ($12. r); writein ('Объем памяти = ',r.AX,' Кбай г') end. Процедура MSDOS. Инициирует прерывание с номером 33 ($21). Формат обращения: MSDOS (<регисз ры>)
Высокоуровневые методы ина тематики и г рограммирования. 103 Программное прерывание с номером 33 ($21) стоит особняком, так как оно дает доступ к большому количеству функций Д' )С (эт им прерыванием вызы- вается 85 функций). Рассматриваемая процедура по ihoct ью эквивалентна вызову процедуры INTR с номером прерывания 33. Например, следующая программа (пример 3) выведет на экран версию операционной сист емы: 11ример 3. I Jses DOS; var г: registers; begin r.AH $30; MjDos(r); WriteLn('Bepcjia операционной системы:i .AL, '' r.AH) end. 3.4.4. Поддержка процедур обработки прерываний При написании процедур обработки прерываний существенными являют- ся два обстоятельс гва. Во-первых, процедура обработки прерывания не должна искажать работу трерванной npoi раммы. Дли эт оги необходимо сначала сохра- нить регистры цен гратьного процессора, а перед выходом из процедуры - восета - новить их. Во-вторых, процедура должна строит ься по принципу реентерабельно- сти (повторной входимосги): ее работа может быть прервана в любой момент другими прерываниями и ДОС може г обрат н вся к соотвегству ющей функции до завершения обработ ки предыдущег о прерывания. Турбо Паскаль предоставляет программисту возможность написания про- цедур обработки прерывания на языке высокого уровня, хотя обычно такие про- цедуры пишутся на языке Ассемблера 11роиедура обработки прерывания, написанная на Турбо Паскале, должна начинаться ст а.щартной директивой INTERRUPT (прерывание), например Proceduie IntProc (Flags, CS, IP. AX, DX. CX, DX. SI, ] )I, DS, ES. BP : word); inerrupt; begin end ; Формальные параметры в заголовке процедуры должны перечислят ься в указанном порядке - через эти параметры все регистры прерванной программы становятся доступны процеду ре обработки прерывания. Количес гво перечисляе- мых в заголовке процедуры паоаметров-рег истров может быть любым, но не больше 12. Если в списке опущен какой-либо параметр, должны быть опушены также и все предшес гвующие ему параметры. Например, описание Procedure lntPioc(Sl 1 )Р, ES: word): inten upt: будет неверным (опущены параметры DS и ВР). правильное описание: Procedure IntPioc(Sl. 1 )Р, DS, 1 S. BP: woi d); interrupt. Компилятор не контролирует порядок перечисления параме гров в за, о- ловке процедуры обработки прерывания. Директива 1NT] RRUPT вызывает генерацию специа шных машинных ко- дов, обеспечивающих заталкивание регистров в стек при входе в процедуру и из- влечение их из стека перед выходом из нее. При входе в процедуру.
104 Глава 3. Объектно-ориентированное программирование. push ax push bx push ex push dx push si push di push ds push es push bp mov bp, si sub sp, LocalSize mov ax, SEG DATA mov ds, ax При выходе из процедуры: mov sp, bp pop bp pop es pop ds pop di pop si pop dx pop ex pop bx pop ax irep В самой процедуре обработки прерывания не рекомендуется обращаться к другим функциям ДОС, так как некоторые из них, в том числе все функции вво- да-вывода. нерентерабельны. Для связи с любыми процедурами прерываний, а, следовательно, и с про- цедурами, написанными программистом, используются векторы прерываний - четырехбайтные абсолютные адреса точек входа в эти процедуры. Векторы пре- рываний располагаются в младших адресах оперативной памяти, начиная с ну ле- вого адреса: прерывание номер 0 - по адресу 0, номер 1 - по адресу' 1*4 = 4, номер N - по адресу N * 4. С помощью следующих двух процедур программист может прочитать содержимое любого вектора или установить его новое значение. Процеду pa GET1NTVEC Возвращает вектор прерывания с указанным номером. Обращение: GETLN1VEC (<,<вектор>) Здесь <D> - выражение типа BYTE; номер прерывания; <вектор> - переменная типа POINTER: адрес точки входа в процедуру об- работки прерывания. Представленная в примере 4 программа выводит на экран содержимое всех ненулевых векторов прерываний. Пример 4. Uses DOS; var i : byte; p : pointer; begin for i := 0 to 255 do
Высокоуровневые методы информатики и программирования 105 begin GetlntVec (i, р); if (Seg (p) о 0) or (Ofs (рл) о 0) then WriteLn (’ N-, i:3,' Seg-1, Seg i p):5, ' Ofs - , Ofs (p) :5) end end. Процедура SETINTVEC Устанавливает новое значение вектора прерывания. Формат обращения: SETIN1 VEC (<,<адрес>) Здесь <D> - выражение типа BYTE; номер прерывания; <адрес> - выражение типа POINTER; адрес точки входа в процедуру об- работки прерывания. При нормальном завершении программы она выгружается из памяти, что делает невозможным разработку резиден гных в памяти процедур обработки пре- рываний. Можно прекратить работу программы и оставить ее резидентной в па- мяти, если воспользоваться процедурой KEEP. Процедура KEEP Завершает работу программы и оставляет ее резидентной в памяти. Об- ращение: KEEP ( <код>) Здесь <код> - выражение т ипа WORD - код завершения программы Код завершения представляет собой, фактически единственный механизм передачи сообщений от запущенной программы к про1рамме, которая ее запустила. Он мо- жет быть проанализирован в вызывающей программе с помощью функции DOSEXITCODE. Функция DOSEXITCODE Возвращает значение типа WORD - код завершения подчиненной про- граммы Обращение: DOSEXITCODE 3.4.5. Запуск внешних программ Из программы, написанной на Турбо Паскале, можно запустить любую другую готовую к работе программу. Для этого используется процедура ЕХЕС из библиотечного модуля DOS Фермат обращения к процедуре: ЕХЕС (<имя>,<параметры>) Здесь <имя> - выражение типа STRING; имя файла с вызываемой про- граммой; <параметры> - выражение типа STRING; параметры вызова. Имени запускаемой программы может предшествовать путь к файлу. Па- раметры передаются запускаемой программе в виде текстовой строки и могут быть проанализированы ею с помощью двух следующих функций. Функция PARAMCOUNT Возвращает общее количество параметров вызова программы (значение типа WORD). Обращение: PARAMCOUNT Параметры вызова обычно следуют в командной строке ДОС сразу за именем вызываемой программы и отделяются ол этого имени и друг от друга пробелами,например: C:\TP\TURBO MYPROG.PAS
106 Глава 3. Объектно-ориентированное программирование. C:\SIAM A:\SYbTEMl.SIA Здесь MYPROG.PAS и A:\SYSTEM1.SIA - параметры, передаваемые про- граммам TURBO и SIAM. При вызове npoi раммы непосредственно из среды Турбо Паскаля ей можно передать параметры с помощью опции OPTIONS/PARAMETERS (см. прил.1). Функция PARAMSTR Возвращает значение типа STRING, соответствующее нужному парамет- ру вызова. Формат обращения: PARAMSTR (<D>) Здесь <D> - выражение типа WORD; порядковый номер параметра. Программе всегда передается параметр, соответствующий N = 0. В этом параметре ДОС сообщает полное имя запущенной программы с указанием диска и каталога, откуда она была загружена. Использование процедуры ЕХЕС имеет ряд особенностей. 11режде всего необходимо отметить, что сама вызывающая программа остается резидентной в памяти, поэтому она не должна занимать всю оперативную память. Объем выде- ляемой программе памяти регулируется опцией OPTIONS/M EMORY SIZES (см. прил.1). По умолчанию параметры LOW Е1ЕАР LIMIT и HIGH HEAP LIMIT этой опции таковы (соответственно 0 и 655360 байт), что вызывающая программа, на- писанная на Турбо Паскале, занимает весь доступный объем памят и, и вы тыкае- мая программа не будет загружена. Полезно включить в текст вызывающей про - граммы директиву компилят ора, в которой изменяются принятые по умолчанию размеры памяти. Например, так: {$М 2048, 0, 0) Такая директива ограничивает используемую программой область стека величиной 2 Кбайта и исключает возможность использования в ней динамиче- ской памяти. Разумеется, можно установить и другие значения параметров в этой директиве. Специфические особенности исполнения программ Турбо Паскаля тре- буют изменения стандартных значений некоторых векторов прерываний. К ним относятся векторы со следующими шестнадцатеричными номерами: $00. $02. $18, $23. $24, $34, $35. $36. $37. $38, $39, $ЗА, $ЗВ, $ЗС, $3D. $ЗЕ. S3F, $75. Начальные значения этих векторов сохраняются в восемнадцати перемен- ных с именами SA VEINTXX из библиотечного модуля SYSTEM, где XX - шест- надцатеричный номер прерывания 1 Тоэтому непосредст венно перед запуском внешней программы и сразу после возврат а из нее. рекомендуется вызывать биб- лиотечную процедуру без параметров SWAPVECTORS, которая обменивает со держимое векторов прерывания и перечисленных переменных Программа из примера 5 читает с клавиатуры любую команду ДОС, затем вызывает командный процессор COMMAND. СОМ операционной системы и пе- редает ему эту команду. Внимание: для указания файла COMMAND.COM и пути к нему исполь- зуется обращение к библиотечной функции GETENV, с помощью которой можно получить параметры настройки операционной системы В част ноет и, параметр COMSPEC определяет спецификацию файла, содержащего командный процессор. Пример 5. {$М 1024.0.0}
ВлСОКиУ РОВН1-ВЫР МгТОДы И <ФОР> Д1ИКИ I. ПРСГРМ' ПИРОВАНИЯ. 107 Uses Di )S; var st: sti ing [79]; begin write ('Введите коман ciy ДОС:'); readin (st); if st о " then begin st := 7C ’+st; SwapVectors; Exec (GetEnv ('COMSPEC'j si); SwapVectors end end. Функция ENVCOUNT Возвращает значение типа INTI iGER в котором содержи гея общее коли- чество уст ановленных в ДОС параметров. Обращение: ENVCOUNT Функция ENVSTR Во гвращает значение типа STRING, содержащее имя и значение нужного параметра настройки операционной системы. Формат обращения: ENVSTR (<D>) Здесь <D > - выражение типа IN I EGER; номер параметра. Эта функция возвращает ст poKj' т ипа NAME-VALUE, где NAMI - имя, а VALUE - значение соответствующего параметра нас тройки. Функция GETENV Возвращает значение типа STRING, в котором содержится параметр на- стройки ДОС. Формат обращения: GETENV (<имя>) Здесь <имя> - выражение типа STRING: имя параметра. Эта функция имеет параметр обращения NAME, а возвращает значение VALUE (см. функцию EN\ S I’R). 3.4.6. Оверлей Известно, что максимальный размер модуля не может превышать 64 Кбайта, однако количество модулей не ограничено, что дает возможность разра- батывать весьма крупные программы, занимающие, например, всю доступную оперативную память ПК ^прибли штсльно 580 Кбайт). Тем не менее, в некоторых случаях и этот объем может оказаться недостаточным. Турбо Паскаль пр? юстав- ляет в распоряжение программно га простой и достаточно эффективный механизм оверлея, с помощью которого можно создават ь npoi раммы практ ически неогра- ниченной длины (следует оговориться, что речь идет только о длине кода про- граммы; два важных размера - длина сегмента данных и размер программного стека - в Турбо I [аскале не могут превышать 64 Кбайта независимо с г структуры прог раммы). Оверлей - эго такой способ исполь ювания оперативной памяти, при кото- ром в один и тот же j час ток памяти, на гываемый оверлейным буфером, попере- менно. по мере надобности, загружаются различные оверлейные (перекрываю- щиеся) модули. При этом все оверлейные мо, ;ули в готовом г: работе виде хранят- ся на диске, а в оперативной г гамят и в каждый момен г находи гея лишь один ак-
108 Глава 3. Объектно ориентированное программировав ие тивный модуль и. возможно, небольшое число неактивных Пусть, например, программа состоит из главной части MAIN и двух мо- дулей А к В, a LM, LA и LB - соответственно длина главной части и обоих моду- лей, причем LA > LB. Тогда неоверлейная программа займет в памяти LM + LA + LB байт, в то время как оверлейная программа - лишь LM + L А байт. При исполнении оверлейной программы в память первоначально загру- жается главная часть и один из модулей, например, модуль А. Если в процессе исполнения программы встретится обращение к модулю В, программа приоста- новит свою работу, с диска в оверлейный буфер будет загружен модуль В (модуль А при этом частично уничтожается), после чего программа продолжит свою рабо- ту. Если в дальнейшем встретится обращение к А, точно таким же обра юм будет загружен модуль А. причем загрузка нужных модулей в оверлейный буфер осу- ществляется автоматически, и программисту не нужно об этом заботиться Опи- санный механизм выявляет главное преимущество оверлейной структуры: объем оперативной памяти, занимаемой оверлейной программой, определяется длиной ее главной части и наибольшего из перекрывающихся модулей, в то время как при неоверлейной структуре в этот объем входит суммарная длина всех модулей. Чем больше в программе оверлейных модулей и чем меньше длина наибольшего из них, тем больший выигрыш в памяти дает оверлейная структура. Однако со- вершенно очевиден и главный недостаток таких структур: на каждую загрузку оверлейного модуля с диска в оверлейный буфер требуется дополнительное вре- мя. поэтому оверлейная программа будет исполняться с меньшей скоростью. Работа оверлейных програ-мм обеспечивается с помощью процедур и функций библиотечного модуля OVERI .AY, входящего в библиотечный файл TURBO.TPL. При создании оверлейных программ нужно руководствоваться следую- щей последовательностью действий: • Выделить главную часть программы и разбить оставшуюся часть на несколько модулей. При этом никаких дополнительных ограничений на модули не накладывается за одним исключением: в оверлейных модулях нельзя исполь- зовать процедуры обработки прерываний. Желательно продумат ь состав модулей таким образом, чтобы по возможности минимизировать количество их перезагру- зок в оверлейный буфер в процессе исполнения программы. • В главной части программы указать с помощью директив компилято- ра вида {SO <имя>} те модули, которые будут оверлейными, например: Program Main. Uses CRT. DOS.Graph. Overlay, UnitA, UnitB; {SO DOS} {SO UnitA} {SO UniiB} Следует подчеркнуть, что из всех стандартных библиотечных модулей только один модуль DOS может быть оверлейным, остальные модули (CRT, Graph. Printer и т.д.) не могут объявля гься оверлейными. • Предусмотреть перед первым, по логике работы программы, обраще- нием к оверлейному модулю вызов процедуры инициализации оверлея OVR INIT. Здесь же, если это необходимо, следует установить размер оверлейного буфера и указать возможность использования расширенной памяти (см ниже). • В начале главной программы и каждого оверлейного модуля необхо- димо поместить директивы компилятора {SO+} и {SF+} или установить опции
Высокоуровневые методы информатики и программирования. 109 OPTIONS /COMPIL E/FORCE FAR CALLS и OPTIONS/ COMPILE/ OVERLAYS ALLOWED в активное состояние, после чего откомпилироват е программу на диск. Программа 1 отова к работе. Таким образом, все процедуры и функции в оверлейной программе долж- ны использовать дальнюю модель вызова - это обязательное условие. Необходи- мо отметить, что попытка компиляции оверлейного модуля, в начале которого отсутствует директива ($О+) предполагает, что опция среды OPTIONS/COMPILE/OVERL AY ALLOWED неактивна и будет обнаружена ком- пилятором, в то время как! неправильная (ближняя) модель вызова оверлейных подпрограмм компилятором не контролируется, и может привести к непредска- зуемым результатам при исполнении программы. Далее инициация оверлея (осуществляется вызовом процедуры OVRJNIT, см. ниже) должна происходить до вы юва любого из оверлейных модулей. Это требование кажется тривиальным, однако множество проблем в оверлейных про- граммах обычно связано именно с ним. Дело в том, что обращение к оверлейному модулю может происходить еще до начала работы основной программы: любой модуль (в том числе и оверлейный) может иметь инициирующую часть, которая исполняется перед началом работы основной программы. В связи с этим, реко- мендуются придерживаться следующего простого правила: никогда не использу- ется оператор BEGIN в конце модуля, если нет нужды в инициирующих действи- ях; пустая инициирующая часть содержит пустой оператор, которому будет пере- дано управление на этапе инициации. Таким образом, пустая инициирующая часть оверлейного модуля очень часто может вызывать сообщение об ошибке пе- риода исполнения с кодом 208 (не установлена система управления оверлеем). Как же быть, если в оверлейном модуле все-таки нужна инициирующая часть? В этом случае можно рекомендовать следующий прием. Следует создать лишний модуль, в котором будут пустыми все части, кроме инициирующей. В этой части разместить команды инициации оверлея. Новый модуль не должен быть оверлей- ным, и его имя должно стоять в предложении USES основной программы перед именем любого оверлейного модуля. После компиляции такой программы ини- циация оверлея будет осуществля гься перед выполнением любой другой иниции- рующей части и проблема будет решена. Процедура OVRIN1T Инициализирует оверлейный файл. Обращение: OVR1NIT (<имя>) Здесь <имя> - выражение типа STRING; имя файла с оверлейной частью программы. При компиляции оверлейной программы создается специальный файл с именем, совпадающим с именем главной программы, и расширением .OVR. В этот файл компилятор помещает все оверлейные модули, из не1 о же эт и модули загружаются в оверлейный буфер в процессе исполнения программы. Файл с оверлейной частью программы должен размещаться в том же каталоге, чго и файл с главной частью (с расширением .EXE). Имя оверлейного файла необходи • мо дополнять расширением .OVR Обычно размер оверлейного буфера определяется автоматически таким образом, чтобы в нем мог разместиться самый крупный из всех оверлейных мо- дулей. Программист может увеличить размер буфера. Тогда при загрузке в буфер очередного модуля программа проверит, достаточно ли в буфере свободного мес- та и, если достаточно, загрузит новый модуль сразу за старым, который, таким
110 Глава 3. Объектно-ориен’ированное программирование. образом, не будет уничтожен. Такой механизм способствует минимизации потерь времени на перезагрузку модулей. Если установлен очень большой размер буфе- ра, то в нем, возможно, смогут разместиться все оверлейные модули, однако в этом случае оверлейная структура становт ся просто нею жной. Процедура OVRSETBUF Устанавливает размер оверлейного буфера. Формат обращения: OVRSETBUF (<длина>) Здесь <длина> - выражение типа LONG1NT задает новую длин) буфера в байтах не больше той, которую сама система устанавливает автоматически. Рас- ширение буфера идет за счет соответствующего уменьшения доступной динами- ческой памяти, поэтому к моменту- вызова этой процедуры куча должна бьп ь пус- той. Функция OVRGETBUF Возвращает значение типа LONGINT, содержащее текущий размер овер- лейного буфера. Обращение: OVRGETBUF Процедура OVR1NITEMS Обеспечивает использование расширенной памяти. Если ПК относится к классу компьютеров типа IBM PC/AT, и в нем имеется так называемая EMS- памя гь (Expanded Memory Specification - расширенная! память, удовлетворяющая стандарту фирм Lotus/Intel/Microsoff), тогда можно использовать эту памя гь для размещения в ней оверлейного файла .OVR. Поскольку время доступа к расши- ренной памяти значительно меньше времени чтения с диска, такое размещение увеличивает скорость исполнения оверлейной программы Обращение: OVRINITEMS При обращении к этой процедуре программа, прежде всего, проверит, достаточен ли объем имеющейся в ПК EMS-памяти для размещения оверлейного файла. Если это так, то оверлейный фай i считывается в EMS-память, сам файл закрывается, и программа будет получать оверлейные модули из этой памяти. Если же EMS-память отсутствует или ее объем недостаточен, обращение к проце- дуре ш норируется, и программа будет считывать оверлейные модули с диска. Все управление оверлеем осуществляется стандартной подпрограммой, которая называется администратором оверлея. Эта подпрограмма получает управление всякий раз, когда программа обращается к ресурсам оверлейно! о мо- дуля. не размещенного в данный момент в буфере. Администратор оверлея сна- чала перемешает предыдущий оверлейный модуль из буфера в, так называемую, контрольную зону, а уже затем грузит с диска в буфер новый модуль. Если в мо- мент. когда оверлей находится в контрольной зоне, npoi рамма вновь обратится к нему, он вернется на свое старое место и, таким образом, затраты времени на об- мен данными с диском будут уменьшены. Программист может задать размер кон- трольной зоны с помощью обращения к процедуре OVRSETRETRY и получить этот размер с помощью функции OVRGETRETRY. Обычно размер контрольной зоны составляет от одной трети до половины размера оверлейного буфера. Мож- но подобрать этот размер экспериментально в ходе пробного прогона программы. Для этого используются две переменные модуля OVERLAY: var OvrTrapCount Word,{Счетчик обращений к администратору} Ovrl oadCount' Word;} Счетчик загрузок в оверлейный буфер}
Bb SOKpyPOBF ЕВЫЕ МЕТОДЬ ИНТОСРНАП КИ И ПРОГРАММ I РОВАН ИЯ 111 Всякое обращение программы к оверлейному модулю, которого нет в оверлейном буфере (в том числе и к модулю, находящемуся в коня рольной зоне), приводи г к наращиванию содержимо1 о переменной OVR1RAPCOUNT на едини- цу. Всякая загру зка оверлейною модуля и з файла в буфер увеличивает на едини- цу счетчик OVRLOAD( ’OUT I. В интерфейсной части модуля OVtRLAY объявлены еще три перемен- ные, которые могут ока заться полезными для некоторых применений. type vrReadFunc = Function (OvrSeg. Word): Integei; var vrReadBuf: OvrReadFunc; {Функция чтения из оверлейного файла} vrResult integer; {I [ризнак ошибки оверлея} vrFileMode:Byte;{Cnoco6 доступа к оверлейному файлу} Переменная OVRRESUL Г содержит код, указывающий на успех или не- успех каждой очередной операции администратора оверлея. Значения этой пере- менной могут быть такими:. О - операция прошла успешно; - 1 - общая ошибка; - 2 - не найден оверлейный файл; - 3 - не хватает памяти для оверлейного буфера; - 4 - ошибка чтения -записи оверлейного файла; - 5 - не работает драйвер I MS-памяти; - 6 - не хватает EMS-памяти. Переменная OVRFILEMODE обычно содержит 0, чт о грактуе гея кг к воз- можность доступа к оверлейному файлу только для чтения информации. Перед вызовом процедуры OVR1NIT программа может у станови гь друг ое значение «той переменной и, таким образом, изменить доступ к файлу, что бывает необходи- мым. ес. ш ПК подключен к сети ЭВМ. В переменной OVRREADBI Т содержатся имя функции, к которой обра- щается администратор оверлея при каждом ч гении из оверлейного файла. Про- грамма может перехва гитг обращение к этой фу нкции и проанализировать ре- зультат операции. Для этого необходимо в основной программе сохранить имя стандартной функции чтения в глобальней переменной типа OVRREADFUNC и помост ить в переменную OVRREADBI IF имя новой функции. В эту новую функ- цию администратор будет передавать управление всякий раз, когда появится не- обходимость чтения из оверлейного файла. Программа может проверить состоя- ние дисков перед исполнением операции (например, наличие нужного сменно-о диска), выполнить саму операцию (путем вызова функции сохраненной в гло- бальной переменной) проверить результат обращения и предпринять необходи- мые действия. Нормальное завершение операции чтения указывается нулевых значением функции чтения. ненулевое значение означает ту или иную ошибку; код ошибки стандартен для ДОС (см. прил.З) и/или для драйвера EMS-памяти. При желании можно пристыковать оверлейный файл в конец FXF-файла основной программы. При этом следует учесть, что интегрированная среда при- стыковывает в конец EXE-файла отладочные таблицы, поэтому программу и все ее модули следует компилирован в режиме отключенных опций OPTIONS /COMPh.ER/DF.DUG INFORMATION и OPTIONS/COMPILER/LOCAL SYMBOLS (см.прил. 2.8). Для обьединения ЕХЕ-файла с оверлейным файлом необходимо дагь такую команду ДОС:
112 Глава 3. Объектно-ориентированное программирование. COPY /В NA ME.EXE+NAME.OVR Здесь NAME.EXE - имя ЕХЕ-файла, NAME.OVR - имя оверлейного файла. Чтобы оверлеи читались ил ЕХЕ-файла, нужно просто указать имя этого файла при обращении к OVRIN1T: Ovrlnit(ParamStr(0)); (в программу всегда передается параметр ParamStr(O), в котором ДОС со- общает полное имя запущенной программы - с указанием диска и каталога, оз ку- да была загружена программа). 3.4.7. Прямое обращение к памяти и портам ввода - вывода В Турбо Паскале имеется пять предварительно объявленных .массивов; MEM, MEMW, MEML, PORT и PORTW. Первые три обеспечивают доступ к лю- бому участку оперативной памяти по абсолютному адресу, два других - доступ к портам ввода-вывода. Компонентами массива МЕМ являются данные типа BYTE, массива MEMW - типа WORD, массива MEML - типа LONGINT. Обращение к элементам этих массивов, т.е. их индексация, имеет специальный вид: каждый индекс пред- ставляет собой абсолютный адрес и состоит из двух выражений типа WORD, пер- вое дает сегментную часть адреса, второе - смещение; выражения разделяются двоеточием. Например: Мет[$0000:$1000] := 0; DataMem := MemWfSeg(p):Ofs(pl]; MemLong :.= MemL [64 i*SizeOf (real) ]; Как следует из технического описания операционной системы MS-DOS, в памяти по адресу $FOOO:$FFFE располагается байт-указатель типа компьютера. Следующая программа (пример 6) прочтет этот байт и выведет на экран тип IIK. Пример 6. begin Write (' Тип компьютера:'); case Mem [$FOOO:$FFFE] of $FF : WriteLn (’PC); $FE : WriteLn('XT’); $FD : WriteLn('PCjr'); $FC : WriteLn('AT'); $F9 : Writel,несовместимый c PC) end end. Компонентами массива PORT являются байты (тип BYTE), а массива PORTW - слова (тип WORD). Индексами этих массивов должно быть выражение типа BYTE, указывающее номер нужного порта. Присвоение значения элементу массива PORT или PORTW приведет к записи в порт, упоминание элемента в вы- ражении - к чтению и з порта. Компоненты массивов PORT и PORTW нельзя пе- редавать в качестве параметров процедурам или функциям. Эти идентификаторы не употребляются без индексных выражений. 3 4.8- Длинные строки Среда Турбо Паскаль 7.0 обладает весьма интересным новшеством: в ней введена поддержка длинных строк, т.е. строк, длина которых может превышать
Высокоуровневые t етодь информатики и пр, грани hi оьа <ия. 113 255 байт. Как известно, тип String в Турбо Паскале имеет максимальную длину 255 байт. Эю связано с тем, что истинная длина строки в эт ом т ипе указывается первым байтом, мощность которого не позволяет опредг[ягь строки большей длины. В го же время в языке С используется другой п )дход к заданию текст овых строк: первый байт строки является ее первым символ >м, второй байт - вторым символом и т.д., пока не встрети гея байт с символом #0. Таким образом, длина строки не укатывается явно, кат. в типе String, а определяется по замыкающему символу #0. Ясно, что такие строки могут иметь произвольную длину, ограничи- ваемую лишь объемом опсрат ивной памяти и ли принятой схемой ее адресации: в MS-DOS такой граг ицей является длина сегмента, поэтому максимально возмож- ная длина С-с гроки для ПК составляет 65535 символов. 1 акие строки в дальней- шем будут называться ASC1 lZ-строками. Дэ'Я реализации операций над ASCIlZ-ci роками в язык введен новый тип PChar, определяемый как указатель на символ: type PChar -Char; Однако такой обычный для Паскаля тип-указатель в рамЛа> Турбо 11аска- ля 7.0 трактуется необычным способом: считается, чго он указывает на цепочку символов заканчивающуюся терминальным нулем, т.е. на ASCI lZ-строку. Более того, с н им типом совместим любой одномерный символьный массив с ну гевой левой границей, а переменные типа PChar можно индексирова гь. как если бы они были массивами символов. Следующая программа напечатает все за1 1авные бук- вы английского алфавит а. {$Х+] {Включаем расширегный синтаксис] var Chars : array [0..26] of С har; {Массив символов] PChars: PChai; {Указатель на символ] k : Integer; begin for к := 0 to 25 do Chars} к] := Chrfk ord('A’): {Наполняем массив] PChars := Chars: {Указателю присваиваем массив!} PChars[26] :=#0; {Индексируем указа гель!} WriteLn(PChars) {Печатаем у каза гель!} end. Три последние оператора npoi раммы недопустимы в с гандартном П аска ле и в ранних версиях Турбо Паскаля, но возможны в версии 7.0, если включен расширенный синтаксис (директивой {SX+] или опцией Options/Compiler/Extended syntax). Следует обратить внимание: процедура Write I п этой версии умеет работат ь с ASCII?-строками Для поддержки ASCIIZ-строк р гзработан моду ib Strings, в котором реа- лизованы необходимы процедуры и функции. Функция StrCat Объединяет строки. Заголовок: 1 unction StrCattDcst. Source: PChar): PChar; Копирует строку Source в конец ст р< >ки Dest и возвращает указатель на начало Dest. Функция StrComp Сравниваст строки. 3ai о. ювок:
114 I ЛАВА 3. ОЬЫ К НО-ОРИЕН ИРОВАНЬОЕ ПРСТАММИРОВАНИЕ. Function StrComp(Strl Str2. PChar) Integer; 11обайтно сравнивает строку Str! co строкой Strl и возвращает следующий результа г: =0 StrI=Str2; >0 Strl>Str2; <0 Strl<Str2. Функция StrCopy Копирует строку. Затол >вок: Function StrCopy(Dest, Source: PChar): PChar; Копирует строку Source в строку Dest и возвращает указатель на Dest. StrCopy не проверяет реальный размер памяти, связанный с Desi (он до тжен быть не меньше StrLen(Source) Ы). Процедура StrDispose Удаляет строку из кучи. Заголовок. Procedure StrDispose(Str: PChar); Строка Str должна быть предварительно помешена в кучу функцией StrNew. Если Str=NIL, процедура ничего не делает. Функция StrECopy Объединяет строки. 3ai оловок: Function StrECopy(Dest, Source: PChar): PChar; Эта функция работает в точности как StrCat, но возвращаег указагель на конец сцепленных строк, т.е. на терминальный но зь. Функция StrEnd Возвращает конец ст роки. 3ai оловок: Function StrEnd(Str: I ’Char): PChar; Функция возвращает указатель на термин^ зьный ноль ASCIIZ-строки Str. Функция StrlComp Сравнивает строки. Заголовок: Function StrlComp(Sul, Str2: PC har): PChar;. Функция сравнивает строки, игнорируя возможную разницу в высоте букв. Возвращает такой же результат, как и StrComp. Функция правильно работа- е г лишь с лат иницей. д. зя кириллицы ее нужно модифицировать (см. ниже). Функция StrLCat Объединяет строки. Заголовок: Function StrLCat(Dest, Source: PC har; MaxLen: Word): PChar; Копирует символы строки Source в конец строки Dest до тех пор, пока не будут скопированы все символы, или когда длина сцепленной строки Desi н е дос- тигнет MaxLen. Возвращает указатель на сцеплгнну ю строку. В отличие от StrCopy эта функция блокирует возможное переполнение области памяти, связанной с Dest. Обычно в качест вс MaxLen используется вы - ражение SizeOI (Dest) -1.1 [апример: [$Х+] Uses Strings; var S: array [0..9] of Char; begin StrCopvtS, 'Turbo'); StrLCat(S,", SizeOI, S)-l); StrLCatfS, 'Pascal', S.zeOfzS)-1);
ВЫСОКОУРОВНЕВЫЕ Ml ТОДЫ ИНФОРМАТИКИ И f POI РАНЖИРОВАНИЯ. 115 WriteLn) S) { Напечат ает ' 1 urbo Pas") end; Функция StrLComp Сравнивает строки. Заголовок: Function StrLComp) Dest, Source: 1 'Char; Maxi ,cn Word). PC har; В отличие от StrComp сравнивает не более Maxi еп символов ст рок Воз- вращаемый результат такой же. как и у StrComp. Функция StrLCopy Зато iobok: Function StrLCopy) Dest. Source: PChar; MaxLen. Word). PC har: Копирует символы из строки Source в строку Dest до тех пор. пока не бу- дет скопирована вся строка или пока не 6} дет скопировано MaxLen символов. В отличие от StrCopy блокирует возможное переполнение области памят и, связан- ной с Dest. В качестве MaxLen обычно используется выражение SizeOt (Dest) -1. Например: IЬХ t-} I Jses Strings: var S: array [ 0..9] of Char; begin Strl .Copyt S.' Iurbo Pascal', SizeOf(S)-l); WriteLn(S) {Напечатает ' Turbo Pas") end, Функция StrLen Возвращает длину строки. Загс ювок: Function StrC atiStr: PC har): Word, Функция StrLIComp Сравнивает строки с учетом регистра Заголовок: Function StrLIComp(Strl. Str2: PCbar; MaxLen: Word): PChar. Сравнивает не более MaxLen символов строк, проверяя точное соответст- вие высоты букв. Возвращаемый ре1ультат см. StrComp. Функция правильно ра ботает только с латиницей Функция StrLower Преобразует в строчные буквы. Заголовок: Function StrLower(Str: PC har): PChar, Преобразует заглавные буквы строки Str к строчным и возвращает ужаза- тель на результат. Функция правильно работает только с латиницей. Функция StrMove Копирует строку. Заголовок: Function StrMove(Dest Soui се: PChar, Count: Word): PC har; Копирует точно C ount символов строки Source в ст року Dest и возвращает у казатель на результат. Функция и, норирует дейс гвите тьные размеры строк и може г выйти за их пределы. Функция StrNew Помещает строку в кучу. Заголовок. Г unction StrNewfStr: PChar): PChar; Функция Str Pas Преобразует ASC HZ-строку в строку String. Заголовок: Function StrPasfS r: PChar,): String;
116 Глава 3. Объектно -ориентированное программирование. Функция StrPCopy Преобразует с гроку String в ASCIIZ-сгроку. Заголовок- Function StrPCopy(Str: PChar; S String): PChar, Возвращав г указатель на Str. Функция StrPos Ищет подстроку. Заголовок: Function StrPos(Strl, Str2: PChar): PChar; Ишет подстроку Str2 в строке Sti 1 и возвращает указатель на первое вхо- ждение Str2 или NIL, есди подстрока не найдена. Функция StrRScan Ищет последний символ Заголовок: Function StrRScan(Str: PChar; Cn: Char): PChar; Ищет символ Ch в строке Str и возвращает указатель на последний обна- руженный символ Ch или Nil.. если символ не найден. Функция StrScan Ищет первый символ. 3ai оловок: Function StrScan(btr: PChai; Ch: Char); PChar; Ищет символ Ch в строке Str и возвращает указатель на первый обнару- женный символ Ch или NIL. если символ не найден. Функция StrUpper Заголовок: Function StrLowerfStr: PChar): PChar; Преобразует строчные буквы строки Str к заглавным и возвращает указа- тель на результат. Функция правильно работает только с латиницей. Четыре функции модуля Strings (StrLower. StrUpper. StrlComp и StrLIComp) используют преобразование высоты букв и работают корректно толь- ко для букв латинского алфавита (латиницы). Для ру сских букв эт и функции можно изменить следующим образом: {Этот модуль содержит модификацию функций стандартного модуля Strings для работы с кириллицей (альтернативный вариант кодировки) {$Х+} Unit StringsR IN FERI ACL Function LoC.ase(Ch: Char): Char; Function UpCase(Ch: Char) Char. Function StrLower(Str PChar): PChar; Function StrUpper(Str: PChar): PChar, Function StrlComp(Strl Str2: PChar): Integer; Function StrLIComp(Strl. Str2 PChar. Maxf en: Word): Integer; IMPLEMENTATION Uses Strings; Function LoCase(Ch: Chai): Char; {Преобразует латинскую или русскую букву Ch к строчной) begin case Ch of 'A'. .'Z':LoCase:= Chr(ord(’a’)J-ord(Ch)-ord('A')): ’A' .'lT:LoCase~ Chr(ord(’a')+ord(Ch)-ordCA')); 'P'.. Я':1 x>Case:= Chr(ord(,p')+ord(Ch)-ord(,P')); else
Высокоуровневые мыэды иг форма, ики и про»гликирования. 117 LoCase:= Ch end end; {---------------} Function UpC ase<< h: Char). Char; {Преобразует латинскую или русскую букв} Ch к заглавной} begin case Ch of 'a ..'z': UpCase := Chr( ord('A')H ord(Ch)-ord('a')); UpC ase := C hriordt A’) Hord(Ch)-ord('a'j); 'р'..'я': UpCase := C hr(ord( P')4 ord(Ch)-ordf’p)) else UpC ase:- Ch end end; {---------} Function StrLow er(Str. PChar): 1 ’Char; {Преобразует латинские и русские буквы строки Str к строчным} var k: Word; begin for к := 0 to St: Len(Str)-1 do Strfk] — LoCase(Str[k]); Str Lower := Str end; {---------) Function StrUpper(Str. PC har): PChar; {Преобразует латинские и русские буквы строки Str к заглавным! var k: Word; begin for к :=0 to StrLen( Str)-1 do Str[k] UpCase(Slr| kJ); Strl Jpper:= Str end; {---------} Function StrlComp (Strl. Str2 : PChar): Integer: {Сравнивает две строки. И1норнруя возможную разницу в высоте латин- ских или русских букв} var k: Word; Max: Word; begin {Определяем максимальное количество сравниваемых символов как ми- нимум длин строк} Мах := StrLen(Strl); if StrLen (Str2).< Ma x then Max := StrLen(Str2); {Проверяем символы до первого несовпадения Буквы преобразуем к за-
118 Глава 3. Объектнс-ориентированнсе программирование. главным} for к := 0 to Мах-1 do if UpCase(Strl[k])oUpCase(Str2fk]) then begin {Строки не равны} StrlComp := ord(UpCase(StrlCkJ;)-ord(UpCase(Str2[kJ)); Exit end; {Разницы нет - результат зависит от совпадения длин} StrlComp := StrLen(Strl)-StrLen(Str2) end; {----------} Function StrLIComp(Str1, Str2: PChar, MaxLen: Word): Integer. {Сравнивает не более MaxLen символов строк, проверяя точное соответ- ствие высоты букв} var k. Max: Word; begin {Определяем максимальное количество сравниваемых символов как ми- нимум длин с грок и MaxLen} Мах := MaxLen; if StrLen(Strl)<Max then Max :- StrLen(Strl); if StrLen{Str2)<Max then Max StrLen(Str2); {Проверяем символы до первого несовпадения.Буквы преобразуем к за- главным} for к := 0 to Max do if UpCasefStrl | kJ)oUpCase(Str2[k]) then begin StrLIComp := ord(UpCase(Strl[k] l)-ord(UpCase(Str2[k] i); Exit end; {Разницы нет. Если проверено MaxLen символов, строки считаются рав- ными, в противном случае результат зависит от совпадения длин строк} if Max=Maxl ,en then StrLIComp := О else StrLIComp := StrLen(Strl)-StrLen(Str2) end; end. При использовании этот модуля, следует ссылайться на него в предложе- нии Uses после ссылки на стандарт ный модуль Strings; Uses Strings. StringsR. . 3.5. Встроенный Ассемблер Ассемблером называется машинно-зависимый компилятор, преобразую- щий специальным образом составленные текстовые строки в машинные инструк- ции. Как и любой другой компилятор, Ассемблер упрощает разработку программ за счет того, что предоставляет пользователю доступ к кодам машинных инструк- ций и операндам с помощью символьных имен.
Высокоуровневые методы информатики и программирования 119 В этой главе рассматриваются приемы программирования с помощью Ас- семблера. встроенного в компилятор Турбо Паскаля. Встроенный Ассемблер име- ется в версиях 6.0 и 7.0 Турбо Паскаля и, в руках опытного программиста, пред- ставляет собой мощный инструмент, по (виляющий «выжать» из ПК все возмож- ное. 3.5.1. Общее описание МП 8086 8088 Встроенный Ассемблер (далее - просто Ассемблер) дает возможность программировать на уровне отдельных машинных инструкций. Это главное отли- чие Ассемблера от Паскаля, и в этом отличии сосредоточены все его достоинства и недостатки. Достоинство заключается в том, что, программируя на Ассемблере, программист обычно выбирает последовательность машинных инструкций так, чтобы реализовать нужные вычисления с максимальной скоростью при мини- мальных затра гах памяти. В то время как даже такой весьма совершенный компи- лятор, как компилятор Турбо Паскаля, неизбежно вносит в машинный код неко- торую избыточность, уменьшающую скорость счета и увеличивающую затраты памяти. С другой стороны, программирование на уровне машинных инструкций - чрезвычайно хлопотное занятие и не может сравниться по скорости разработки программ с программированием на 11аскапе. - в этом заключается главный недос- таток Ассемблера. Чтобы использовать средства Ассемблера, необходимо ясно представлять себе детали архитектуры микропроцессоров Intel 80x86. К этому семейству отно- сятся микропроцессоры: 8086 - 16-разрядный микропроцессор, используемый в 1 IK IBM PC/XT; 8088 - аналог 8086. отличается от него только взаимодействием с памя- тью: 8086 может обмениваться с памятью как байтами, так и 16-разрядными сло- вами. в то время как 8088 - только бай гами: 80286 - улучшенный вариант 8086, используемый в ПК IBM АТ; может работать в двух режимах: в реальном режиме, полностью эмулирующем работу' МП 8086. и в защищенном режиме, в котором способен адресовать память до 16 Мбайт (в реальном - до 1 Мбайт); 80386 - 32-ра (рядный вариант 80286: способен адресовать до 4 Гбайт; 80486 - комбинация 80386/80387. т.е имеет внутреннюю подсистему реа- лизации операций с плавающей т очкой; 80586 (Pentium) - имеет ряд усовершенствований, обеспечивающих ему увеличение производительности в 2 - 3 раза по сравнению с 80486. в том числе возможность обрабатывать 64 -разрядные числа. Микропроцессоры этого семейства наращивают свои возможности в пе- речисленном порядке, но строго совместимы от младших моделей к старшим: все. что может 808о78088. реализует и Pentium, но не наоборот. Ниже обсуждается архитектура (внутреннее устройство, способы адресации и система команд) МП 8086/8088. 3.5.2. Регистры В МП 8086/8088 имеется 14 регистров. В функциональном отношении они делятся на 1 руппы: • регистры общего назначения (АХ, BX, СХ, DX) предназначены для хранения операндов и выполнения основных команд, любой из них может ис- пользоваться как совокупность двух независящих друг от друга 8-разрядных ре-
120 Глава 3. Объектно ориентированное программирова1 hf. гистров: старшего байта регистра (АН, ВН, CH, DH) и младшего байта (AL, BL, CL, DL): например. АХ состоит из АН и А1 • cei ментные регистры (CS. DS. SS. ES) используются для указания сегмента при адресации памяти; • регистры-указатели (SP, BP, IP) используются для указания смещения при адресации памяти; • индексные регистры (SI. DI) применяются для индексной адресации; • регистр флагов используется для хранения признаков состояния про- цессора. Внутри одной и той же функциональной группы регистры используются различным образом. Ниже описывается специфика использования регистров. Регистр АХ Является основным сумматором. Используется во всех арифметических операциях (сложить, умножить и т.п.). Только с помощью АХ и его полурегист- ров Al IIAL возможен обмен данными с портами ввода/вывода. Регистр ВХ Используется как сумматор в арифмет ических операциях, а также как ба- зовый регистр при индексной адресации. Регистр СХ В основном используется как счетчик при выполнении операций повторе- ния и сдвига. Может также участвовать в арифметических операциях. Регистр DX Используется как регистр данных в операциях ввода/вывода, а также как сумматор при обработке длинных целых чисел (32-разрядных). Регистр CS Содержит номер сегмента памяти (сегмента кода), в котором располагает- ся текущая машинная инструкция. Для получения полного адреса следующей ко- манды, его содержимое сдвигается влево на 4 разряда и складывается с pei ист- ром-указателем IP. Содержимое CS автоматически изменяется в командах даль- него (межсегментного) перехода и вызова процедур. Регистр IP Определяет смещение относительно начата сегмента кода CS очередной исполняемой машинной инструкции. Содержимое IP автоматически изменяется в ходе исполнения инструкции, обеспечивая правильный порядок выборки команд из памяти. Регистр DS Содержит номер сегмента памяти (сегмента данных), в котором распола- гаются данные (конст анты и переменные). Все глобальные переменные и типизи- рованные константы программы Турбо Паскаля всегда располагаются в единст- венном сегмен ге, адресуемом этим регистром Регистр SS Содержит номер cei мента стека. Стек - это участок автоадресуемой памя- ти, предназначенный для временного хранения операндов. С помощью стека Тур- бо! Таскаль организует обмен данными между программой и процедурами, кроме того, в нем он размещает все локальные переменные (т.е. переменные, объявлен- ные внутри процедуры). Память стека используется по правилу «последним при- шел - первым ушел»: самый последний помещенный в стек операнд будет первым извлекаться из него.
ВЫСОКОУРР°.НЕВ1 IF М -ТОДЬ ИНФОРМАЦИИ И ПРО РАММИРОВАНИЯ. 121 Регистр SP Указывает на вершину стека, т.е. совместно с регистром 55 адресует ячейку памяти, куда будет помещаться операнд или отку да он будет извлекаться. Содержимое ttoi о регистра автоматически уменьшается после размещения в сте- ке очередного операнда и увели чивается после извлечения операнда из стека. Регистр ВР Так называемый указат ель базы Обле> чает создание и использование ло- кального стека (т.е. стека для использования внутри процедуры}. Регистр ES Дополнительный сегментный регистр ES испотьзуется для межсегмент- ного обмена данными и в некоторых строковых операциях. Регистр SI Определяет адрес источника информации при индексной адресации дан- ных (например, при обработке массивов). Обычно используется в паре с ретист- ром DS. Регистр DI В паре с регистром £5 определяет приемник информации при межсе! - ментном обмене данными. Регистр флагов Отдельные разряды (биты) этого регистра имеют следующее назначение: Флаг переноса CF Содержит 1, ес 1и произошел перенос единицы при с тожении или заем единицы при вычитании. Используется также в циклических операциях и опера- циях сравнения. Флаг четности PF Содержит 1, если в результате операции по чучено число с четным коли- чеством значащих разрядов, т.е. дополняет результат до нечета. Используется в операциях обмена для контроля данных. Флаг внешнего переноса AI Контролирует перенос из 3-го бита данных. 1 Толезен при операциях над упакованными десятичными числами. Флаг нуля ZI Равен 1, если в результате операции получен ноль, и равен 0 в противном случае. Флаг знака SF Равен 1, если в результате операции получено отрицательное число (с единицей в старшем разргде). Флаг трассировки TF Равен I, если программа исполняется по шагам, с передачей управления 1 (осле каждой выполненной команды по прерыванию с вектором 1. Флаг прерываний IF Содержит 1, если микропроцессору разрешена обработка прерываний. Флаг направления DF Управляет направлением передачи данных: если он содержит 0, то ног де каждой индексной операции содержимое индексных регистров увеличивается на 1, в противном случае - уменьшается на 1. Флаг переполнения OF Устанавливается в единицу, сети в результате операции получено число, выходящее за разрядную сетку микропроцессора
122 ГПАВЛ 3. ObbEI ТГ О-ОРРЕ ТИРОВАННОЕ ПРОГРАММИРОВАНИЕ 3.5.3. Адресация В архитектуре МП 8036/8088 адрес любого байта задастся двумя 16 битовыми словами - сегментом и смещением. При формировании 20-разрядного полного адреса, необходимого для адресации в пределах 1 Мбайт, сегмент сдви- гается влево на 4 разряда (умножается на 16) и складывается со смещением. По- скольку емкость 16-разрядного смещения составляет 65536 значений, в пределах одного сегмента можно адресовать до 61 Кбайт. Архитектура МП позволяет использовать семь различных способов адре- сации. Регистровая адресация 11звлекает операнд из регистра или помещает его в регистр. 11римеры: mov ax,bx {Извлекаем из ВХ и помещаем в АХ} add сх,ах {Содержимое АХ прибавляем к СХ} push ex {Заталкиваем в стек содержимое СХ} Непосредственная адресация Операнд (8- или 16-разрядная констана) содержится непосредственно в тепе команды. Примеры: mov ах, 100 {Загружаем в АХ значение 100, add ах,5 {К содержимому АХ прибавляем 5 ] mov cx,$ITFF {Помещаем в СХ значение 65535} Прямая адресация Смещение операнда задается в теле программы и складывается с рет ист- ром DS; например: var X: Word. В: Byte; mov ах,Х {Пересылаем значение переменной X регистр АХ} add ah,В {К coдepжимoмv регистра АН прибавляем значение переменной В} mov Х,ах {Пересылаем содержимое регистра АХ. в область памяти пере- менной X] Косвенная регистровая адресация Исполнительный адрес операнда (точнее, его смещение) содержится в од- ном из регистров BX. BP. SI или DI. Дтя указания косвенной адресации этот ре- гистр должен заключаться в квадра гные скобки, например: mov ax,|bx] {Содержимое 16 -разрядного слова, хранящегося в памяти по адресу О8:ВХ.пересылаем в регистр АХ}; Каждый из регистров BX...DI по умо знании работает со своим сегмент- ным регистром: DS:BX. SS:BP. DS:SI. F,S:D1 Допускается явное указание сегментною регистра, если он отличается от умалчиваемого, например: mov ax,es:| bx] Адресация по базе Базовый регистр ВХ (или BPj содержит базу (адрес начала некоторого фрагмента памяти), от носительно которой Ассемблер вычисляет смещение, на- пример: mov ах.[Ьх]+10 {Загружаем в АХ 10-й по счету байт от начала базы памя-
Высокоуровневые методы мн иогма’ики i программ и pobai иг. 123 ти по адресу DS-.l IX}; Индексная адресация Один из индексны < регистров SI или DI указывает положение элемента относительно начала некоторой области памяти. 1 1усть, например, АОВ - имя массива значений типа Byte. Тогда можно использовать такие фрагменты. mov si, 15 {Помещаем в SI коне ганту 15} moc ah,AOB[si] ] Пересылаем в АН 16-й по порядку байт от начала масси- ва} mov si.O mov AOB[si],ah {Я ересылаем полученное в самый первый элемент масси- ва} Адресация по базе с индексированием Вариант индексной адресации для слу чая когда индексиру емая об пасть памяти задается своей базой. Например. mov ax,[bx][si] Этот тип адресации удобен при обработке двумерных массивов. Если, на- пример, АОВ есть массив из 10x10 бай г вида var АОВ: array [0..9,0..9] of Byte; то для доступа 1 элементу АОВ [2,3] можно использоват i акой фрагмент mov bx,20 [Базе, с гроки 2] mov si,2 {Номер 3-го элемента* mov ax.AOB[b <] [si] {Доступ к элементу] 3.5.4. Система команд В приводимых ниже таблицах указывается мнемоника всех допу стимых инструкций для МП 8086/8088. Для удобства пользования в^е команды разбить: на 6 функциональных групп - пересылки данных, арифметические, битовые, строковые, передачи управления, прерываний. Внутри каждой группы команды объединяются в подгруппы по общим, юполниюльным признакам. Детальный анализ всех команд МП 8086'8088 занял бы слишком много места, поэтому в идущих за т аблицами пояснениях рассматриваются лишь и аибо- лее популярные команды. Исчерпывающее описание всех команд можно оты- скать в работах |1|и|2Р|. Команды пересылки данных Мнемо- ника Формат Пояснение Команды общего назначения MOV MOV приемник, источник Перестать значение PUSH PUS11 источник Поместить в стек POP POP приемник Извлечь и i стека XCHG XCHG приемник, источник Обменять значения XLA1 XLA Г таблица Загрузись в AL байт из табли цы Команды ввода-вывода IN IN аккумул п ор, порт Чг тать и i пор га OUT OLT порт, аккумулятор Записа гь в порт
124 Глава 3 Объектно-ориентированное программирование. Мнемо- ника Формат Пояснение Команды пересылки адреса LEA LEA регистр 16, память 16 Загрузить исполнит ельный адрес LDS LDS регистр 16, память32 Загрузить в DS:perncTpl6 полный ад- рес LES LES регистр 16, па.мять32 Загрузить в Е8:регистр16 полный ад- рес Команды пе •>есылки флагов LAHF LAHF Загрузить флаги в АН SAHF SAHF Установить флаги из АН PUSHF PUSHF Поместить флаги в стек POPF POPF Извлечь флаги из стека Одна из наиболее часто используемых команд MOV позволяет в защи- щенном режиме переслать байт или слово из регистра в регистр, из памяти в ре- гистр или из регистра в память. Тип пересылаемых данных (байт или слово) оп- ределяется регистром, участву ющим в пересылке. 11иже приводят ся примеры ис- пользования команды: mov ах,Table {Пересылка слова из памяти в АХ} mov Table,ah {Пересылка байта из Al I в память} mov ds,ах {Пересылка в сегмент данных} mov es:[bx],ax {Пересылка слова в память: базовая адресация с заменой сегмента} mov ch,-17 {Перес ia гь константу в регистр} mov Table,$FF {Переслать константу в память} С помощью MOV нельзя пересылать: • из памяти в памя гь, например, вместо mov Meml,Mem2 следует использовать mov ах,Мегп2 mov Mem Lax • константу или переменную в DS. например, нельзя mov DS,Data_Seg нужно: mov ax,Data_Seg mov ds,ax • один сегментный регистр в другой, например, нельзя mov es, ds но можно mov ах,ds mov es,ax • в регистр CS; значение этого регистра (сегмента кода) автоматически меняется при выполнении дальних команд CALL и JMP; кроме того, он загружа- ется из стека при выполнении команды RF.TF (выход из дальней процедуры). Для временного сохранения pei истров и данных, а также для обмена зна- чениями между регистрами, широко используются стековые команды PC SII и
Высокоуровневые методы tn форматики и программирования___________________ POP. Каждая из них работает со словом, т.е. в стек нельзя помес гить или извлечь из него одиночный бай г. 11ри выполнении PUSH вначале уменьшается на 2 со- держимое ука зателя SP. а затем операнд помешается по адресу SS- SP При извле- чении из стека снача па читается память по адресу SS' SP. а затем SP увеличивает- ся на 2. Таким образом, при заполнении указа гель вершины сп ека SP смещается к младшим адресам, а при освобождении - к старшим. При работе со стеком следу- ет помнить о специфике использования стековой памяп и («последним пришел - первым ушел»), а также о том. что эта память интенсивно используется при вызо- ве процедур, т.е. состояние стека к моменту выхода из процедуры должно быть crpoi о согласовано с дальнейшей работой программы Первое условие <ятределяет порядок 1. звлечения данных из стека - он должен быть обрат ным порядку, в кото- ром эти данные помещались в стек. Второе условие фактически означает, что по- сле выхода из процедуры указатель SP должен содержат ь то же смещение, чт о и I моменту входа в нее. Иными словами, процедура не должна «забыть» в стеке лишнее слово или взять из него больше нужного. Команда загрузки адреса LEA загружает в регистр адрес I смещение) нуж- ного участка памяти. Этого же можно достичь с помощью зарезервированного слова OFFSET, стоящего перед именем переменной. Например: vai X: Word; asm mov ax, OFFSE1 X {Загружаем смещение X в АХ} lea ах.Х {То же дейст вне} end ; Разница состои г в том, ч го в случае команды 1.1 А разрешается использо- вать индексную адресацию, что особенно удобно при пересылке массивов дан- ных. Две другие команд: i адресной загрузки - LDS и 1 .ES - загружают первое 16-разрядное слово из источника в регистр-приемник, а затем с тедующее слово - в регистр DS или ES т.е. они рассчитаны на загрузку полного адреса операнда (сегмента и смещения). Арифметические команды Мнемоника Формат Комментарий 1 .оманды сложения ADD ADD приемник, ис- точник Сложить ADC ADC приемник, ис- точник СлояЖт ь, доба1 ит ь перенос AAA AAA Скорректировать сложение для таблицы ASCII DAA DAA Скорректирова гь сложение для двоично- деся гичных чисел INC INC приемник Увеличит ь на единицу Команды вычитания SUB SI IB приемник, ис- точник Вычесть
Глава 3. Оььектно-ориентированное программирование. Мнемоника Формат Комментарий SBB SBB приемник, ис- точник Вычесть с заемом AAS AAS Скорректировать вычитание для таблицы ASCII DAS DAS Скорректировать вычи тание для двоично- деся гичных чисел DEC DEC приемник Уменьшить на единицу NEG NEG приемник Обратить знак CMP СМР приемник, ис- точник Сравнить Команды умножения MUL MUL источник Умножить без знака IMUL IMUL источник Умножить со знаком ААМ ААМ Скорректирова гь умножение для таблицы ASCII Команды деления DIV DIV источник Делить без знака 1DIV ID1V источник Делить со знаком AAD AAD Скорректировать деление для таблицы ASCII Команды расширения знака CBW CBW Преобразовать байт в слово CWD CWD | Преобразовать слово в двойное слово При использовании арифметических команд следует помнить о том. что МП может обрабатывать знаковые числа, числа без знака, а также двоично- десятичные числа В беззнаковых числах для представления значения использу- ются все биты, т.е. они эквивален гны типам Byte и Word, в то время как знаковые числа в старшем разряде хранят знак числа и эквивалентны типам Shortlnt и Integer. Двоично-десятичные числа используют по 4 бита для каждого десятично- го разряда и могут быть упакованными или неупакованными. В первом случае один байт хранит 2 десятичные цифры (старшая - в старшем полубайте), во вто- ром - только одну (старший полубайт не используется). Основные арифметиче- ские команды МП (ADD. SUB, MUL, DIV) не учитывают двоично-десятичную форму представления чисел, поэтому в архитектуру МП включены команды кор- рекции результата. Битовые команды Мнемоника । Формат Коммен гарий Логические команды AND AND приемник, источник Выполнить AND OR OR приемник, источник Выполнить OR XOR XOR приемник, источник Выполнит ь XOR NOT NOT приемник Выполнить NOT
Высокоуровневые »ртоды hi фориатики .1 программирования. 127 Мнемоника Формат Комментарий TEST TEST приемник, источник 11роверитг Сдвиговые команды SAL/SHL SAL приемник, счет чик Сдвинуть влево SAR/S1IR SAR приемник, счетчик Сдвину гь вправо ROL ROL приемник, счетчик Сдвинуть в icbo цикли- Ч.ьКН ROR ROR приемггик, счетчик Сдвину । ь вправо цик ги- чески RCL RCL приемник, счетчик С двинуть в тево с пере- носом RCR RCR приемник, счетчик Сдвинуть вправо с пе- реносе г Битовые команды используют ся при исчислении логических выражений, а также в тех случаях, когда необходимо измени гь отдельные разряды операнда. По ические команды AND, OR XOR и NO'l эквивален гны соответству юшим операциям Турбо Паска >я в случае, когда операндами являются целочисленные выражения. Команда TESI выполняет целочисленную операцию поразрядного суммирования AND, но не изменяет значения операндов, а лишь устанавливав г флаги в соответствии со значением результата сравнения, обнуляет CF и OF, из- меняет PF, ZF, SF и не меняетАР (флаг ZF ус гановится в 1 в том случае, когда оба операнда содержат по единице хотя бы в одном соответствующем разряде) Ко- манды сдвига SHL/SHR эквивалент ны одноименным операциям Турбо Паскаля и от личаются от команд циклического сдвига ROLIROR тем, что выт е< ценные в ходе и х выполнения значащие разряды теряются в то время кал при циклическом сдвиге эти разряды появляются «с другой стороны». Например, если выполнить фрагмент moval.l {Загружаем в AL единицу} shr al,l {Сдвигаем вправо на 1 разряд} регистр AL будет содержать 0 (вь-^ненная вправо единица будет помешена в CF), в то время как после замены команды SHR на ROR в нем будет значение $80=128 (вытесненная единица будет помешена в ст арший бит оегистра). Счетчиком в командах сдвига может бы гь цифра 1 или количес гво сдви- 1 ов, указываемое в per истре CL. Команды передачи управления Мнемоника Формат Комментарий Безусловные переходы CALE САН имя Войти в процедуру RF Г RFT [ко. iHnevTBo параметров] Верну гься из процедуры Л IMP JUMP имя Перей ги Условные переходы JA 'JNBE JA близ) ая мс г«.а Перейти, если выше (по- сле сравнения беззнаковые операндов)
128 Глава 3. Объектно-ориентированное программирование. Мнемоника Формат Комментарий JAE/JNB JAE близкая_метка Перейти, если выше или равно JB/JBAE/JC JB близкая метка 11ерейти, если ниже JBE/JNA JBE близкаяметка Перейти,если ниже или равно JCXZ JCXZ близкая метка Перейти, если СХ=0 JE/JZ JE близкая_метка Перейти, если равно JG/JNLE JG близкая метка Перейти, если больше (по- сле сравнения знаковых операндов) JGE/JNL LGE близкая_метка Перей ги. если больше или равно JL/JNGE JL близкая метка Перей ги, если меньше JLE/JNG JLE близкая_метка Перейти,если меньше или равно JNC JNC близкаяметка Перейти, если нет перено- са JNE/JNZ JNE близкая метка Перейти, если не равно JNO JNO близкаяме гка Перейти,если нет пере- полнения JNP/ JPO JNP близкая метка IТерейти, если нечетный JO JO близкая метка 11ерейти, если перенос JP/JPE JP близкая метка 11ерейти, если четный JS J S близкая метка Перейти, если отрица- тельный Команды управления циклами LOOP LOOP близкая метка Повторит ь цикл LOOPE/LOOPZ LOOPE близкая метка Повторять, пока равны LOOPNE/LOOP NZ LOOPNE бли жая метка Повторять, пока не равны Команды безусловных переходов CALL, RET, JMP могут использовать дальнюю или ближнюю модель памяти, в то время как команды условных пере- ходов - только малую (в пределах -128...+127 байтов). При дальней модели памя- ти (устанавливается опцией Options/Compiler/Force lar calls среды Турбо Паскаля или директивой компилятора {F+}) осуществляется как внутрисегментная, так и межсегментная передача управления, при ближней - только внутрисегментная. Инструкция CALL работает следующим образом. Вначале адрес следую- щей за CAI L инструкции (адрес возврата) помещается в стек, затем в регистр IP (или в пару CS:IP) помещается адрес точки входа в процедуру, таким образом, сразу за командой CALL будет исполняться уже первая команда процедуры. Оба адреса (точки входа и возврата) будут 16-битовыми смещениями для внутрисег- ментного вызова или 32-битовыми полными адресами для межсегментного. Все
Высокоуровневые метэде i hh dopma’hkm i грограммиговае ия. 129 процедуры (функции) Паскаля, оттранслированные в режиме IF+} или содержа- щие зарезервированное слово 1 AR в заголовке, должны вызываться как дальние. Для этого за ин< тракцией CAI 1 следует указать модель памяти: ] 'rocedure МуРгос; гаг; asm call FAR Му Proc {Вызов дальней процедуры end; Таким же способом должны вызываться все библиотечные подпрограммы (т.е. объявленные в интерфейсных частях модулей). При дальнем вызове в стек сначала загалкивается содержимое сег мента кода CS, а уже затем - смещение воз- вра га. При выходе из дальней процедуры команда RET извлекает из стека оба 16-разрядных слова и помещает первое в 1Р, а второе в CS, а при выходе из ближ- ней извлскас । из стека только смещение и помещает его в 1Р. Команды у словных переходов способны передавать у правление на метку, расположенную в пределах ближайших плюс-минус 128 байт от самой команды. Если нужно передать управление на метку расположенную дальше в том же сег- менте, или на метку в другом сег ленте, сразу за командой условной передачи рас пола1 ают безусловную команду JMP или CAL, например: стр ах.О {Проверяем АХ} jne@NotZero {АХ_0 °} jmp IsZero {Да - переходим на дальнюю метку ' ...{Нет - продолжаем работу} В таблице термин «выше/ниже» используется применительно к сравне- нию беззнаковых операндов, а «больше/меньше» - знаковых. Поскольку условные переходы реализуют вет вление программы на осно- ве проверки флагов, обычно непосредственно перед ними, располагаются коман- ды, и вменяющие эт и флаг и. чаще всего - команда сравнения СМ Р. 11иже пока заны комбинации СМР - условный переход для различных соотношений приемника и источника (первого и второго операнда) команды СМР: Условие Для беззнаковых чи- сел Для чисел со знаками I [риемник больше ис сочника JA JG Приемник и источник равны JE JE Приемник меньше источника JB JL Приемник не меньше источника JAF JGE Приемник не больше источника J JBE JLE Приемник и источник не равны JNE JNE Например: стр ах. 5 {АХ>5 ?} ja OAboveS {Да. больше - переходим} стр Ьх,-3 {ВХ<=-3 ?} jle @LessM3 {Да. меньше или равен)
130 глава 3. Обьектво-ophfhti.pobahhof программироваг me. Команды LOOP/LOOPE/L OOPNE служат для организации циклов. Все они используют содержимое регистра СХ как счетчик чис га повторений, I юманда LOOP уменьшает СХ на единицу и передает управление на метю начала цикла, если содержимое этого регистра отлично от нуля. Команды LOol'L/LOOPNE также уменьшают счетчик СХ, но передают управление в начало цикла при со- вместном условии установки (или сброса) флага ZF и неравенства нулю счетчика СХ. Вот как, например, можно отыскать нулевой байт в массиве АОВ: var АОВ: array [1..1 ООО] of Byte: asm mov ex. lt)00 {Инициируем счетчик СХ} lea bx.AOB {Помещаем адрес АОВ в ВХ} dec bx {Готовим цикл} {Здесь начало цикла проверки} @@Test: inc bx {Адрес очередного байта} cmp BYTF PTR | Ьх],0 {Проверяем байт} loopne ©Test {Замыкаем цикл} jnz ©NotZero {Если не найден нулевой байт} ...{Нашли ну ювой байт} end; Строковые команды Мнемоника Формат Коммент арий Пересылка строк MOVSB MOVSB Пересылать байты MOVSW MDVSW Пересылать слова Сравнение строк CMPSB CMPSB Сравнивать байты CMPSW CMPSW Сравнивать слова Сканирование SCASB SCASB Искать байт SCASW SCASW Искать слово Загрузка и сохранение LODSB LO1 )SB 3ai ружать бай гы LODSW IODSW 3ai ру жать слова STOSB STOSB Сохраня гь байть: STOSW STOSW Сохраня гь слова С гроковые команды рассчит аны на обработг у строк. Термин «строка» здесь отнюдь не эквивалентен аналогичному термин} Турбо I Гаскаля и означает произвольную цепочку байт или слов длиной до 64 Кбай г. Эти команды опери- руют пя гью примитивами, каждый из которых обрабатывает лишь с тин байт и пи одно слово за раз. Перед примитивом обычно указывается префикс повторения RLP/RErL/RFPNE, заставляющий выполня гься примет ив до тех пор, пока не об-
Высокоуровневые мгтсды информатики и программирования. 131 нулится счетчик повторений СХ или не будет нарушено соответствующее усло- вие. При испо. гьзовании строковы к команд важно помнит ь два обстояте тьс гва Во-первых, эти команды всегда беру г адрес строки-источника из дары DS:S1, а строки-приемника - из пары ES :Г>1 Таким образом, перед испо шением строковой команды необходимо инициироваз ь сегмен гные регистры нужным образом. Во- вторых. строковые коман, гы используют индексную адресацию с авт оматическим изменением смещения в SI/D1 после однократного исполнения примитива. Со- держимое этих регист ров изменяется на 1 при обработке байтов и на 2 при обра- ботке слов, причем наращивается, ес ги флаг направления DF сброшен, и умень- шается, если он равен 1. Вот как можно осуществить Пересы тку массива .А в массив В. var А,В' array 11..250] of Inreger; asm lea si, А {Смещение A - в SI (источник)'} push ds pop es {Инициируем LS := US] lea di,В {Смещение В - в DI (приемник; I mov ех,250 {Счетчик- переноса} с Id {I Управление переноса - наращивать} rep movsw {Переносим 500 байт} end, В npoi рамме на 1 урбо Паскале регистр DS всегда содержит сегмент дан- ных. поэтому инициировать его необязательно Что касается регистра дополни- тельного сегмен га ES, такого правила не г и, хотя, в бо 1ьшинсз ве случаев он так- же ссылается на сегмент данных, рекомендуется проводить его инициацию г грел использованием строковой команд! (см. выше команды push ds, popes). Команды прерываний Мнемоника Формат Коммент арий INT INT номер 1 (ыполнить прерывание INTO INTO 1 (ыполнить прерывание по переп< [RET IRET Вернуться из прерывания Выполнение прерываний во многом напоминает косвенный вызов даль- ней процедуры. По команце INT (INTO’ в стек помещается ре; истр фла ов сег- мент CS и указаз еть IP, а новые значенг я этих регистров берут ся из 4-байтного вектора прерывания, соответствующего номеру прерывания в команде INT, или из вектора 4 -, гля коман, гы INTO. Таким образом, единсз венным отличием от ко • манды CALL являет ся го, что в стек предвари те гьно заносится регистр фт агов. Следует, правда, отмесит; перед передачей управления программе обработки прерьгвания микропроцессор сбрасывает фла; и трассировки 1F и прерываний IF; сброс TF необходим для обеспечения нормальной рабозы отладчиков, исполь- зующих прерывание по вектору 1 или 4 сброс IF блокирует вмешазельс гво дру- гих процессов в ход обработки прерывания. Команда INTO предс гавляе г соб, >й условна >е прерывание и выполняется, если в этот момент взведен флаг переполнения ОТ. 1 команда IR.FT реализует прз вилытый выхол из программы обработки прерывания: она спит ывасз из стека 3
132 Глава 3. Объектно-ориентированное программирование. двухбай гные слова и помещает их в регистры IP, С S и регистр флагов. Команды управления Мнемоника Формат Комментарий Управление фла) ами SFC STC Установить перенос CLC CLC Очис гить перенос СМС CMC Инвертировать СЕ STD STD Установить направление CLD CLD Очистил ь направлени STI STI Разрешить прерывания CL1 CLI Запретить прерывания Внешняя синхронизация HLT HLT Остановить вычисления WAIT WAIT Ждать акл ивности на шине ESC ESC код, источник Передать команду LOCK LOCK Захватить шину Пустая команда NOP NOP Нет операции Команды внешней синхронизации работ ают следующим образом. HAL Т переводит МП в состояние останова, из которого его можно вы- вести только при перезагрузке системы или при наступлении немаскируемою прерывания. WAIT заставляет МП выполнять холост ой режим работы и каждые 5 так- тов проверять уровень сигнала на входной шине: пока на этой шине нет сигнала активности, процессор выполняет WAIT, но как только шина активизируется, он продолжит исполнение программы. Эта инструкция обычно используется для ожидания сигнала обслуживания (прерывания) высокоприоритетного устройства типа контроллера прямого доступа к памят и. Команда FSC используется для передачи указанного в ней операнда на шину данных. Тем самым обеспечивается возможность передачи команд другим процессорам. Эта команда чаще всего используется для управления работой арифметического сопроцессора. В этом случае код представляет собой код ко- манды сопроцессора, а источник - используемый в этой команде операнд. Команда I ОС К. фактически предел автяет собой однобайтовый префикс, который можно использовать совместно с любой другой командой микропроцес- сора. 11о этой команде MI I акт ивизирует одноименный сигнал на своей шине, что исключает возможность использования этой шины любым другим внешним уст- ройством (процессором). 3.5.5. Спецификация встроенного Ассемблера Приведенное выше общее описание архитектуры МП 8086/8088 являе гея базовым для любого Ассемблера, в том числе и для встроенного Ассемблера Тур- бо Паскаля. Однако Ассемблеры содержат массу дополнительных возможностей,
ВЫСОКОУРЭВГ ЕВЫЕ МЕТОДЬ ИНФ0РМАТ1 КИ И ПРОГ.’АМР" РОВАНИЯ 133 обле! чающих разрабол ку готовых к работ е программ. Эти возможности о сража- ются в директивах и макрокомандах Ассемб, lepa. Встроенный Ассемблер не предназначен для написания законченны к программ, поэтом) в нем отс) тел вую г макрокоманды и директивы. Главной особенностью встроенного Ассемблера яв- ляе гея практически полное отсу гсг вне в нем средств описания переменных и данных, т.к. эти объект ы описываются среде гвами Турбо Паскаля. 3.5.6. Оператор ASM Зарезервированное слово ASM от крывает доступ к средствам в< троенного Ассемблера. Этот опера гор может располагали я только внутри исполняемой час- ти npoi раммы (подпрограммы) Область действия оператора A's'vl ограничивается ближайшим по тексту зарезервированным словом END. Таким образом структу- ра любого Ассемблерного оператора такова: asin <Одна или несколько команд встроенного Ассемблера> end; С точки зрения Турбо Паскаля пара asm .. end считается операторными скобками, ограничивающими единственный оператор Паскаля, например: if Х> 10 then asm end el se for k :=1 to 5 do asm end; Тело Ассемблерного оператора asm... end можег быть нусгым или содер- жать несколько Ассемблерных команд. Каждая Ассемблерная команда должна располагаться на отдельной строке или отделя гься от следующей за ней коман 1ы символом «;». Ниже приводятся два разных способа написания одной и той же последовательности Ассемблерных команд: asm mov ah.O; ini $16; mov ChCcdc, al; mo\ ScCode, ah end; asm mov ah. 0 int $ 16 mov ChCode. al mov ScCode. ah end, В конце строки, содержащей единственную Ассемблерную команду, или между двумя командами, располагающимися на одной строке, разрешается вс гав лять комментарий, который должен оформля гься по обычным правилам Т урбо Паскаля, т.е. ограничиваться символами «{», <<}» или «(*». «*)». Таким образом, комментарии разрешены между Ассемб первыми командами, но не внутри них. Например, такой операл ор бу гет правильным. asm
134 Глава 3 Объектно-ориентированное программирование {Инициируем регистры] lea si,X; push ds; popes; {F.S :=DS} lea di.Y; mov ex, 100 cld {Перенос - вперед} rep {Выполняем Y :=X} movsw {Здесь нет ошибки - комментарий можно вставлять между префиксом и командой} end; а такой - неправильным: asm {Готовим регистры} lea si,X; push ds; pop {ES:=DS} es; {Ошибка! Комментарий разорвал мнемонику команды и ее операнд} lea di.Y; mov ex,100 {и направление} eld {Комментарий является разделителем команд, поэтому перед ним можно не ставить ";"}. rep movsw end; В пределах Ассемблерного оператора допускаются любые команды, но Турбо Паскаль требует выполнения следующего соглашения, в начале Ассемб- лерного оператора регистр DS содержит сегмент кода, SS - сегмент стека, ВР - текущий стек, SP указывает на вершину стека. Все эти регис гры должны иметь точно такие же значения к моменту' завершения работы Ассемблерного операто- ра. Программист не должен делать каких-либо предположений о содержимом остальных регистров, и эти регистры могут иметь произвольное значение после завершения работы Ассемблерного оператора. Исключением является случай Ас- семблерной функции, которая должна использовать некоторые регистры для воз- врата своего значения (см. п. 12.2.3). 3.5.7. Синтаксис Ассемблерных команд Ассемблерными командами называются команды на языке встроенного Ассемблера, вставляемые в тело Ассемблерного оператора asm... end. Структура Ассемблерной команды такова: [Метка] [Префикс] [Код [Операнд [.Операнд]]] В квадратных скобках указываются необязательные элементы структуры. Метки Любой команде Ассемблерного оператора может предшествовать одна или несколько меток. В Ассемблере используется два типа меток: глобальные и локальные. Глобальные метки - это обычные метки Турбо Паскаля. Они объявля- ются в разделе описаний после зарезервированного слова Label. С помощью гло- бальной метки можно передать управление в тело Ассемблерного оператора опе- ратором GOTO. Например: Label AltEnt; begin
Bb СОКОУРОВЕ ЕВЫЕ МЕТОДЫ ИНФОРМ АТТ Кй И ПРОГРАММИРОВАНИЯ 135 Goto AltEnd; {Передаем управ пение внутрь Ассемблерного оператора} asm Alt] nd' {Сюда можно пере, ;ать управление извне; end; Локальные метки объявляются непосредственно в теле Ассемблерного опера юра. Эти метки обязаны начинаться символом «@» Поскольку этот символ нельзя использовать в именах Турбо Паскаля, он позволяет отпилить локашную метку от глобальной. Локальная метка не известна нигде вне Ассемблерного опе- ратора. поэтому на нее нельзя передал ь управление оператором GOTO. I Io этой же причине в разных Ассемблерных операторах можно использовать одноимен- ные локальные метки. Префиксы Встроенный Ассемблер поддерживает следу ющие префиксы команд: LOCK Захват шины REP/REPE/RIJ ’NE I [овтор строковой команды REPZ/REPNZ Синоним REPE/REPNE SEGCS 1 Терекрытие CS SEGDS Перекры гие DS SEGSS 11ерекрытие SS SLGES Перекрыт ие ES Префиксы LOCK/REP/REPE/REPNE описаны в п. 12.1.3. Префиксы SEGxx определяют сегментный регистр, который должен использоваться вместо умалчиваемого, и распространяю гея т олько на следующие за ними Ассемблерные команды. Если префикс указан без кода инс грукции, он распространяет свое дейст- вие на следующу ю Ассемблерную коман ду. Код инстру кции очень ре. iko имеет бопее одного префикса и никогда - более трех. Допускается следующая последовательность 1 ,ОСК SEGxx RETxx Гели при обработ ке строковой команды произошло аппаратное прерыва- ние. МП 8086/8088 «забывает » префиксы 1 ОС К и SE G хх, которые, возможно, определены в той же команде, так что использовать сложные префиксные конст- рукции не рекомендуется. Коды инструкций Встроенный Ассемблер воздерживает мнемонику всех команд, перечис- ленных в п. 12.1.3. Кроме того, в Ассемблерных командах может использоваться мнемоника инстру кций процессора 8087, а также коман цы процессоров 80286/80287. Инструкции 8087 допустимы только при активном с тстоянии {SN+}, 80286 - при {SG-Ж а 80287 - в слу чае {SG h,N+}. Операнды Операндами встроенною Ассемблера могут быть выражения состоящие из комбинации регис гров, коне гант, имен и символов операций. Регистры Во встроенном Ассемблере используется мнемоника регистров, указанная в п. 12.1 1, а также имя SI для ссылки на регистры арифметического сопроцессо- ра.
136 Глава 3. Объектно-ориентированное программирование. Константы Ассемблер поддерживает строковые и числовые констант ы. Строковые константы заключаются в апострофы или кавычки. Если кон- станта объявлена с помощью кавычек, внутри нее символ апостроф рассматрива- ется наравне с другими символами, т.е. не считается ограничигелем константы. Точно так же внутри константы, обрамленной апострофами, не считается ограни- чителем символ кавычки. Если внутри констант ы необходимо указать ограничи- вающий ее символ, он удваивается. Примеры: 'Строковая константа' "Это - тоже строковая константа" 'Символ ' не считается ограничителем' 'внутри строки, обрамленной кавычками ". Числовые константы могут быть только целыми, и их значение не может превосходить емкост и двойного слова, г е. должно бы гь внутри диапазона - 2 147 483 648...4 4 294 967 295. По умолчанию при записи числовых констант используется десятичная нотация, но Ассемблер поддерживает также двоичные, восьмеричные и шестна- дцатеричные константы. Двоичная константа составляется как комбинация еди- ниц и нулей, заканчивающаяся символом В (от Binary - двоичный); при записи восьмеричной констан гы использу ются символы 0...7, а в ее конце ставится сим- вол О (Octal - восьмеричный); шее гнадцат еричная констан га записывается по правилам Турбо Паскаля (начинается с символа #), либо по правилам Турбо Ас- семблера: начинается с цифры, в конце с гавится символ Н (от Hexadecimal - ше- стнадцатеричный). Имена Локальные метки - это единственные имена, кот орые ра ^решается опре- делять внутри Ассемблерного оператора. Имена остальных объектов программы - констант, переменных, подпрограмм - должны определяться только с помощью средств Турбо Паскаля. Область определения имен подчиняется тем же правилам, что и в Турбо Паскале -имена должны быть «видны» в том месте, где они используются. Они локализуются в пределах блока, в котором описаны. Во встроенном Ассемблере могут использоваться три предопределенных имени: @@.Сode - текущий сегмент кода @Data - начальный сегмент данных @Result - ссылка внутри функции на ее результа г Имена @Code и @Data могул использоваться только в сочетании с дирек- тивой SEG для ссылки на нужный сегмент. 1 [апример: asm mov ах, SEG ©Data mov ds.ax end; Имя @Result используется для присвоения результата функции. Напри- мер: Function Min(X,Y: Integer): Integer; {Эта функция сравнивает два целых числа и возвращает наименьшее из них)
Высокоуровневые методы информатики и программирования 2э / begin asm mov ах.Х {11омещаем X в АХ} cmp ax.Y {X<Y ?} jl © {Да - на выход} mov ах,Y {11ет - помещаем Y в ЛХ} mov ©Result.ax {АХ содержит результат} end end; Для доступа к полям записей разрешается использование составных имен. Например: type Point - record X,Y: Integer end: Rect = record A,B: Point end; var P: Point; R: Rect; begin asm mov ax.P.X add ax,P.Y mov R.A.X.ax end end. Идентификаторы типов можно применять к операндам для уточнения данных, о которых идет речь. Каждая из следующих команд реализует одно и то же действие: загружает в регистр АХ слово по адресу ES: [DI+4 ]: mov ax.(Rect PTR es:[di]).B.X mov ax,Rect(es:[di]).B.X mov ax,esrRect[di] B.X mov ax,Rect[es:di] B.X mov ax,es:|diJ.Rect.B.X Следующие имена не могут использоваз ься в операндах вс троенного Ас- семблера; • стандартные процедуры и функции (например, WriteLn, Chr); • предопределенные массивы Mem, MemW, MemL, Port, PortW; • константы с плавающей точкой, строковые и множественного типа; • макросы (процедуры и функции, полностью реализуемые одним Ini те-оператором); • символ • ©Result вне функции. Выражения Встроенный Ассемблер использует выражения трех классов: регистровые, ссылки на память и непосредственные.
138 Глава 3. Объектно-ориеь'ироваьное программирование. Регистровое выражение - это выражение, состоящее из имени регистра. Все следующие команды содержат только pei метровые выражения: push ds pop es mov ah.bl add ex,ax 1 [епосредственные выражения - это нетипизированные константы и имена типов. Примеры непосредственных выражений: const dec =10; asm mov ax. dec mov bx,0 add cx,2*dec-ul sub dh - 5 end; Все остальные выражения относятся к ссылкам на память. Например const dec: Word= 10; Step =12; var X,Y: Byte; asm mov ax, dec mov ex, [Step] add ah,X mov Y.bl mov ax,[bx] end; Важным отличием ассемблерных выражений от выражений Турбо Паска- ля является то обстоятельство, что они должны быть статическими, т.е. разреше- ны (вычислены) на этапе создания npoi раммы. Если выражение может быт ь пол- ностью вычислено к моменту его трансляции, т.е. если оно состоит только из ре- гистровых или непосредственных значений, такое выражение называется абсо- лютным; компилятор вычисляет его и использует для создания команды. В ходе компиляции программы вырабатывается, так называемый, объект- ный код, который затем преобразуется компоновщиком в готовую к работе про- грамму. При создании объектного кода компилятор не может вычислить значения выражений типа «ссыпка на память», так как не знает окончательного положения в памяти меток, переменных, подпрограмм В результате он создает. так называе- мое, перемещаемое выражение, которое затем компоновщиком преобразуется в нужную ссылку на память. Встроенный Ассемблер разрешает любую операцию над абсолютным значением (см. ниже), но ограничивает перемещаемые выражения до сложения или вычитания, одним из операндов которою должна быть константа. Другое важное отличие ассемблерных выражений от выражений Т} рбо Паскаля заключается в способе интерпретации переменных. В выражениях Пас-
ВЫ( .OKOyPOBIJBblH Ml "ОД il И> ФОРМА.ИКИ И ПРО1 РАММИРОВАНИР 139 каля любая ссылка на перемени) ю инт ерпретир) ется, как текущее содержимое этой переменной. В Ассемблерных выражениях это справедливо то.ты.о тогда, когда все выражение в целом состоит из имени переменной. Во в.ех ост альных случаях ссылка на переменную интерпретируется как адрес переменной. Напри- мер, выражение х+10 в 11аскале означает «к содержимому переменной > прибавить 10». 11 Ассемблер- ной команде это означает: «к адрес) (смещению) переменной X прибавить 10». Однако команда mov ах,Х означает: «поместить в регистр АХ первые два байта переменной X». Если бы понадобилось за1 рузитъ в АХ адрес переменной X. с тедлвало бы написа гь mov ax.OJ 1'SE Г X Попытка «перехи грить» Ассемблер командами типа mov ах,Х+0 mov ax,X-f 1-1 и т.п. не дает желаемого результата- Ассемблер просто загружает в АХ содержи- мое переменной X. Как и в Паскале, ассемблерные выражения имеют тип, но, в с гдичие от Паскаля, этот тип определяет только размер объекта в памяти и не ограничивает применяемые к нему операции. Встроенный Ассемблер имеет следующие предопределенные типы: 1 ип i Длина в памяти RY ГЕ 1 WORD 2 DWORD 4 QWORD 8 TBYTE 10 NEAR - FAR - Имена предопределенных типов можно использовать для приведения ти- пов выражений. Например, если определены переменные var Flag 1 boolean; X : Word; то такие Ассемблерные выражения недопустимы: mov 1 lag,bx mov ah.X Для корректного задания последней команды можно использовать сле- дующие вариант ы: mov ah.BYTF PTR X mov ah.Byte(X) mov ah.X.] Jyte Во всех случаях в АН буде г загружен первый (м тадший байт переменной X. Встроенный Ассемблер по щерживает операции, перечисленные в следующей таблице (н порядке убывания приоритет а).
140 "лава 3 Объектно ориентированное программирование. 3.5.8. Операции встроенно! о Ассемблера Операция Комментарий & Перекрытие идентификатора 0 Подвыражение _J1 _ . Ссы тка на память . (точка) Селект ор структуры HIGH LOW Доступ к байту в слове + - Унарные операции задания знака Перекрытие сегмен га OFFSET SEG TYPE P1R * / MOI) SHL SHR + - Бинарные операции NOT AND OR XOR Операции нат битами Операция & Осуществляет перекрытие идентификатора: с тедующий за знаком & идентификатор считается определенным в программе, даже если он совпадает с зарезервированным словом. 11апример: vai Ch: Byte; mov ch,0 {Посылаем 0 в регистр СП} mov &С h,0 {Посылаем 0 в переменную Ch] Операция О Круглые скобки используются обычным для Паскаля образом - для изме- нения порядка исчисления выражения (подвыражение, ограниченное скобками, вычисляется в первую очереди). Ес пи i сред скобками с тоит имя типа, все выра- жение приобретает указанный тип. Например: mov ах,((1+2)*3н 4)*5 {АХ - 65} mov bx,l+2* 3+4*5 {ВХ - 27} Операция}] Определяет ссылку на намят ь. Выражение внутри скобок вычисляется в первую очередь. Обычно оно связывается с регистрами ВХ, BP ,SI DI и может использовать операции + и - для указания индексации. Например. mov ah, 100 mov ah,[ 100] {AH = 100} {Загружаем в AH содержимое байт а по адресу DS-100} Операция. (точка) Селектор элемента структуры. Результат - сумма выражений до и после точки с типом второго выражения. Например: var R: record X: Word; У Byte end; mov ax, R. X mov R.Y.al
Высокоуровневые методы информатики и программирования. 141 Операции HIGH и LOW 1IIGH возвращает с гарший, a LOW - младший байт выражения типа сло- ва, следующего за символами операции. Выражение должно иметь абсолютное непосредственное значение. Например: mov al,High $ WOO {AL-$10} Операция : (двоеточие) Указывает Ассемблеру, что выражение после операции должно относить- ся к сегменту, указанному до операции. Результат - ссылка на память со значени- ем второго выражения. Например: mov ах, [10]} АХ = слово по адресу DS: 10} mov ax.BS:| I0J {АХ = слово по адресу BS: 10} Операция OFFSET Возвращает смещение выражения, следующего за операцией. Результат имеет непосредственное значение. Например: mov ах.Х {АХ = слово по адресу переменной X} mov ах,offset X {АХ = смещение адреса X} Операция SEG Возвращает сегмент выражения, следующего за операцией. Результат имеет непосредственное значение. Операция PTR Осуществляет приведение типа. Результат - ссылка на память со значени- ем выражения после операции и типом выражения до операции Например: Function Swap(X: Integer): Integer; {Меняет местами байты в слове X} begin asm mov ах,Х mov BYTE PTR @Result,ah mov BYTE PTR @Result H,al end; end; Операции * и / * - умножение. / - целочисленное деление. Оба выражения должны иметь непосредственные абсолютные значения, такое же значение имеет и результат операции. Например: mov ах.2*2 {АХ - 4} mov ах. 17/3. {АХ = 5} Операция MOD Возвращает остаток от целочисленного деления. Оба выражения должны иметь непосредственные абсолютные значения, такое же значение имеет и ре- зультат операции. Например: mov ах, 17 mod 3 {АХ =2} Операции SHL и SHR Осуществляют логический сдвиг влево (SHL) или вправо (SHR) выраже- ния. стоящего до операции, на количество разрядов, определяемое выражением после операции. Оба выражения должны иметь непосредст венные абсолютные значения, такое же значение имеет и результат операции Например; mov ah, 1 shl 7 {Ah = $80 = 128}
Глава 3. Объектно-ориентированное программирование. Бинарная операция ь Осуществляет сложение двух выражений. Выражения могут быть непо- средственными значениями или ссылками на намят ь, но только одно из них мо- жет быть перемещаемым. Если одно из выражений - ссылка на память результат также определяет ссылку на память, а если одно из выражений - перемещаемое, результат будет перемещаемым. Бинарная операция Вычитание двух выражений. Первое выражение может быть любого клас- са, а второе - должно быть абсолютным непосредственным значением. Результат относится к тому же классу, что и первое выражение. Побитовые операции NOT, AND, OR, XOR Имеют такой же смысл, что и одноименные операции Турбо Паскаля над целыми числами. Оба выражения должны иметь непосредственные абсолютные значения, такое же значение имеет и резу пьтат операции. 3.5.9. Директивы Ассемблера Встроенный Ассемблер не поддерживает никакие директивы, обычно ис- пользуемые в других Ассемблерах, за исключением DB, DW, DD. Структура ди- ректив такова: Dx <константа> [,<константа>,...,<константа>] Здесь Dx - DB, DW или DD; <константа> - Ассемблерная константа или константное выражение. DB определяет цепочку байт, DW- слов, DD - двойных слов. Например: db 'Турбо Паскаль’,13,10 dw 0,$ FFFF, NearProc dd 'ABCD 1,999999999. FarProc В качестве константных выражений разрешается использовать любые Ас- семблерные констан гы со значением, не выходящим из диапазона байта (DB) слова (DW) или двойного слова (DD). В любой директиве можно определять строковую константу, которая приводит к побайтовому заполнению памяти ASCII-кодами символов. Поскольку слово (двойное слово) размещается в памяти, начиная со своего младшего байта, старший (старшие) байт в директивах DW и DD при размещении строкой константы может остаться неопределенным и за- полняется нулем. Например, два следующих объявления эквивалентны: dw '5' dw $35 {$35 - ASCII-код символа '5'} В директивах DW и DD разрешается также указывать имена, которые в этом случае интерпрет ируются как адреса соот ветствующих объектов, причем для DW это - ближний адрес (смещение), а для DD - дальний. Например: dw X {Размещает смещение переменной X} dd Proc {Размещает Г AR-адрес процедуры Proc) Данные, определяемые директивами Dx, всегда размещаются в текущем кодовом сегменте. Разместить таким образом данные в сегменте данных (т.е. оп- ределить константу или типизированную константу) невозможно - для этого ис- пользуются стандартные средства Турбо Паскаля. Более того, директивы не могут снабжаться именами, а поэтому использовать размещаемые с их помощью данные не так-то просто. В следующем примере на экран выводится текстовое сообще- ние. Для этого используется функция 9 вызова ДОС, в соответствии с которой в
Высокоуровневый и в годы информатики и программ и рован ия. 2 j регистрах DS;DX должен содержат вся адрес текстовой строки, а сама строка должна заканчиваться символом «$»: asm jmp ©NextCode {Обходим фрагмент данных} @: db ’Текстовая строка, 13,10.'$' @NextCode: push ds {Сохраняем DS} push cs pop ds {DS = CS} mov dx,OFFSET@ {DS:DX - адрес строки} mov ah,9 {AH - код функции вывода} ini 21 h {Выводим строку} pop ds {Восстанавливаем DS} end; Следует обратить внимание на использование регистра DS В соответст- вии с требованиями функции 9, он должен содержать сегмент выводимой строки. В этом случае строка располагается в кодовом сегмен ге, поэтому необходимо сначала сохранить значение DS в стеке, а затем восс гановить его. Если этого не сделать, то по завершении Ассемблерного оператора oei истр DS укажет на сег- мент кода, и потеряется связь программы Турбо 1 Таскаля с глобальными перемен- ными и константами. 3.5.10. Ассемблерные подпрограммы Ассемблерные подпрограммы - это процедуры и фу нкции, объявленные с директивой Assembler. В таких подпрограммах исполняемая часть не содержит begin... end и состоит из единственного Ассемблерного оператора asm... end. На- пример; Function LongMul(X,Y:Integer):Longlnt; Assembler; asm mov ax. X imul Y {DX/AX содержат "длинный" результат} end; При компиляции Ассемблерных подпрограмм выполняется ряд оптими- заций кода, в том числе: • параметры-значения строкового типа, а также длиной в 1, 2 и 4 байта не копируются во временную память, т.е. внутри подпрограммы они считаются парамет рами-переменными ; • компилятор не создает переменну ю @Result для результата функции, и ссылка на эту переменную в Ассемблерной функции недопустима; исключени- ем являются функции, возвращающие значения строково) о типа - для них разре- шается использовать ссылку на @Result; • генерируются следующие команды на входе в подпрограмму и на ее выходе; push bp {Сохраняется ВР} mov bp,sp {ВР содержит текущую границу стека} sub sp.Locals {Резервируется часть стека для размещения локальных пе-
144 Глава 3. Объектно ориентированное программирование. ременных} mov sp,bp {Восстанавливается граница стека} pop bp {Восстанавливается ВР} ret Params {Из стека удаляются параметры подпрограммы и осуществля- ется выход из нее} Здесь Locals - общая длина в байтах всех объявленных в подпрограмме локальных переменных, a Params - длина (в байтах) всех формальных параметров Если Locals и Params равны нулю, входной код не создается, а выходной содер- жит единственную инструкцию RET. Все локальные переменные Турбо Паскаль размещает в стеке. Это отно- сится как к обычным, так и к Ассемблерным подпрограммам. Для ссылки на ло- кальные переменные используется адресация по базе, задаваемой парой DS: ВР, поэтому при входе в процедуру всегда создается, так называемый, локальный стек: в регистр ВР помещается текущая граница стека, а сама эта граница смеща- ется вверх на суммарную длину всех локальных переменных, чтобы работа со стеком внутри подпрограммы не разрушила локальные переменные. Например: Procedure ...; Assembler; var X Word, Y Byte; asm mov X, ax {Компилируется в mov [BP-2], ax} mov ah,Y {Компилируется в mov ah,| BP-3]} end; Ассемблерные функции должны следующим образом возвращать резуль- тат своей работы: • длиной 1 байт (Byte, Char и т.п.) - в регистре AL; • длиной 2 байта (Integer, Word) - в per истре АХ; • длиной 4 байта (Pointer, Longlnt) - в регистрах D.X (старшее стово) и АХ (младшее слово); • типа Real - в регистрах DX, ВХ, АХ (старшее слово - в DX, младшее в АХ); • вещественных типов Single, Double, Extended, Comp - в регистре ST (0) сопроцессора, • строкового типа - во временной области памяти, на которую ссылает- ся @Result.
Высокоуровневые методы информатики и программирования. ГЛАВА 4. ОСОБЕННОСТИ ПРОГРАММИРОВАНИЯ В ОКОННЫХ ОПЕРАЦИОННЫХ СРЕДАХ Для программирования в оконных операционных средах используется интегрированная среда разработки Integrated Development Environment 1 IDE) IDE позволяет создавать, компилировать, з естировать и редакл ировать проект в еди- ной среде программирования IDE входит в комплект Delphi. Delphi - это грече- ский юрод, где жил дельфи некий оракул. Этим именем был назван новый про- 1 раммный продукт с феноменальными характеристиками. Он удачно сочетает в себе несколько передовых технологий. В процессе работы разработчик выбирает готовые компоненты и проектирует в среде. После выполнения компиляции по- лучают код, который исполняется в 10-20 раз быстрее, чем то же самое, сделанное при помощи ин герпретатора. Delphi включает полный набор визуальных инстру- ментов для скоростной разработки приложений (из готовых компонентов, число которых непрерывно растет даже за счет других фирм). Delphi включает в себя локальный сервер для того, чтобы можно было разработать приложения на любые внешние серверы. Сам Delphi разработан на Delphi. Delphi - это высокопроизводительный инструмент создания приложений. Текущая версия является 32-разрядным компилятором для создания программ, работающих в среде Windows. Дня запуска Delphi требуется Pentium с 32МВ опе- ративной памяти и 15 дюймовый мони гор. 4.1 Структура среды программирования Среда разработки состоит из ряда элементов, которые всегда присутству- ют на экране, а также утилит, которые могут быт ь вызваны из меню или при ра- боте с компонентами. Основные составные части среды программирования Delphi включают: 1. Меню команд Delphi, которое осуществляет функции управления при разработке программ - File (Файл), Edit (Правка), Search (11оиск), View (Вид), Pro- ject (Проект), Ran (Запуск), Component (Компонент), Database (База данных), Tools (Инструменты), Help (Справка). Меню позволяет получить доступ ко всем функциям интегрированной среды разработки Delphi Имеется управление по на- бору “горячих клавиш”. Можно использовать меню для выполнения широкого круга задач: создание форм и модулей, открытия и закрытия файлов, управления отладчиком или настройкой среды программирования. 2. Панели инструментов - меню команд быстрого доступа к командам, содержащее набор кнопок, функции которых эквивалентны наиболее часто упот- ребляемым командам Главного меню Они расположены непосредственно под меню, слева от Палитры Компонентов Если задержать мышь над любой из ико- нок. то появится подсказка. Можно идентифицировать каждую панель с помощью меню View / ToolBars. В группу Панелей инструментов включены: • View (Вид) View Units (Показать модуль). View Forms (Показать форму), Toggle nit/Form (Переключить модуль/форму ). New Form (Но- вая форма); • Debug (Отладка) - Run (Запуск), Pause (Пауза), Trace Into (Шаг в), Step Over (Шаг через); • Standard (Стандартная) - New (Создать), Open (Открыть), Save (Сохра- нить), Save All (Сохранит ь все), Open Project (Открыть проект). Add to
Высокоуровневые методе информатик! и программирования. 147 этого ине гру мента можно увидеть все объекты, методы и переменные, объявлен- ные и используемые в любом выбранном модуле Рис. 4. Главное окно DELPHI с окном формы
148 Глава 4. Особенности пр< раччиювания е оконных огерацисиных сргдах. Рис. 5 Окно ре. >акт ора кода.
Высокоуровневые методы информатикиипрограммирования. 149 4.2. Обзор палитры компонентов В Палитре компонентов отображаются компоненты, содержащиеся в биб- лиотеке компонентов Библиотека компонентов это коллекция компонентов, которую можно использовать при построении интерфейса, а также логической части приложения. Палитра компонентов группирует компоненты в соответствии с выполняемыми функциями и отображает каждую группу на отдельной страни- це. Для доступа на ст раницу дос гаточно шелкнуть на соответствующей закладке. Для выбора компонента надо щелкнуть на его пиктограмм] на странице палитры, а затем щелкнуть внутри окна формы, чтобы помест ить экземпляр компонента на форму. Основная Палитра компонентов Delphi имеет двенадцат ь страниц. Standard. Большинство компонентов на этой странице являются аналога- ми интерфейсных элемен гов самой Windows: меню, кнопки, полосы прокрутки, списки. Набор и порядок компонентов на каждой странице являются конфигури- руемыми. Так, можно добавить к имеющимся компонентам новые, изменить их количество и порядок. Standard | Айкйлзпа! | Win32I System | DataAccess I Data Conhcfc j ADO | InterBase ] Midas | r.T~ri l Рис. 6. Палитра компонент ов с содержимым страницы Standard Стандартные компоненты Delphi перечислены ниже с некоторыми ком- ментариями по их применению. MainMenu позволяет помести гь главное меню в программу. При помещении TMainMenu на форму это выглядит, как просто иконка. Иконки данного типа называют 'невидимыми компонентом", по- скольку они невидимы во время выполнения программы. Создание меню включает три шага: (1) помещение TMainMenu на форму, (2) вызов Дизайнера Меню через свойство Items в Инспекторе Объек- тов, (3) определение пунктов меню в Дизайнере Меню._________ PopupMenu позволяет создавать всплывающие меню. Этот т ип меню появляется по щелчку правой кнопки мыши. I abel служит для отображения текста на экране. Можно изме- нить шриф г и цвет метки, ес ги дважды шелкнуть на свойство Font в Инспекторе объектов. Это легко сделать и во время выполнения программы, написав всего одну' строчку кода.________________ Edit - стандартный управляющий элемент Windows для ввода. Он может быть использован для отображения короткого фрагмен га текста и позволяет пользователю вводить текст во время выполне- ния программы._______________________________________ _ Мето - иная форма TEdit. Подразумевает работу с большими текстами. Я Мето может переносить слова, сохранять в Clipboard фрагменты текста и восстанавливать их и обеспечивает основные функции редактора. ТМето имеет ограничения на объем текста в 32Кб, это составляет 10-20 страниц. (Есть VBX и “родные” компо- ненты Delphi, где этот предел снят)._
150 Г лава 4 Особенности программирования в оконных операционных средах. ок | Button позволяет выполнить какие-либо действия при нажагии кнопки во время выполнения программы. Поместив TButton на форму, по двойному щелчку можно создать загс говку обработчика события нажат ия кнопки. Далее нужно заполнит ь заготовку ко- дом (подчеркнуто то, что нужно написать вручную); Procedure TForml.ButionlCTick(Sender: TObject); begin MessageDIgfAre you there?', mtConfirmation, mbYesNoCancel, 0); End; CheckBox отображает строку текста с маленьким окошком ря- дом В окошке можно поставить отметку, которая означает, что что- то выбрано. Например, если посмотреть окно диалога настроек компилятора (пункт меню Project / Options страница Compiler), то можно увидеть, что оно состоит преимущественно из CheckBox ов. Этот компонент называют также Кнопка с независимой фиксацией. RadicButton позволяет выбрать только одну опцию из несколь- ких. Если открыть диало! Project / Options и выбрать страницу Linker Options, то можно видеть что секции Map file и Linkei output состоят из наборов RadioButton. Этот компонент называют также Кнопка с зависимой фиксацией. ListBox нужен для показа прокручиваемого списка. К гассиче- ский пример ListBox’a в среде Windows - выбор файла из списка в пункте меню File / Open. Названия файлов или директорий и нахо- дятся в ListBox’e. ComboBox во многом напоминает ListBox. за исключением того, 1 что позволяет вводить информацию в маленьком поле ввода сверху ListBox. Есть несколько типов ComboBox, но наиболее популярен выпадающий вниз (drop-down combo box), который можно видеть внизу окна диало! а выбора файла. Ш-Ы Scrollbar - полоса прокрутки, появляется автоматически в объек- тах редактирования, ListBox’ах при необходимости прокрутки тек- ста для просмотра. й GroupBox используется для визуальных целей и для указаний Windows, каков порядок перемещения по компонентам на форме (при нажатии клавиши TAB). Panel - управляющий элемент, похожий на GroupBox. использу- ется в декоративных целях. Я гобы использовать Panel, можно по- местить его на форму и затем положить другие компоненты на него. Теперь при перемещении Panel будут передвигаться и эти компо- ненты. Panel используется также для создания линейки инструмен- тов и окна статуса. j. i b=j RadioGroup “ав гоматизирует” создание набора зависимых пере- ключа гелей RadioButton. ActionList обеспечивает место в приложении, из которого мож- но управлять множеством, сос гоящим из одного или 60 iee методов, ।
Высокоуровневые mi годы информатики и программирования. 1 э J Это полный список объектов на первой странице Палитры компонентов. Для дополнительной информации нужно выбрать на Палитре объект и нажать клавишу F1 - появится Справочник с полным описанием данного компонента. Остальные страницы подробно описаны в Приложении 2. Additional. Эта страница содержит различные дополнительные интер- фейсные элементы: графические кнопки (SpeedButlon); компонент, предназна- ченный для отображения данных в виде таблицы (StringGrid); компоненты, глав- ное назначение которых отображение графической информации - компонент Im- age загружает и отображает растровые изображения; компонент Shape обеспечи- вает формы окружностями, квадратами и т.д.; компонент Chart предназначен для создания профессионально оформленных диаграмм. System. На странице System хранятся компоненты, которые для обеспече- ния своих функций опираются на операционную систему. Страница System также содержит компоненты, обрабатывающие обмен высокого уровня между програм- мами посредством OLE (Object Linking and Embedding). Примером может слу- жить компонент Timer, который выполняет свою фу нкцию за определенный про- граммистом интервал времени. Определение обеспечивает операционная система. Win32. Эта страница содержит компоненты, позволяющие созданным с помощью Delphi программам использовать такие нововведения в пользователь- ском интерфейсе 32-разрядной Windows, как просмотр древовидных структур, просмотр списков, панель состояния, присутствующая в интерфейсе программы Windows Explorer (Проводник), расширенный текстовый редактор и другие. Dialogs. Страница Dialogs предоставляет программам Delphi простой дос- туп к стандартным диалоговым окнам: операций над файлами, выбора шрифтов, цветов и т.д. Data Access и Data Controls. Delphi использует механизм баз данных ком- пании Borland (Borland Database Engine, BDE) для организации доступа к файлам баз данных различных форматов. Компонен гы этих двух страниц облегчают про- граммам Delphi использование сервиса баз данных, предоставляемого BDE, на- пример, многопользовательского считывания, записи, индексации и выдачи за- просов для таблиц dBASE и Paradox. С использованием этих компонентов созда- ние программы просмотра и редактирования базы данных почти не требует про- граммирования. QReport. Эта страница предоставляет компоненты для создания отчетов с информацией из баз данных. Среди них компоненты для отображения статиче- ского текста, значений пилей. а также компоненты для формирования табличных отчетов, отчетов - диаграмм, отчетов - бланков. 4 3. Преобразование данных с форматированием Для форматного преобразования вещественных чисел предназначены функции FloatToStrF и FormatFloat. Функция FloatToStrF Функция Function Float loStrF(Value Extended; Formal TfloatFormat; Precision, Digits: Integer): String; - преобразует вещественное значение Value строку символов с учетом формата Format и параметров Precision - точность и Digits - количество цифр Функция FloatToStrF преобразует вещественное число в его строковое представ тение, однако в отличие от FloatToStr, она позволяет получить изобра- жение числа в различных форма гах. В общем виде обращение к фу нкции выгля-
152 Глава 4. Особенности програгм! ования в иконных or ерацюнных сред/./ ди г так: S : - FloatToStrF(3Ha4eHHa| Формат, Точность Количество! (ифр); где s - строковое представление числа Значение; Значение - число, изображение которою надо получить; Формат - именованная константа, определяющая вид строки s; Точность — определяет точность представления преобразуемого числа. Значение Точность должно быть равно 7 или меньше для типа Single, 15 или меньше - для типа Double, 18 или меньше - для типа Extended. Значение Количе- ствоЦифр зависит от используемого формата. Правила использования параме гра форматирования функции Float! с StrF приведены в таблице 3. Таблица 3 Константа Форма г ffGeneral У ниверсальный формат, использующий наиболее удобную для чтения форму представления вещественного числа.Число изображается с деся гичной точкой, если количество цифр слева от точки меньше и ти равно заданной т очности или если число больше или равно 0,00001. В противном случае число изображается в “научи ом формате” и парамет р Количеств''Цифр задает количест во цифр экспонен гы. ffExponent Научный формат. Число изображается в виде d.ddd.. .Esddd, где s-знак «плюс» и tn «минус»; d - десятичная цифра Обще коли- чество цифр числа, включая число перед. МеШг^Р&л 3 равно заданной точности. I (араметр Количест вбЦифр задает минимальное количество предс гав тения экспоненты (0..4). ffFixed Формат с десятичной точкой. Число преобразуется к виду: ddd ddd... Если число отрицательное, то строка, являющаяся изображением числа, начинае гея знаком «минус». Перед деся- тичной точкой всегда находится как минимум одна цифра. ] 11- раметр КоличествоЦифр задает количество цифр после де- сятичной точки (0..18) Если количество цифр целой части больше, чем заданная точность, го число изображается в науч- ном формате. ffN umber Чис. твой формат. Числовой формат похож на формат с деся- тичной точкой fffFi xed). только в изображении числа использу- ется разде гите гь групп ра грядов. Например, число 12345.6 бу - дет изображено так: 12 345,6. ffCurrency Денежный формат. Используемые в изображении числа в денежном форма ге разделитель целой и дробной частей, разделитель групп разрядов, июбражение денежной единицы определяются настройкой Windows (вкладка Денежный фор- мат свойс гва Язык и стандарт ы панели управления). Параметр КоличествоЦифр задает количество цифр после десятичной точки. Функция FormatFloat Функция Function FormatFloat, Format: String; Value: Extended): String- - преобразует вещественное значение Value строку символов с учетом спецификатора формата Format. ] тараметр Format в функции FormatFloat м эжет содержать спецификаторы форма гированля вещественных чисел указанные в таблице 4.
Высокоуровневые методы информатики и г poi раммирования. 153 Таблица 4. Спецификатор Значение 0 Определяет поле для цифры. Если форматируемое число не имеет значащую цифру, выводится 0 То же, но если форматируемое число не имеет значащую цифру, ничего не выводит ся. I Юле для разделителя целой и дробной част ей числа. Поле для раз, юлителя ть сяч. Разделитель спецификаторов формата для положительно! о, отрица геленого и нулевого числа. Е+,е+,Е-,е- При шак представления числа в научном формате. Спецификаторы Е-r, е+ предписывают выводить знак <- перед неотрицательным деся г»- чным порядком. 4.4. Ввод данных Исходные данные необходимы для работы подавляющего большинства программ. Программа может получит ь исходные данные из т рех источников: ок- на ввода, полей ввода диалогового окна или из файла. Ввод из окна ввода Ввод данных из окна ввода осуществляется вызовом стандартной функ- ции InputBox, возвращаемым значением которой является строка, введенная пользователем. В общем виде ввод данных с использованием функции InputBox выглядит так: <'Переменная> := 1пршВох(Заголовок, Подсказка, Значение г где 1 временная - идентификатор переменной строкового типа, значение которой должно бы гь по >учено из окна ввода. Заголовок - текст за: оловка окна ввода; Подсказка - текст поясняющего значения; Значение - текст, находящийся в поле ввода в момент появления окна ввода на экране. Напри мер, в программе вычисления площади поверхности шара ввод ве- личины радиуса г ара может выглядеть так; S := 1прщВох('Вычисление площади повсрхносги i тара', 'Введите рд щус шара мм ''); Выполняется ввод значения следующим образом. На жран выводится диалоговое окно вьода (рис. 7). Рис. 7. Диалоговое окно, гпя ввода значения радиуса шара 11осле то1 о, как в попе вво, ia будет введено (набрано на клавиагу ре) число и выполнен щелчок на одной из командных кнопок окна ввода, ОК или Cancel, переменная s получит значение: введенную строку, если щелчок был на кнопке ОК, или, если щелчок был на кнопке Cancel, предопределенное значение, у ка 5ан- ное при вызове функции InputBox в качес гве ее аргумента.
154 Гг два 4. Особен юсти гры рамми°ования в оконн- х операции ных ср1 д \х Следует иметь ь виду, чго значение функции Input Box строкового (string) типа. Поэтому, если программе требуется получить значение числового, типа, то введенная ст рока до тжна быть преобразована в чис го при помощи соответст- вующей функции преобразования. Например, если в программе переменная г ве- щественного (real) типа, то опера горы, обеспечивающие ввел ее значения, мог т выглядеть так: 5:=1прЩВох(‘Вычисление площади поверхности тара’, ’Введите радиус ша- ра,мм’,”); г := StrToFloat(s); Ввод из поля редактирования Для ввода из поля редактирования надо поместить на форму экземпляр компонента Edit страницы Standart палитры компонентов. Чтобы добавить ком- понент, надо в палитре компонентов на странице Star dan щелкнуть на пикто- грамме нужного компонен га (Edit) и затем щелкнут ь кнопкой мыши в той т очке формы, где до. 1жен находит ься правый верхний yi ол компонент а. В результате в форме появится экземпляр компонента 1 .dil 1 стандартного размера. Ввод данных из п зля редактирования осу ществ тяется обращением к свой- ству Text этого поля, т.е. Edit 1.1 ехт. На рис. 8 приведен вид диалогового окна программы с полями ввода значений для табулирования функции. Табуляции Функции Введите- альног srwMSHH'exo I--- “--------- конечное значение Чт J к<-><,нчест»о‘,очек n J I . Рис. 8 Пример диал эгового окна с полями ввода редактирования Следует иметь в виду, что свойство Техз представляет собой строку. 11о- этому, если программе требуется получить значение числового типа, то введенная строка должна быть преобразована в число при помощи сооз вез с гвующей функ- ции преобразования. 4.5. Вывод данных Вывести результат программа может в окно сообщения, в поле вывода диалогового окна, в файл и на устройство печаз и (прия гер). Вывод в окно сообщения Вывод в окно сообщения может быть выполнен вызовом процедуры ShowMessage или функции MessageDlg. 11роцедура ShowMessage позволяет вывести я т экран прос гое диалоговое окно с текстом и одной командной кнопкой. В общем виде вы юв процедуры ShowMessage выглядит так: ShowMessage (Сообщение), где Сообщение - выра- жение строково1 о типа. Например, на рис. 9 вид окна сообщения, выводимо! о процеду рой Show- Мс5Е^е("Площадь шара=' + s ч ’кв. см').
ВЫСОКОУРОВЧЕВЬР МЕТ ОД11 ».Н t>OPMA ПК,I И ПРОГРАММИРОВАНИЯ. 155 Рис. 9 Отображение результат ов в окне сообщения Заголовок окна сообщения, выводимого процедурой ShuwMessage, по умолчанию совпадает с именем исполняемого файла приложения. Функция Me ;sageDlg позволяет сопрово щть сообщение одним из с~ан даргных значков Windows, например, значком «Внимание», задать количество и тип командных кнопок. На рис. 10 призеден вид окна сообщения, полученного в результате выполнения оператора вызова функции: S := MessageDlgCl 1араметр "Количество точек" не может быть пустым', mtlnformation, |mbOK], 0). Функция MessageDlg возвращает результат - число, проверив значение которого можно определить, выбором какой командной кнопки был завершен диалог. Обращение к функции MessageDlg вы: лядит так: <Выбор'> := MessagcDtgfСообщение, 3 ип, Кнопки, Контекст справки); где Сообщение - текст (содержание) выводимого сообщения: Тип - зго тип (вид) сообщения. 1 'ис. 10. ] 1ример окна сообщения Сообщение может бы гь информационным, предупреждающим, сообще- нием об ошибке. Тип сообщения задается именованной константой. В таблице приведены именованные константы, определяющие тип сообщения, выводимого функцией MessageDlg. Значения именованных констант определяющих тип со- общения, выводимого функцией MessageDlg (см. табл. 5) Таблица 5. Констант а 1 ип сообщения и значок mtWarning Внимание, черный восклицательный знак в желтом греу сольнике mtError Ошибка, белый крест в красном круге mtlnformation Информация, синяя латинская i на бе том фоне mtconfirmation Запрос подт верждения, шах вопроса в а белом фоне mtC i stem 11 эльзовательское, сообщение без значка
156 Г IAEA 4 OCQEEt НОСТИ ПРОГРАММИРОВАНИЯ Е ОКОННЫХ ОСЕРАЦИОННЫХ СР ДАХ. Кнопки - список, задающий число и вид кнопок и состоящий из несколь- ких разделенных запятыми именованных консташ, записанных в квадратных скобках. Перечень констант, которые могут быть использованы: mbYes, mbNo, mbOK, mbCancel, mbHelp, mbAbort, mbRetry, mblgnore. mbAll, mbOkCancel, mbYesNoCancel, mbAbortRetry Ignore. ) {азвания коне гант содержат информацию о текстах на кнопках. Например, чтобы в окне сообщения были кнопки ОК и Can- cel список Кнопки должен быть таким: [mbOK, MbCancel] или [mbOKCancel]. КонтекстСправки - определяет номер экрана справочной системы, кото- рый появится при нажатии на клавишу <F1> в тот момент, когда окно сообщения находится на экране. Если использование справочной системы не предусмотрено, то при вызове функции MessageDlg в качестве параметра КонтекстСправки дол- жен быть указан ноль. Выбор - значение, возвращаемое функцией MessageDlg после щелчка на одной из кнопок. Определить, на какой из кнопок был выполнен щелчок, можно с помощью именованных констан г, идеи гифицирующих нажатую кнопку: mrAbort, mrYes, mrOk. mrRetry, mrNo. mrCanceL mrlgnore, mrAll. Вывод в поле диалогового окна Часть диалогового окна, предназначенная для вывода информации, назы- вается полем выво, ia или полем метки. Для вывода в поле диалогового окна надо поместить на форму экземпляр компонента Label страницы Standart Палитры компонентов. Добавить к форме компонент нужного размера можно следующим образом. После щелчка на палит ре компонентов нужно помест ить курсор мыши в ту точку формы, где должен находиться левый верхний угол компонента, нажать кнопку мыши и, удерживая ее нажатой, переместить курсор в точку, где должен быть нижний угол компонента, затем отпустить кнопку мыши. В форме появится компонент нужного размера. Вывод данных в поле метки осущес гвляется об- ращением к свойству Caption этого поля, т.е. Label 1.Caption, которое является пе- ременной строкового типа. Например, чтобы в поле вывода появился текст доста- точно написать: Label 1.Caption := 'Значение функции равно ' + Float! oStr(y); 4.6 Программирование в DELPHI При программировании в Delphi основная работа заключает ся в ра зработ ке подпрограмм. Задачу организации взаимодействия разработанных подпрограмм берет на себя Delphi. В языке Object Pascal основной npoi раммной единицей яв- ляется подпрограмма. Различают два вида подпрограмм: процедуры и функции Отличие функции от процедуры заключается в том, что с именем функции связа- но значение, поэтому имя функции можно использовать в выражениях. Структура процедуры Процедура начинается заголовком, за которым следуют разделы: описа- ния констант, описания типов, описания переменных и раздел операторов. Опи- сание процедуры выглядит так: Procedure <Имя процедуры^ (Список параметров); Const { описания констант ) Туре { описания типов } Var { описания переменных } Begin { раздел операторов }
ВЫСОКОУРСВНЕЕЬ 2 МЕТОДЫ i.riOOP 4А1.ЖИ и ПЮГ нА* МИЛОВАНИЯ. 157 End; Загс ювок процедуры состоит из слова Procedure, за которым следует имя процедуры. Если у процедуры есть параметры, то они указываются после имени процедуры в скобках. Завершается зато ювок процедуры символом «точка с запя- той». Если в процедуре используются именованные константы, то они объяв- ляются в ра аде ie объявления коне гант, ко горый начинается ключевым сл эвом Const, е ai [ример: Const Size - 100; Mess - 'ошибка ввода'; За разделом констант следует раздел описания типов, начинающийся сло- вом type Стандартные типы данных не требуют описания (Real, Integer. Boolean. Char. String) Требуется описание типов, которые создаются пользователем. На- пример: Type Day = I ..31: {Тип - диапазон (интервальный)} TColors = (red. white, I >lue); {Перечис тимый тип} После раздела описания типов следует раздел описания переменных, в котором объявляются все переменные, используемые в процедуре. Раздел описа- ния переменных начинается словом var, например: Var I, J, N- Integer, S: String[5]; Раздел операторов начинается словом begin и заканчивается словом end, за которым следует символ «точка с запятой». В разделе операторов располага- ются опсрат эры, которые выполняются последовательно друг за другом. Структура функции Функция начинается заголовком, за которым следуют раз целы: описания констант, описания типов, описания переменных и раздел операторов. В общем виде описание функции вьпл ядиттак: Function <Имя функции> (Список параметров): < Тип результата:*; Const { описания коне ган г} Туре { описания типов } Var { описания переменных } Begin i раздел операторов } End; Заголовок функции начинается словом Function, за которым через пробел следует имя функции. 11осле имени функции, в скобках, указывается список па- раметров. за которым через двоеточие указывается тип значения фу нкции. Завер- шается заголовок процеду ры символом «точка с запятой ». В разделе операторов помимо переменных, перечис. юнных в разде ie объявления переменных, можно использовать локальную переменную Result, ко- торую не нужно объявлять. 1то завершении выполнения операторов функции, значение этой переменной становится значением функции, поэтому среди опера- торов должен быть оператор присваивания значения переменной Result. Напри- мер, функция вычисления площади поверхности шара. Function Place(n: integer); real, begin Result:- 4*PI*Sqr(n)/100; end; Обращение к функции: s : = 1 ’lace(rad); где использованы переменные s - переменная типа real для сохранения значения площади, rad - типа Integer дня значенья радиуса.
158 Глава Ь Технология создания программ в ср ;де DEI PHI. ГЛАВА 5. ТЕХНОЛОГИЯ СОЗДАНИЯ ПРОГРАММ В СРЕДЕ DELPHI В среде Delphi работа выполняется с проектами. Проект это набор фай- лов. используя которые компилятор создает файл исполняемой программы. В проект включаются: • Файлы форм, служащие для сохранения информации о внешнем виде форм, являющиеся графическими представлениями приложения, со- держащие свойства форм и компонентов, включенных в формы, и имеющие расширение .dfm; • Файлы с исходным текстом модулей, которые содержат тексты проце- дур, функций, описания типов и прочую информацию, необходимую компилят ору для создания исполняемой npoi раммы, и имеют расши- рение .pas; • Главный модуль приложения, который формируется средой Delphi, содержит общее описание проекта и связывает вместе все фай 1ы, из которых состоит приложение; главный модуль проекта называет ся файлом проекта и имеет расширение .dpr. Доступ ко всем перечисленным модулям проекта обеспечивает Менеджер проектов (команда главного меню View/ Project Manager) Любое приложение, разрабатываемое в среде Delphi, имеет, по крайней мере, еще несколько вспомогательных файлов, которые можно удалить без риска, так как они moi ут быть восстановлены при компиляции. 5.1. Структура простого проекта Для каждого приложения может быть только один файл проекта. По умолчанию проект имеет название Project!. Фай . проекта содержит инструкции, с которых начинается выполнение программы. ФаГ i проект а имее г расширение .dpr. Чтобы уви теть текст главно! о моду ля i [риложения, надо выбрать в i гавном меню View/ Projecl Source. Н. же приведен текст главного модуля программы Prog, am Projecl 1; Uses ] orms, Unitl in‘Unitl.pas’ {Foiml}; {$R * RES) Begin ApplicationJnitialize; Application.CreateForm( Fforml, 1 orm 1 j Application.Run; End. Начинается главный модуль словом Program, за которым с педует имя про- граммы, совпадающее с именем проекта. Имя программы задается программистом в момент сохранения файла проекта, и оно определяет имя соз таваемого компиля- тором исполняемого файла программы. Да тее за словом Uses, еле, 1утот имена ис- пользуемых модулей: библиотечного моду ля Forms и модуля формы. Похожая на комментарий директива f$R *.RES] указывает компилятору, что нужно использовать файл ресурсов, который содержит описания ресурсов
ВЫСОКОУРОЬНЕВь t Ml *ДЫ ИНФОРМАТИКИ И TPOI РАММИРОВАНИЯ. 159 приложения, например, пиктограммы. Звездочка показывает, что имя файла । к - сурсов такое же, как и у файла проекта, но с расширением .res. Выполняемая часть главного модуля находиться между инструкциями Begin и End. Инет рукции исполняемой част и обеспечивают инициализацию при- ложения и вывод на экран стартового окна. Помимо главного модуля, каждая программа включает в себя как мини- мум один модуль формы, который содержит описание формы приложения и под- держивающих ее работу процедур. В Delphi каждой форме соответствует свой модуль с расширением .pas с исходным кодом программы. Модуль состоит из нескольких разделов. Каждый раздел начинается клю- чевым словом и продолжается до начала следующего разде ia. UnitUnitl; 'Имя модуля} Interface {Раздел интерфейса} Uses {Список библиит ечных модулей.} {используемые про раммой} Windows, Messages, SysUtils, Classes, Graphics, Controls, 1 orms, Dialogs, StdCtrls; Type {Описание типов, сформированное Delphi] TForm I = Class(TForm) Private { Объявление переменных типа Private } Pul 'lie { Объявление переменных типа Public } Var {Описание переменных, доступных для других модулей приложения] Fonnl: Tforml; Implementation ] Раздел реализации] {$R *.DFM} End. Начинается .модуль еловом Unit, за которым следует имя модуля. Имя именно это модуля. Именно это имя упоминается в списке используемых мэдулей в инструкции Uses главного модуля приложения, текст которого был приведен выше. Сост оит модуль из трех разделов: интерфейса, реализации и инициализа ции. Раздел интерфейса (начинается словом Interface) сообщает компиля гору, какая часть модуля является доступной для других модулей программы. Здесь перечислены используемые модулем другие библиотечные модули, находится сформированное Delphi описание формы (типа), которое следует за словом Туре. Раздел реализации (начинается словом Implementation) содержит объяв- ления локальных переменных, процедур и функций, поддерживающих работу формы. Начинается раздел реализации директивой {$R *.DFM1. указывающей компилягору, чго в раздел реализации надо вставить инструкции установки зна- чений свойств формы, которые находя гея в файле с расширением D1 М и генери • руется Delphi на основе внешнего вила формы. За директивой {$R *.D1 М} следует описание процеду р обработки собы тий формы. Сюда же программист может поместит ь описание своих процедур и функций, ко горше могут вызваться из процедур обработки отбытий.
160 ГЛАВА 5. ТЕХНОЛС ТЕ СОЗДА> ИЯ ПРОГРАММ В CPI Д' DELPHI. Раздел инициализации позволяет выполнить инициализацию переменных модуля. Инструкции раздела реализации надо располагать после раздела реализа- ции, между begin и end. Если раздел инициализации не содержит операторов (кат в приведенном примере), то слово begin не указывается. Следует отметить, что значительное количество операторов модуля запи- сываются Delphi, например, Delphi, анализируя действия программиста по созда- нию формы, формирует описание класса формы. 5.2. Технология разработки приложения Delphi относится к системам визуального программирования, поэтому разработка приложения в De.phi сосл оит из двух этапов: создание интерфейса и определение функциональности. При этом понятие интерфейса определяется как способ взаимодействия по гьзователя и приложения, то есть внешний вид форм при выполнении приложения и то, каким образом пользователь управляет прило- жением. Примером пользовательского интерфейса являет ся интерфейс среды раз- работки программ любою стандартного приложения Windows. Интерфейс при- ложения составляют компоненты, которые разработчик выбирает из палитры компонентов и размещает их на форме. При конструировании интерфейса прило- жения действует принцип WYSIWYG (What You See Is What You Get - Что види- те, го и получи те). Процесс со здания прил скений в среде 1 Jelplti можно разделить на шаги: • построение интерфейсной части (установка свойств главной формы расположение на ней интерфейсных i омпонентов, выбранных из па- литры, и задание их свойств с помощью Инспектора объектов: тести- рование интерфейса); • написание кода обработчиков событий; • компиляция программы - преобразование исходной программы, напи- санной на языке программирования в машинный код, т.е. на язык ко- манд процессора. Для демонстрации возможностей Delphi и технолог ии визу ального проек- тирования разрабол аем программу вычисления значения фу нкции. Пример 7. Вычислить объем шара в куб. см. Радиус шара ввесл и с к гавиал уры в мм. Разработать программу, в которой предусмотрены: - ввод радиуса R с клавиатуры; - вычисление объема шара по формуле V = 4tcR3/3; - вывод резульгал а Проектируелся инлерфейс: ввод значения R осуществляется из поля вво- да, вычисление и вывод резу. штата - по нажатию кнопки “Вычислить”. Работа над новым приложением, так в Delrhi называется ра срабатываемая программа, начинается с создания нового проекта. Для этого нужно в главном меню выбрать пункл File и в нем - New Application. В окне проекл ировщика форм появится новая форма. Из нее создается с тар говая форма приложения - окно, ко торое появляется при запуске приложения. 5.3. Форма приложения Стартовая форма создастся путем изменения свойств формы Foi ml. С вой- ства формы определяют ее внешний вид: размер положение на экране, текст за-
Вэ1С0К0УР0ВНЕВЫЕ МЕТОДЫ ИНФОРИАТИКИ 1, ПРОГРА" МИРЭВАКИЯ. J головка, вид рамки. Свойства перечислены на вкладке Propenies (свойства) окна Object Inspector. В левой колонке находятся имена свойств, в правой - их значе- ния. Сначала надо изменить значение свойст ва Caption (зап .ловок) — заменить Form 1 на Вычисление объема шара Для этого щелкнут ь мышью в поле Caption. В результат е л ого в правой колонке, где находиться текущее значение свойства - текст Formi. появляется курсор. Использтя клавишу <Backspace>, надо удалить Form 1 и ввести ‘ Вычисление объема шара”. Аналогичным образом можно установить значения свойств Height и Width, которые определяют высоту и ширину формы. Этим свойствам надо при- своить значения 341 и 456. При выборе некоторых свойств, например, Coloi (цвет), которое опреде- ляет цвет фона формы, после значения свойст в выводи гея значок выпадающего списка. В результате щелчка на нем появляется список допустимых значений свойства, и j когоро! о можно выбрать нужное значение. Помимо обычных свойст в, у объект ов, в том числе и у формы, могут быт ь вложенные свойства. Пере, i именем вложенного свойства стоит значок "плюс". При двойном щелчке на имени виженного свойства раскрывается список уточ- няющих свойств, а значок “плюс’ меняется на “минус”. В поле значения свойства Font расположена командная кнопка с тремя точками, при нажатии на которую появляется стандартная диалоговое окно Win- dows выбора шрифта и его свойств. большинство свойств определяют внешний вид формы. Свойст во Name определяет имя формы, оно используется в npoi рамме для управления формой Таблица 6 Свойства Обозначение Значение Имя формы Name Formi 3ai оловок С aption Bi । числение объе- ма шара Горизонт альная. координата ле- вого верхнего угла Left 192 Вертикальная координата левого верхнего угла Top 121 Высота Height 341 Ширина Width 456 Шрифт Font.Name Arial Размер шриф га Font Size 10 Выше, в табл 6, приведены и гмененчые свойства формы ра щабатываемо- го приложения Остальные свой :т ва формы оставлены без и 1менения и в таблице нс приведены. Свойства Left, Top. Height, Width обычно определяются визуально при выборе расположения формы или компонентов на форме. Таблица содержит значения вложенных свойств: Name и Size. 11еред име- нем вложенного свойства указывается имя свойства его вмещающего Font.
162 Гг аза 5 Tlx юлогия созда! hi программ е ср д. DElPhI. 5.4. Компоненты формы Прсирамма Вычисление объема шара должна подучить от пользователя исходные данные - значение радиуса. В Windows данные с клавиатуры вводятся е поля редактирования. Поэтому в данную форму надо добавить компонент по ie редактирования. Ч гобы добавит ь компонент, надо в палитре компонен гов на странице Standart щелкнуть на пиктограмме нужного компонента (Edit) и, затем, щелкнут ь кнопкой мыши в той точке формы, i де должен находиться правый верхний угол компонента. В результате в форме появится экземпляр компонента Editl стан- дартного размера. Компонент формы, окруженный восемью маленькими квадрат иками. на зывается выделенным (маркированным). Свойства маркированного компонента отображаются в окне Inspector Ooject. В табл. 7 представлены основные свойства компонента, называемого полем редактирования. Таблица? Свойство Обозначение Значение Имя поля. Используется в программе для дос- тупа к содержимому (тексту) поля Name Editl Текст, находящийся в поле ввода- редактирования Text Расстояние от левой границы поля до левой гра- ницы формы Lefi 192 Расстояние от верхней границы поля до верх- ней границы формы Top 64 В лсота поля Heighl 24 Ширина поля Width 121 Шрифт, используемый для отображения вводи- мого текст а Font I [ризнак наследования свойств шрифта роди- тельской формы ParentFont 1 ак же, как свойства формы, свойства компонента можно и вменить в окне Object Inspector. Чтобы свойст ва требуемого компонента появились в данном ок- не, надо маркировать нужный компонент или выбра гь ei о имя из раскрывающе- гося списка объектов, кнопка раскрытия которого находится в верхней части Ob- ject Inspector. Помимо поля редактирования, окно формы должно содержа гь пояс- няющий текст, краткое информационное сообщение. Текст, находящийся в фор- ме, называется меткой. Добавляется метка к форме точно так же, как и поле ре- дактирования. Пиктограмма метки (большая буква А) находится в палитре ком- понентов на странице Standart перед пиктограммой поля редактирования Компо- нент метки называется I abel. После того, как метка добавлена, можно, используя окно Object Inspector, и 5менить ее свойст ва К форме разрабатываемого при юже- ния надо добави гь две метки. В табл 8 приведены значения свойств компонентов метки Label 1. Если свойство AutoSize (автоматический подгон размера) имеет значение
Высокоуровневые методы информатики и п°ог >амм рования 163 True, то Delphi автоматически устанавливает размеры метки в зависимости от ко- личества символов текста метки, используемого шрифта и его размера. Если надо, чтобы метка представляла собой т екст из нескольких строк, то свойству AutoSize надо присвоить значение False, а значению Wordwrap (перенос слив) - True и вручную ус сановит ь значения свойсл в, определяющих ее размер. Таблица 8 Название свойства Значение свойства Name Label 1 С aption Введите значения R: AutoSize False Top 64 Left 40 Height 16 Width 142 Wordwrap True В завершение к форме надо добавить командную кнопку, при щелчке на которой будет выполняться вычисление значения функций Кнопка дополняется в форму точно так же, как и другие компоненты. Пиктограмма командной кнопки, в виде кнопки ОК, находится на палитре стандартных компонентов и называется Button После добавления кнопки с помощью диалогового окна Object Inspector надо установить требуемые значения ее свойств, которые пре к гавлены в таб I. 9 Таблица 9 Название свойства Значение свойства Name Button 1 Caption Вычислить Top 104 Left 192 Height 25 Width 121 На рис. 11 представлен вид среды разрабо гь и интерфейса npoi раммы и вид формы при поженив после выбора компонентов и установки свойств в окне проектировщика фор*- Цифрами обозначены элементы: 1 - окно формы с компонентами и мар- кированным компонен гом 11оле редактирования; 2 - окно инспектора объектов, в котором на вкладке Properties указаны свойства Д1я выделенного компонента F.dil 1; 3 - окно редактора кода; 4 - компонент 1 .abel (Метка); 5 - компонент Поле редакл ирования Edit: 6 компонент Кнопка Button (указанные компоненты нахо- дятся на странице Standari палитры компонентов): 7 - кнопка для запуска компи- ляции пр< п раммы.
7 А 5 6 Ch < - f r '.jfcCtZ j 0|e Edit aAjtrrh "“A. E^ojpc* Run Oontpohaint £tyaDasfe\Ton|s Workgroup' 'nfoPow“' b°lp " Winjys.] rvstem I 'nternetl L'ata Acp | ba a’jontrois | м.лаь | b&cisidi .ij |x £ -1 - -a^eew» Рис. 11. Вид среды разработки приложения bcntl rbait ^roperttns |:£ v.erts | ♦Anchors^ — Asutnbeleci Г tie/-, ,nutoSi7E Pete BiD'Mode odLeftToRii BOrderStyic b“S ingle Cha- ass ecN'jrmdi CjIcz clWindow *гОп®ч'а1Г'»9 fTSi7ef'nns CSI3D Пне Cursor c'Defadlt rragCursbr ert/ag dOragKind dkOrag DragModr- dciM пи-1 Erablfed True (TFerrt Height j 24 HefpContext 0 ^ideSelscfidTue a^ieMode imdohtcare .Ihterslanife 'g"' h о tf ,zL*i Введите радиус, мм | Вычисление объема шара Render: TObject) ; private public { Public declarations J end. IF T Mcdmed j|nsprt Вычислить g|Ls, Classes, Graph Глава 5. ~гехнолсп я соз„а мя прл рамм в оцт DELPHI.
Высокоуровневые методы информатики и программирования. 165 5.5. Событие и процедура обработки события Вид созданной формы подсказывает, как работает приложение Очевидно, что пользователь должен ввести значение R в поле редактирования, затем щелк- нуть по кнопке Вычислить. Щелчок на изображении командной кнопки - это пример того, что в Windows называется событием. Событ ие - это то, что проис- ходи г во время работы приложения. В Delphi у каждого события есть имя, напри- мер, щелчок кнопкой мыши - это событие OnClick. Реакцией на событие должно быть какое-нибудь действие. Например, реакцией на событие OnClick, произо- шедшее на кнопке Вычислить, должно быть вычисление функции. В Delphi реак- ция на событие реализуется как процедура обработки события. Таким образом, задача программиста состоит в написании необходимых процедур обработки со- бытий. Методику создания подобных процедур можно рассмотреть на примере процедуры обработки события для кнопки. Сначала следует маркировать объект, для которого создается процедура обработки события, - это командная кнопка. Затем выбрать вкладку Events (события) окна Object Inspector. В результате этих действий в окне появиться вкладка со списком событий, которые способен вос- принимать маркированный компонент, в данном случае - командная кнопка. В левой колонке вкладки перечислены имена событий, на которые может реагиро- вать маркированный объект. Если для события определена процедура обработки события, то в правой колонке, рядом с именем события, выводится ее имя. Чтобы создать процедуру обработки события надо сделать двойной щелчок в поле име- ни процедуры обработки события. В результате открывается окно редактора кода (в Delphi кодом называется текст программы) с макетом процедуры обработки собы гия. Delphi автоматически присваивает процедуре обработки события имя. Имя процедуры обработки события состои г из двух частей. Первая часть идеи ги- фицирует форму, которой принадлежит объект. для которо! о со шается процедура обработки события. Вторая часть имени идентифицирует сам объект и событие. В данном случае имя формы - Form 1 Button 1 - имя командной кнопки Вычислить, а имя события - Click. В окне редактора кода, между begin и end, можно написать операторы Object Pascal, реализующие процедуру обработки события Переклю- чение между окном проектирования формы и окном Редактора кода производится нажатием клавиши F12 Ниже приведен текст процедуры для события OnClick на кнопке Вычислить. Procedure TForm LButtonlChck(Sender: TObject); Begin r := Str! oFloat(Editl .text); v := (3/4) * pi * IntPower(r, 3)/l 000; Show Message(‘O6beM шара V -' + Float! oStr(v) -t # 13 +' радиу c = ' + FloatToStr(r)); End: Исходные данные программа получает из поля редактирования Editl. об- ращением к свойству Text. Свойство Text содержит строку символов, поэтому, для преобразования числа в число в процедуре используется функция StrToFloat. Для вычисления значения используются функции IntPower - целочислен- ная степень и Power - степень с произвольным показателем. Для того, чтобы под- ключить эти функции в программу, требуется дополнить список используемых модулей модулем Math, содержащим математические функции.
166 Глава 5 Технология создания г рограмч в среде DELPHI Вывод вычисленного значения программа осуществляет в окно сообще- ния Для этого вызывается функция ShowMessage, в качестве параметра которой указана строка с сообщением о результатах вычисления. При этом для преобразо- вания числа в строку используется функция Float loSli. Для вывода текста в не- сколько строк используется функция Chr, которая возвращает символ «Новая строка», код которого равен 13. 5.6. Редактор кода DELPHI Редактор кода Delphi автоматически выделяет ключевые слова языка про- граммирования Object Inspector (Begin, End, Procedure. Const, Var и др.) полужир- ным, что делает текст программы более выразительным, облегчает восприятие структуры программы. Кроме ключевых слов, редактор выделяет комментарии. Как только про- граммист напечатает символ начала комментария, открывающую фигурную скоб- ку, тогда текст, стоящий после этой скобки, меняет свой вид. После того, как про- граммист поставит закрывающую скобку коммен гария, текст, находящийся после этой скобки, приобретает обычный вид. Исходный код программы: Unit Unitl; Interface Uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms. Dialogs, StdCtrls, Math; Type TForm 1 = class(TForm) Label 1: TLabel; EditLTEdit; Button!: fButton; Procedure Button 1 Click(Sender: TObject): Private { Private declarations} Public { Public declarations } End; Var Forml: TForm 1; r,v: real; {объявление переменных: радиус, объем} Implementation {$R* DFM] Procedure TForm 1.Button lChck(Sender: TObject); Begin R := StrToFloat(Editl.text); V := (3/4! * PI * IntPower(r, 3)'1000; ShowMessage(‘O6beM шара V = ’ + FloatToStr(v) + #13 + ' радиус = ' 3 FloatToStr(r)); End; End.
ВЫСОКОУРОВ 1Г:ВЫЕ- МEl ЭДЫ ИНФОРМАТИКИ I ГРрГРАММЭРОВАГ ИР. 167 5.7. Работа с Code Explorer 1 х 1И добави гь программный код в объявление класса, то он автома гиче- ски отобразится в окне Code Explorer. 11апример, если созда гь на форме нова ю процедуру, то ее объявление появит ся в Code Explorer. Верно и обратное. Если щелкну гь правой кнопкой на узле Private или Pub- lic в разделе I опт 1 в Code Exploier. можно объявить новый метод или процедур}. При этом потребуется ввести полную синтаксическую запись, включая парамет- ры, скобки и завершающую точку с запятой. Если объяви гь метод объекта, а за тем поместить курсор над ним и нажа гь сочетание клавиш | Ctrl] + [Shift + [с], будет создан шаблон для реализации ,toi о мет ада, т.е. в модуль автоматически добавится программный код, связанный с эт им мет одом. Чт обы перейт и от объ- явления метода к его реализации или наоборот, следует нажать комбинацию к та- виш Ctrl | +1 Shill ’ t [jj или | Ctrl | +1 Shift | + Ц I Ес ти ввести реали зацию мет ода и поместить курсор над его заголовком и нажать [Ctrl] + | Shift | + [F . то его объявление i енерируется автоматически. В случае, когда объявлено несколько мет одов или объявлено несколько рехтизаций, то при нажат ии | Ctrl + | Shift | г |F| автоматически добавляю гея все недостающие объявления и реализации. Редактор кода снабжен контекстно-зависимой справочной системой, ко- торая автоматически, во время набора текста программы, выводи г справочную информацию о процедурах и функциях языка программирования. Например, если во время набора текста программы напечатать слово “Strl oFloat”. которое являет- ся именем функции преобразования строки символов в действительное число, и после него постави гь открывающую скобку, то на экране появится маленькое ок- но. в котором будет указан тип параметра функции (Const S: String!. При наборе текста программы можно получи гь справку о конструкции языка программирова- ния. процедуре или функции. Для этого надо в окне редактора кода напечатать слово, о кот ором надо получить справку, установить курсор на любую его букву' и нажать функциональную клавишу <F 1 >. Как правило, с одним словом в справочной сис геме связано несколько разделов, поэтому для получения справки по конкретному разделу надо в списке выбрать его название и щелкнут ь на кнопке “Вывести”, Другой способ получить справку - это из меню Help выбратс команду Keyword Search, и в открывшемся окне справочной системы, в поле "‘Введите первые буквы нужного слова”, ввести слово, по которому требуется получить справку. 5.8. Компиляция и выполнение программы 5.8.1. Сохранение проекта Чтобы сохранить проект, надо из меню I ile выбрать команду Save Project As. Если проект еще ни разу не был сохранен, то. р от вет на команду сохранения проект a Save Project As 1 k'lphi сначала выводи г диалоговое окно Save Unit As. 11 этом окне следует выбрать гапку, предназначенную для хранения всех проектов Delphi. R панке проектов Delphi следует создать новую, отдельную папку для фай нов сохраняемого проекта. Для этого надо щелкнуть на кнопке Создание но-
168 ~ЛАВА 5. ТЕХН0Л01 ИЯ СОЗДАНИЯ ПРО 'РАММ В СРЕДЕ DELPHI вой папки. Рядом с появившимся значком новой г апки в рамке, следует напеча газ ь имя папки проекта и нажат ь <Enter>, после чего двойным щелчком на значке созданной папки, раскрыть ее. Затем в поле Имя файла надо ввести имя пршраммного модуля, например, FuntToKg. и щелкнуть на кнопке Сохранить. После щелчка на кнопке сохранить в диалоговом окне Save Unitl As появляется следующее диалоговое окно - Save Project I As В поле Имя файла следует ввести имя файла проекта. 5.8.2. Компиляция После ввода тексза процедуры обработки события и сохранения проекта можно, выбрав команду Compile <Ctrl F9> из меню Projecl, откомпилировать приложение. Если в программе нет синтаксических ошибок, то на экране появля- ется окно Compiling, ш формирующее о результатах компиляции. В этом окне выводится количество обнаруженных компи (я гором ошибок (I Errors), количес гво предупреждения (Warnings) и количество подсказок (Hints). Следеет обрати гь внимание, ч го после установки Delphi среда програм мирования автоматически настраивается таким образом, что окно с сообщением о результатах компиляции на экране не появляется. Для того, чтобы после заверше- ния компиляции окно Compiling появлялось на экране, надо из меню Inols вы- брать команду Environment Options, в открывшемся диалоговом окне выбрагь вкладку Preterences и установи гь флажок Show compiler progress, находящийся в группе Compiling and Runni ig, затем щелкнуть на кнопке ОК. Другой способ получить откомпилированную программу выполнить команду Run меню Run или нажать клавишу <F9>. Ошибки компиляции Во время компиляции текс г программы проверяется на от сут ствие син- таксических ошибок Компилятор просматривает программу от начала и, если обнаруживает ошибку, то процесс компи 1яции приостанавливается и в появив- шемся окне Compiling, в поле Error, указывается количество ошибок, которое, как правило, равно двум Первая ошибка - это первая от начала текста сии гаксиче- ская ошибка, обнаруженная компилятором. Наличие в тексте даже одной синтак- сической ошибки приводит к возникновению второй - фатальной - невозможно- сти генерации исполняемой программы После щелчка на ОК окно Compiling исчезает, и в окне редакт ора кода выделяется строка, которая, по мнению компилятора, содержит ошибочную кон- струкцию. В нижнюю часть окна редактора кода компи пят эр выводит сообщения об ошибках. Если размер окна редактора кода недостаточен, чтобы сообщение об ошибке полностью было отображено, то в конце сообщения указываются три точки. В этом случае можно разверну гь окно редактора кода на весь экран, или поместить курсор мыши на слово Error, в результате чего появит ся всплывающее окно, содержащее весь текст сообщения об ошибке. Здесь следует обратить вни- мание на то, что строка, выделенная компилятором, не все! да содержит ошибку. Довольно часто ошибочной является инструкция, находящаяся в предыдущей строке. Ниже, в табл. 10, приведены сообщения о наиболее типичных ошибках.
ВЫСОКОУРОВНЕВЫ МЕТОДЫ ИН Х)РМАТИКИ И ПРОГРАММ И РОВА! ИЯ. 169 1аблица IО Сообщение компилятора Вероятные причины Undeclared identifier (Необъявленный идентифика- тор) Используется переменная, не объявлен- ная в разделе Var программы; Ошибка при написании имени объявлен- ной переменной, например, объявлена переменная Summa, авт ексте npoi рам- мы написано Suma Ошибка при написании имени инструк- ции. например, вместо const написано conts. Untermmated string (11езавершенная строка) Incompatible types ..and... (Несовместимые типы) 1ри записи с гроковой константы не по ставлена завершающая кавычка. В инструкции присваивания тип выра- жения не соответствует или не может быть приведен к типу переменной, полу- чающей значение выражения. Missing operator or semicolon (Отсутст вует оператор или т очка с запятой) Не поставлена точка с запят ой после ин- струкции программы Если синтаксических ошибок в программе нет, компилятор создает ис- полняемый ф 1й. । программы, который позже можно будет запуст ить из Windows. Имя исполняемо) о файла такое же, как и у файда проекта, расширение - exe. Del phi помещает исполняемый файл в тот каталог, где находится файл проекта. Предупреждение и подсказки компилятора ] 1ри обнаружении в программе неточностей, которые не являются ошиб- ками, компилятор выводит подсказки (Hints) и предупреждения (Warnings). 11апример, наиболее часто выводимой подсказкой является сообщение об объявленной, но не используемой в программе переменной (Variable ... is de- clarated but never used ...). Типичным предупреждением (Warnings) является: Variable ... might not have been initialized (переменной, вероятно, не присвоено начальное значение). 5.8.3. Запуск приложения из среды программирования 11робный запуск приложения можно выполнить непосредственно из сре- ды программирования, не завершая работы с Delphi. Для этого надо выбрать ко- манду Run из меню Run. Окно приложения - это обычное окно Windows. Его можно перемещать по »крану, можно свернуть и представить в виде пиктограммы. На рис. 12 пред- ставлено окно, в кот ором отображают ся исходные данные и результаты расчетов по одной из программ.
170 глава 5. Технология создания программ б среде DELP HI. Рис 12. Вид приложения с результатом вычисления 5.8.4. Ошибки выполнения приложения Во время работы приложения могут возникать ошибки, которые называ- ются ошибками времени выполнения, или исключениями (exceptions). В боль- шинстве случаев причинами исключений являются неверные исходные данные. Если программа запускается из Delphi, то при возникновении исключения появ- ляется окно с сообщением об ошибке, и выполнение программы приостанавлива- ется. При этом в окне редак гора кода Delphi выделит инструкцию, при выполне- нии которой во шикло исключение. После щелчка по кнопке ОК можно продол- жить выполнение программы, для этого надо из меню Run выбраз ь Step Over. Для завершения работы приложения надо из меню Run выбрать Program Reset. Разра- батывая проект, программист должен предусмотреть все возможные варианты некорректных действий пользователя, которые могул привести к возникновению ошибок времени выполнения, и обеспечить способы защиты от них. 5.8.5. Окончательная настройка приложения После того, как программа отлажена, необходимо выполнить окончатель- ную настройку: назначить приложению значок, кот орый будет изображать испол- няемый файл приложения в папке или на рабочем столе. Этот же значок б>дет изображать системное меню в главном окне приложения во время его работы и работающее приложение на панели задач Windows. Чтобы назначить приложению значок, надо из меню Project выбрать ко- манду Options, затем, в открывшемся диалоговом окне Project Options, вкладку Application (рис. 13)
ВЫСОКОУРЛ-Ш-ВЫ.- ME I-JU ГН РОРМАТИкИ И ПРОГ иаММЙРОвАНРЯ. 171 Рис. 13. Вкладка Application диалогового окна Project Opt ons В поле Title (заголовок) следует ввести название при поженил. Название приложения во время его работы, выводи гея на панели задач Windows рядом со значком, изображающим это приложение. Чтобы назначить приложению значок, надо щелкнуть на командной кнопке Load Icon (за1 рузит ь значок). В открывшем- ся окне Application Icon, проема гривая каталоги компьютера, с тедует най ги файл подходящего значка (значки хранят ся в файлах с расширением .ico) и щелкнуть по кнопке Открыть. В результате диалоговое окно Application Icon закрывается, и вновь появ- ляется диалоговое окно Project Opti ons, в котором изображается выбранный зна- чок. После этою щелкнуть на кнопке ОК. В состав Delphi входит программа Image Editor (редактор изображения), при помощи которой можно создать для своего приложения уникальный значок Чтобы начат ь работу' по созданию нового значка, надо из меню Tools главного окна Delphi выбрать команду Image Editor, затем в появившемся окне редакт ора изображений из меню I ile выбрать команду New и в появившемся уточняющем списке- команду Icon File. В результате этих действий появится диалоговое окно Icon Properties (свойства значка), в котором выбраны стандартные для значков Windows свойства: размер 32 на 32 пикселя, 10 цветов. Пос ie щелчка на кнопке ОК появляется новое окно, в котором можно, ис- пользуя инстру менты и палитру Image Editor, нарисовать нужный значок. 11осле
172 ГГАВА 5. ThXHO/ 01 ИЯ СОЗДАНИЯ РРОРАММ ВСР^ДР DELPHI того, как значок нарисован, его следует сохранить в файле. Для этого надо из ме- ню File выбрать команд} Save, в открывшемся окне выбрать папку с файлами проекта, для которого предназначен значок, задать имя файла и щелкнуть на кнопке Сохранить. Созданный значок можно связать с приложением так, как бы по описано выше. 5.8 6. Установка приложения Значок приложения можно помесз ить на рабочий стол или в одну из под- структур пункта Программы главного меню Windows. Также можно для прило- жения создать новый подпункт в меню Программы. Чтобы установить приложение, надо из главного меню Windows выбраз ь команду Настройка, затем - команду Панель задач. В появившемся диалоговом окне на вкладке Настройка меню, щелкнул ь на командной кнопке Добавить... В результате этих действий появляется диалоговое окно Создание ярлыка В этом диалоговом окне в поле Командная строка надо ввести имя файла испол- няемого приложения с у казанием пути к нему. Для ввода имени файла приложения можно воспользоваться командной кнопкой Обзор..., после щелчка на которой появляется диалоговое окно для по- иска нужного файла. После ввода командной, строки надо щелкнул ь на командной кнопке Датее> и в появившемся диалоговом окне Выбор папки выбрать одну из соответствующих групп программ меню Программы. Чтобы установить програм- му в новую группу, надо щелкнуть на командной кнопке Сощать папку... и вве- сти имя новой программной группы. После щелчка на кнопке Далее появляется диалоговое окно Выбор назва- ния программы. В поле итого окна следует ввести текст, который будет выводить- ся рядом со значком, изображающим программу в списке программ группы. После щелчка на командной кнопке Готово в указанной командной груп- пе появи гься строка, позволяющая запустить созданное приложение выбором ко- манды из главного меню Windows. 5.9. Графические компоненты Delphi предоставляет разработчику три способа отображения графики: можно использовать заранее созданные графические изображения создава гь эти и юбражения с помощью графических компонентов или отображать графические примитивы во время работы программы. В этом разделе будут рассмотрены три способа отображения графики: графические компоненты, входящие в сос гав Del- phi - Image, Shape и Bevel, их свойс гва и методы, а также примеры их примене- ния. 5.9,1. Компонент Image Компонент Image предназначен для отображения в форме ра гличных гра- фических изображений, хранимых во внешних файлах в формате BMP (растровое изображение), ICO (иконка) и WMF (метафайл). Возможно задание файла, изо- бражение из которого будет отображаться в форме, как во время создания про- граммы, так и во время ее выполнения. Для задания файла во время создания про- I раммы нужно выбрать слово Picture - после чего появится графический редак- тор, с помощью которого можно загрузит ь графическое изображение из файла.
Высокоуровневые методы ин юрнатики и программирова! и \ 1/э Очевидно, что для задания имени файла во время выполнения npoi раммы также необходимо присвоить свойс гву Picture новое значение. 11редположим, чт о нужно создать программу для просмотра BMP-файлов. Расположим в форме 1.ом- понен г Picture, компонент Open! )ialog (ко горый позволит выбирать нам файлы) и создадим меню, содержащее одну команду - rtle/Open. В обработчике команды FilezOpen напишем следующий код: Procedure TForml .Open 1 Click! Sender: 1 Object); begin If OpenDialogl.Execute Tnen Image 1.Picture.) ,oadFromFile( OpenDialogl.FileName ) end: Свойство Picture имеет тип TPicture. Вспомогательный объчи TPicture обладает мет одом Load! romFile, который используется для загрузки 1 рафическо- го и юбражения из указанного файла. Для того чтобы, изображение автоматически изменяло свои размеры, не- обходимо присвоить свойству Stretch значение True. Значение этого свойства иг- норируется для иконок (фантов .ICO), управлять автоматическим изменением размера и юбражения можно также с помощью свойства AutoSize. 5.9.2. Компонент Shape Эт о'г компонент прсдна шачен для от ображения различных геометриче- ских фи1 ур - окружностей, эл типсов. прямоугольников, прямоугольников с за- кругленными углами, квадратов и квадратов с закрут юнными углами, Тип гео- метрической фигуры, отображаемой этим компонентом, может быть задав с по- мощью свойс гва Shape и может принима гь значения, описанные в табл. 11. Таблица 11. Значение Описание St Ellipse Отображается эллипс StRectangle Отображается прям.ту тельник StRoundRect Отображается прямоу гольник с закругленными yi - лами StRoundSquare Отображается квадрат с закругленными углами StSquare Отображается квадрат StCircle Отображается окружность Можно управлять свойствами геометрических фигур через свойство Brush - Color и Style. Свойст во Color позволяет задават ь цвет геометрической фигу ры. а свойст во Sty le - стиль ее заполнения Пример 8. Отобра шть прямоугольник, заполненный желтым цветом. Для решения этой задачи необходимо выполнить следующую программу Procedure ГГогт! .FormCreate( Sender 1 Object); Regin With Shape 1 do begin Shape := stRectangle; { Прямоугольник } Brush.Color := cl Yellow; ( Цвет желтый j Brush.Style := bsSolid; { Тип заполнения - полное заполнение I end; End.
174 Г IAEA 5. ЕХНОЛО к Я С03нА ШВ ПК ГРАММ В CPLJ DELPHI. 1ип и цвет рамки могут быть заданы мере г свойство Pen - C olor и Style. Свойства Brush.Color и Реп.Со1ог могу i иметь значения, приведенные в табл. 12. Таблица 12. Константа Цвет CIBlack Black (Черный) CIMaroon Maroon (Темно-красный) CIGreen Gi een (Зеленый) ClOlive Olive green (Оливковый) CINavy Navy blue (Темно-синий) CIPurple Purple (С иреневый) CITeal Teal (Сине-зеленый) CIGray Gray (С ерый) CISilver Sllvei (Серебряный) CIRed Red (Красный) CILime Lime green (Ярко-зеленый) CIBlue Blue(Голубой) Cl Yellow Yellow (Желтый) CIFuchsia Fuchsia (Сиреневый) ClAqua Aqua (Ярко-голубой) ClWhite White (Белый) CIGray Light Gi ay (Свет ло-серый) ClDkGray Dark Cray! Гемно-серый) Свойство Brush.Style может име гь следующие значения - bsSolid, bsCleai, bsHorizontal, bsVertical. bsFD.agonal, bsBDiagonal. bsCross и bsDiagCross. Свойст- во Pcn.Style может иметь следующие значения - psSolid, psDash, psDot. psDashDot, psDashDotDot. psClear и psInsideFrame. Пример 9. Отобразить на форме прямоугольник, заполненный голубыми диагональными штрихами. (см рис. 14 ) Рис. 14. Приложение по примеру 9. отображающее прямоугольник, заполненный голубыми диагональными штрихами
Высокоуровневое mi >сды информатики и программирования. 175 Procedure TF orml .FormCreate(Sendei: TObject); Begin With Shape 1 do begin Shape := stRectangle; Brush.Color := clBlue; Brush.Style := bsD.agC ros^; end; End; 5.9.3. Компонент Bevel Компонент TBevel предназначен дня оформления и позволяет придать сегментам форм трехмерный вид. Элемент управления TBevel отображает линию фаски, рамку или кадр. С помощью этого компонента можно выделить группу элементов и ’и отделить их друг от друга. Например, если положить на форму компоненты TBevel. а затем разместить в них группы компонентов кнопок неза- висимых переключателей iChec^Box, которые могут быть включены или выклю- чены, и зависимых переключателей 1 radioButton, которые позволяют осущест- вить взаимно исключающий выбор в перечне альтернатив, то группы кнопок бу- ду г ка даться связанными, благодаря рамке скоса вокру г них. Вид компонента TBevel задается свойством Shape, а свойс гво Style управ- ляет внешним видом самой границы, которая может бып приподнятой или уг- лубленной. таким образом создается тип отображения - вдавленный и т : выпук- лый. Свойство Align задает тип выравнивания это1 о ксмпонен га внутри компо- нента-владельца. Свойство Shape. Свойство Shape, задающее вид компонента TBevel, мо- жет иметь одно из значений, представленных в табл. 13. Свойство Style. Свойство Slyle. задающее ст иль отображения, может при- нимать одно и $ значений: BsLowered - вдавленный, В: Raised — выпуклый. 11апример, панели в диалоговом окне Replac е Text (см рис. 15) выделены таким образом: вверху для выделения полей ввода и редакт ирования установлены значе- ния свойств Shape - b< Frame. Sty le - bsLowered; группы кнопок выделены элементами TBevel со свойствами Shape - bsBux, Style - bsRaised. Значения свойства Shape компонента TBevel приведены в таб i. 13. Т аблица 13. Значение Описание BsBox Компонент имеет вид заполненного прямоугольника BsFrame Компонент имеет вид рамки BsTopLine Компонент имеет вид прямой линии, располагаемой сверху bsBottomLine Компонент имеет вид прямой линии, располагаемой снизу BsLeftl .ine Компонент имеет вид прямой линии, распо шгаемой слева BsRightLine Компонент имеет вид прямой линии, pacnonai аемой справа BsSpacer Обрамление компонента отсутствует
176 Гмза 5. Технология ссздагиг программ в среде DElPh; •Is Replace Text Options V Case sensitive Г Whoie .wore: only J Prompt on replace t teeter <• iFc-wd'd C Backward Рис. 15. Примеры использования компонента TBevel для выделения групп элементов В нем соответствующие кнопки связаны, группы кнопок отделены друг от друга, а форма выгляди г рельефнее. 5 9.4. Компонент TPaintBox Компонент TPaintBox (Страница палитры компонентов System) использу- ется в тех случаях, когда в программе необходимо иметь прямоугольную область с канвой для рисования. Канва содержится в свойстве Canvas компонента, графи- ческие инструменты - в свойствах Font, Реп и Brush, а собственно рисование осу- ществляется в обработчике события on Paint. Например, следующий обработчик события создаст окно, изображенное на рис 16, 17. Использование компонента TPaintBox Рис. 16. Вид формы во время разработки приложения
ВЫССКЭУРОВНЕВЫ! Mt ГОДЫ ИН<К РМАТИК1 И ПРО РАНЖИРОВАНИЯ. 1 ?? Procedure П orml.PaintBoxlPaint(Sender: TObject); V ar X. Y. Integer; Begin With PaintBoxl, Canvas Do begin Brush.color := clGreen; Ellipse(0, 0, Width, Height); Font.Name := 'Arial', Font.Si/e := Height div 5; Font.Style := [fsBold, fsltalic]; Font.Coloi := cl White X := (Width - 1 ext W idth('PaintBox')) div 2; у := (Height - 1 extHeight('P')) div 2; Text Out( X Y, ’Paint] Sox') end End; Для реализации этого примера: • Для формы установи гь в инспекторе объектов в свойстве С aption за) оловок Использование компонента TpaintBox и ус гановш ь ее размеры: Height = 290; Width = 390. • На пустую форму положить компонент TPaintBox и установить его размеры: Height = 100; Width = 300. • Создать обработчик события OnPaint. Для этого позиционировать курсор на компонент TpaintBox, ь И спекторе объектов перейти на вкладку Events, вы- брать событие OnPaint и дважды нажать в окне ввода левую клавишу мыши; в результате в Редакторе кода будет создан макет процедуры PaintBoxlPaint, в который требуется вписать текст. Рис. 17. Вид формы во время выполнения поиложения
178 ГЗАВА 5. ТХНОЛО I Я С03ДА ИЯ ПРОГРАММ В СРСДГ DELPHI 5.10. Свойства графических компонентов Все компоненты, которые используются для построения приложения в Delphi, делятся на визуальные (видимые) и невизуальные (системные). Па этапе проектирования интерфейса приложения все компонен гы видны. К визуальным компонентам соотносятся формы, кнопки, списки и др. Визуальные компонент ы формируют интерфейс приложения и используются для у прав юния приложени- ем, иначе их называют управляющими компонентами. 1 [еви зуальные компонент ы реализуют сложные системные функции управления (меню, диалоги, доступ к таблицам баз данных, представление данных из таблиц и т .д.) С их помощью р п- рощается разработка логической части приложения. 5.10.1. Проектирование интерфейса программы При проектировании интерфейса программы разработчик выбирает ком- поненты из пали гры компонентов и помещает их на форму. Каждый компонент, который помещается на форму, имеет свое о сражение в окне Инспект ора Объек- тов (Object Inspectui). Object Inspector имеет две “странички" - “Properties'' (Свой- ства) и “Events” (Собы гия). Создание программы в Delphi своди гея к “нанесению” компонент на форму (которая, кстат и. также является компонент ом) и настройке в заимодействия между ними путем: • изменения значения свойс гв этих компонентов; • написания адекватных реакций на собы гг я. Свойство является важным атрибутом компонента. Для пользователя (программиста) свойство вы лядит как простое поле какой-либо структуры, со- держащее некоторое значение. Однако, в отличие о г “просто” поля, любое изме- нение значения некоторого свойства любою компонента сразу же приводит к из- менению визуально! о предст авг.ения этого компонента, поскольку свойство ин- капсулирует в себе методы ( действия), связанные с чтением и записью этого поля г которые, в свою очередь, включают в себя необходимую перерисовку). Свойства служат двум главным целям. Во-первых, они определяют внешний вид фермы или компонента. А во-вгорых, свойства определяют поведение формы или ком- понента. Существует несколько т ипов свойств, в гависимости от их “природы”, г.е. внутреннего устройства. • 11рос гые свойс гва - это те, значения которых являются числами или строками. Например, свойства Left и Тор принимают целые значения, определяющие положение левого верхнего угла компонента или фор- мы. С войства Caption и Name представляют собой строки и определя - ют заголовок и имя компонента или формы. • 11еречислимые свойства - это те, которые могут принимать значения из предопределенного набора (списка) Простейший пример - это свойст- во типа Boolean, которое может принимать значения 1 rue или False. • Вложенные свойства - это те. которые поддерживают в юженные зна- чения (или объекты) Obj ect Inspector и зображает знак “л ” слева от на- звания таких свойств. Имеется два вида таких свойств: множества и комбинированные значения. Object Inspector изображает множества в квадратных скобках. 1 х ти множест во пусто оно отображается как [ ]. Установки для вложенных свойств вида “множество” обычно имеют значения типа Boolean. Наиболее распрост раненным примером тако, о
Высокоуровневые методы mf wpmathkh и программирования 179 свойства является свойство Style с вложенным множеством булевых значений Комбинированные значения отображаются в Инспекторе Объектов как коллекция некоторых величин, каждый со своим типом данных. Некоторые свойства, например, Font, для изменения своих значений имеют возможность вызвать диалоговое окно. Для этого дос- таточно щелкнуть маленькую кнопку с тремя точками в правой части строки Инспектора Объектов, показывающей данное свойство. В режиме проект ирования манипулирование свойствами осуществляется с помощью Дизайнера Форм (Гorms Designer) на странице “Properties'’ Инспекто- ра Объектов. Например, для того, чтобы изменить свойства Height (высоту) и Width (ширину) кнопки, достаточно “зацепить” мышкой за любой ее угол и раз- двинуть до нужного представления. Того же результата можно добиться, просто подставив новые значения свойств Height и Width в окне Object Inspector. С другой стороны, в режиме выполнения пользователь (программист) имеет возможность не только манипулировать всеми свойствами, отображаемыми в Инспекторе Объектов, но и управлять более обширным их списком. 5.10.2. Изменение свойств визуальных компонентов во время выполнения программы Часто программа должна обеспечить, посредством выбора из меню, воз- можность изменить цвет фигуры и цвет формы, и вменить вид фигуры, а так же обрабатывала автоматическое изменение размера окна. Для примера ниже прове- дем проектирование приложения «Изменение свойств визуальных компонентов» (см. рис. 18): Рис. 18. Окно формы во время разработки приложения «Изменение свойств визуальных компонен гов»
180 Глава 5. Технология создании программ а сред! DELPHI. • л вместим на форму компонент меню (MainMenu); • поместим на форму фи1 уру компонент Shape, объект 1 shape; • для изменения размера фи> уры, изображенной в средней части экра- на, поместим 2 полосы прокрутки (Scroll tlars): • "определим"’ полосы прокрутки изменять свое положение в зависи- мости от размера окна; • “определим” свойство Position г.лос прокрутки изменяться, чтобы правильно отражать размер формы. 1. Главное меню , pi г программы создас гея с помощью компонента Main- Menu (находится на страничке “Standard” палитры компонентов). 1 юли поместить его на форму и дважды щелкнут ь по нему мышкой - откроется редактор меню, в котором можно ввест и нужные названия пунктов меню и, при желании, изменить их имена (задаваемые Delphi по умолчанию). Меню npoi раммы создает» я с гремя главными пунктами:1 Цвета”. "Фигуры", "Выход"’. Для первою пункта меню создаются следующие подпункты: Цвет фигу- ры, Цвет окна. Для второго пункта меню, (ввести в поле С aption и соотвсгственно в поле Name) 11рямоугольник SiRectangle Квадра г S'Square Закругленный прямоугольник StRoundRect Закругленный квадрат S .RoundSquare Эллипс StEllipse Окружность StCircle Третий пункт меню “Выход” не будет содержать никаких подпунктов. После создания всех пунктов и подпунктов меню для работы программы нужно назначить номера для каждого из подпунктов меню, связанных с типом фигуры. Для этого можно воспользоваться свойс гвом 1 ag, и деющимся у каждо! < > пункта меню. Свойство Tag (типа Integer) специально введено в каждый компо- нен г Delphi с тем, чтобы программисты могли использовать его по своему усмот- рению. Назначим 0 свойству Tag пункта "Прямоугольник”, 1 - пункту ‘ Квадрат”. 2 - пункту “Закругленный прямоугольник” и т.д. Цель такого назначения - свя- зать выбор пункта меню с конкретным объект ом (фш j рой), выбранным из масси- ва типов фигур. 2. Для каждого пункта меню выбора фигур установливается событие On Click, вызывая процедуру с именем Tform NewShapeClick. Метод, реатизующий реакцию на выбор подпунктов: Procedure 1 Гогт! .NewShapeClickl Sender 1 Object); Begin Shape 1 .Shape := TShapeType((Sender as TMenuItem).Tag): End; Этот код "работает’’ правильно благодаря тому, что перечисляемый з ип TShapeType в качестве начального имеет значение С, и в свойство Tag подпунктов меню также записаны порядковые номера, начинающиеся с нуля. Оператор As позволяет надежно преобра ювывать типы из одного в дру-
ВЫСОКОУРОВЧ! ВЫЕ MEI ЭТЫ РН'Т>ОРМАТ11КИ И ПРОГРАММ И РОВ АЕ W . 181 гой: в частноеги, преобразовать парамс гр Sender «имеющий общий тип 1 Object) в тип TMenultem. Как правило, параметр Sender в Dciphi - это управляющий эле- мент, посылающий сообщения функции, в которой он фигурирует, 3 данном слу- чае, Sender является пунктом меню, и, следовательно, можно ра^отать с этим па- раметром, как если бы он был декларирован с типом TMenultem. Операт op As обеспечивает проверку преобразования в режиме выполне- ния программы. Когда используется оператор As, преобразование Sender в TMenultem реально будет произведено лишь в том случае, если Sender дейст ви телыю имеет тип TMenultem. 3. Для изменения цвета окна нуж но выбрат ь компонент Color) )ialog из па- литры компонен' ив (она находи гея на страничке “Dialogs”) и поместить его на форму. Дважды щелкнув на событии OnChck пункта “Цвет формы” - Delphi сге- нерирует заготовку метода, который выгляди г следующим образом: Procedure TForml .FormColorClick(sender: TObject); Begin Fnd; Ес ти добавить две простые строчки года, то процедура примет вид: Procedure lEorml .FormColorClicki'Sender: TObject); Begin if ColorD«alogl .Execute then Formi.Color := ColorDialogl.Color; End; Этот код во время выполнения при нажатии кнопки “Цвет формы” вызы- вает стандартное диалоговое окно выбора цвета. Ес ш в эт ом диа юговом окне щелкнуть кнопку ОК, то выполни гея следующая строка: Formi.Color := ColorDialogl .Color; Этот код ) становит свойство Color формы form) в цвет, который был вы бран с помошью диалогового окна Coloi Dialog 1. Та же самая техника может использоваться дзя изменения цвета cj игуры (компонент Shape, объект TShape). Аналогично, щелкнув на OnClick пункта “Цвет Фи1 уры”, дважды щелкнуть по ней мышкой и солдат ь метод аналогичный следующему: Procedure Thorml ShapeColorClick(Sender: TObject); Begin if ColorDiah g 1 .Execute then Shape 1 Brush Color := ColorDialogl.Color: End; 4. Выбрать 2 полосы прокрутки (ScrollBars) (страница STANDART). Ус- тановить в Objed Inspector свойство Scroll)lari.Kind sbHorizontai, orizontaEIhh Hhh свойство ScrollBar2.Kind sbVertical. 5. Установить свойство формы ActiveControl, определяюще, о акт ивный компонент формы horml равным значению Scro11 Bai 1. Это означает, что при по- явлении формы на экране фокус будет установлен на гори юнтальной полосе про- крутки 6. Установить свойство формы Scaled равным True. При значении True разрешается использование свойства PixelsPerlnch, которое указывает, как при- ложению создзва гь масштабируемое окно формы.
182 Гпага 5. Texi отгия сгзд/ния программ г cpj£: DELPHI. 5.10.3. Программирование полос прокрутки окна Пршрамма должна включат ь метод FonnOnResize для объекта Forml Две полосы прокрутки в программе всегда будут располагаться возле границ окна, независимо от ei о размеров. Выполнение этих действий требует написания не- сколько более сложного программирования, чем было показано ] «нее. Delphi, хотя и скрывает от npoi раммиста детали Windows-программирования, однако не запрещает обращат ься к функциям Windows API (прикладного пользовательского интерфейса). Таким образом Delphi поддерживает низкоуровневое программиро- вание на уровне Windows API. Первое, что делается в данном методе. - запрашиваются системные пара- метры. определяющие размеры за, оловка окна, oi ибающей его рамки и меню. Эта информация “добывается” путем вызова функции GetSystemMetrics являющейся частью Windows API. Функции GetSysteir.Metrics передается один аргумент в ви- де константы, определяющей вид запрашиваемой информации. Например, если передать функции константу sm_cyCaption, io можно получить в качестве резуль- тата высоту заголовка окна (в пикселях) Используется значение системных констант- SM CYCAPTION Высота 3ai оливка окна, включая высоту си ибающей окно ра ики, размер которой н з может быт ь изменен iSM CYBORDER). SM CXFRAME SM CYMENE Ширина огибающей окно рамки, размер которой может быть изменен. Bi сота nj юсы меню в одну строку Эт о высота меню за вычетом высоты огибающей окно рамки, размер которой не может быт ь и 1менен (SM CYBORDER). Это вызовы функций li'indows Al I Procedure TForml.FormResize(Sender: TObject); Var Menu, Caption, Frame: Integer; Begin Caption := GetSystemMetncs(sm cyCaption); Frame := GetSystemMetriCs(sm cxF rame) * 2; Menu := GetSystemMetrics(sm cj Menu): Scrollbar] .Max := Width; Scrollbar2.Max := 1 [eight; Scrollbar?.L eit := Width - Frame - Scrollbar?. W idth; Scrollbar?.Height := Height - Frame - Caption - Menu: Scrollbarl .Top := J leight - bcrollbar?.Width - Frame - Caption - Menu, Scrollbar 1.Width := Width - Scrollbar?.W idth - Frame; End: Код, показанный здесь, является реакцией на событие OnResize. Это со- бытие перечислено среди других на страничке "Events" Инспектора Объектов в состоянии, когда выбрана форма (окно) С обьпие (сообщение') OnResize посыла- егся форме (окну) каждый раз. когда пользователь "захватывает’ мышкой за ка-
Высокоуровневые методы информатики и программирования. 183 кой-либо край окна и делает размер окна большим или меньшим. Однако, это же сообщение (событие) посылается окну и ь том случае, когда происходит макси- мизация окна (но не минимизация). В методе FormResize программа вычисляет новые размеры полос прокру гк и: Scrollbar!.Мах := Width; {Максимальное } Scroll эаг2.Мах := Height; {значение, на кот орое может перемещать! я бегунок} Scrollbar2.Left := Width - Frame - Scrollbar?. Width Scrollbar2.Height := Height - Frame - Caption - Menu, Scroll таг 1.Top := Height - Scrollbar2 Width - Frame - Caption - Menu; Scrollbar!.Width := Width - Scrol'bai?.Width - Frame; Вычисления, приведенные здесь, включают простые математические дей- ствия. Например, левая сторона вертикальной полосы прокрутки должна быть равна ширине всего окна (формы) за вычетом ширины рамки и ширины самой полосы прокрутки. Это элементарная логика, и реализовав ее в программе, можно получить вертикальную полосу прокрутки, всегда располагающуюся возле право- го края окна (формы) В программе Мах каждой полосы прокрутки оставалось равным значению по умолчанию - 1С0: эго означало, что после того как бегунок полосы прокру тки пройдет все доступное расстояние <как для вертикальной, так и для горизонталь- ной полосы прокрутки), свойство Position будет установлено в 100. Вели бегунок возвращался к начату. свойство Position устанавливалось равным свойству Min, которое по умолчанию - 0. В программе можно изменять значения свойств Min и Мах так. чтобы диапазон значений Position полос прокрут ки отражал текущий размер окна {фор- мы), даже при изменении формой своего размера в режиме выполнения. Ниже приведены соответствующие строки из мет ода FormResize. Procedure TForml.FormR.esize(Sender: TObjecI); Begin Scrollbarl .Max := Width; Scrollbar2.Max := 1 leight; End; Две строчки кода, показанные выше, просто устанавливают максималь- ные значения полос прокрут ки равными ширине и высот е фо| ‘мы соответственно. После этого всегда можно сделать помещенную на форму фигуру т акой же “большой", как и сама форма. После введения т аких изменений больше не потре- буется умножать свойство Position 1 а какой -либо множите ib. Теперь необходимо включить методы Scrollbarl Change и Sen il!bai2Change для полос прокрутки. { Вертикальный размер компонента (фигуры) } Procedure TForml.Scrollbar2Change (Sender: TObject); Begin Shapei.l leight := Scrollbar2.Position End; { Горизонтальный размер компонента (фигуры)} Procedure TForml.Scrollbarl Change (Sender: TObject); Begin
104 Глава Ь. Технология создания программ в среде DELPHI. Shape).Width := Scrollbar 1.Position; End; Если запустить программу на выполнение, то можно у видез ь, чго она ра- ботает корректно при любом изменении размера формы. Ьолее того, теперь воз- можно выбирать фигуры и цвета из меню, ч го придает программе более строгий вид. Замечания • Каждая форма по умолчанию имеет две полосы прокрутки (HorzScroll- bar и VertScrollbar), которые появляются автома гически всякий раз, ко- гда размер формы становится меньше, чем облас гь, занимаемая управ- ляющими элементами, расположенными на этой форме. Иногда эти полосы прокрутки могут бьп ь очень полезными, но в данной ситуации они сделают совсем не то, ч го хотелось бы. Поэтому, для надежности, можно установить их вложенные свойства Visible в False. • При разработке приложения использовалась такая возможное гь языка Object Pascal, лежащего в основе Delphi, которая дает полное управле- ние над работой приложения, включая прямое обращение к функциям Windows API. Полный список значений этих констант имеется в on-line справочнике Delphi (Help | Windows API | Alphabetical functions | User func- tions | GetSystemMetrics), ниже, в таблице 14 приводится небольшая выдержка из этого справочника: Таблица 14. Имя константы Назначение MCXRORDER Ширина огибающей окно рамки, размер которой не может быть изменен SM CYBORDER Высота or ибающей окно рамки, размер которой не может быть изменен. SM CYCAPTION Высота заголовка окна, включая высоту огибаю- щей окно рамки, размер которой не может бы гь изменен (SM CYBORDER) SM CXCURSOR Ширина курсора SM CYCURSOR Высота курсора SM CXFRAME Ширина огибающей окно рамки размер которой может бы гь изменен SMCYFRAME Высота огибающей окно рамки, размер которой может бы гь изменен SM CXFULLSCREEN Ширина клиентской части для полноэкранного окна SMCYFULLSCREEM Высота клиентской части для полноэкранного окна (эквивалентна высоте экрана за вычетом вы- соты заголовка окна). SM CXICON Ширина иконки SM CYICON Высота иконки SM_CYMENU Высота полосы меню в одну строку. Это высота меню за вычетом высоты огибающей окно рамки, размер которой не может быть изменен
Высокоуровневьи. meiChli ► н рорма ин и и программирования. 185 Имя коне сайты Назначение (SM CYBORDER) SM CXMIN Минимальная ширина окна SM CYM1N Минимальная высота окна SM CXSCREEN Ширина экрана SM MOUSEPRLSEMT Не 0, если мышь установлена Исходный код программы имеет вид: Unit Unitl. Interface Uses Windows, Messages. Sysl Jtils, ('lasses. Graphics, Controls, 1 orms. 1 dialogs. Menus. StdCtrls, ExtCtrls; Гуре 1 Forml = class [T1 orm) Shape 1: TShape; ScrollBarl: T Scroll Bar; ScrollBar2: TScrollBar; MainMenul: TMainMenu, ColorDialog 1: TColorDialog, N1: TMenuItem; N2: TMenuItem; N3: TMenuItem; N4: TMenuItem; N5: TMenuItem; stRcctangle: 1 Menuitem; stSquare: TMenuItem- tRoundRect: TMenuItem; stRoundtSquaie. TMenuItem; stEllipse: TMenuItem- stt ircle: TMenuItem; procedure Sl .apeColorClk k(Sender: TObject)- procedure NewShapeClick(Sender: TObject); proceoure I ormColorCIickt Sender: TObject); procedure ScrollBar2Change( Sender TObject); procedure ScrollBarl Changel Sender. TObject); procedure FormResize( Sender: TObject); procedure ExitClickl Sender 1 Object); procedure FormMouse] )own(Sender: TObject: Button: TMouseButton; Shift’ 1 ShiftState: X. V: Integer); Private { Private declaral ions } Public { Public declaral ions } End; Var Forml: TForml; xO: Integer;
186 Глава 5 Техн злогия созданич программ в сррде DELPHI. уО: Integer, Implementation {SR *.DFM) Procedure TForm 1 .ShapeColorClick( Sender: TObject); Begin {Изменение цвета фигуры, если цвет выбран) If ColorDialogl .Е xecute then Shape 1 .Brush.Color = ColorDialogl .Color; End; Procedure TForm 1 .FormColorClickl Sender 1 Object); Begin {Изменение цвета формы, ec ги цвет выбран) If ColorDialogl .Execute then Form 1 .Color := Colni Dialogl.Colui; End; Procedure TForm 1 NewSh apeClickf Sender: TObject) Begin {Выбор фигуры и ? элементов перечислимого типа FShapeType в соответствии со значением, указанном в свойстве Tag пункта меню) Shape 1 Shape TShapeType{( Sender as TMenultem) Tag); End; Procedure TForml .ScrollBar2Cnangc(Sender: TObject), Begin {Изменение вертикального размера фигуры: устанавливается равной позиции бегунка вертикальной полосы прокрутки) Shapel .Height := ScrollBar2.Positton; End; ProcedureTForml.ScrollBarlChange(Sender: TObject); Begin {Изменение горизонтального размера фигуры: устанавливается равной позиции бегунка горизонтальной полосы прокрутки) Shapel .Width. ScrollBarl .Position; End; Procedure fForm 1 .EormResizetSender: TObject), Var Menu, {Высота полосы меню} Caption, {Высота заголовка окна и огибающей рамки) Frame: Integer; {Ширина or ибающей рамки) begin {Вызов функций WPJDOWS API (прикладною пользовательского интерфейса) запрашиваются системные параметры, определяющие размеры заго товка окна, огибающей его рамки и меню) Caption := GetSystemM etrics(smсу Caption); Frame := GetSystemMetrics(s m cxFrame) * 2; Menu := GetSystemMetrics(sm_cyMenu); {Максимальные значения, на которые могу т перемещаться бегунки горизон- тальной и вертикальной полос прокрутки, равны соответствующим значениям формы и огра «аю г текущий размер формы во время выполнения программы) Scrollbar 1.Мах :— Width;
BblCOKCyPOBt ЕВЫЬ МЕТОДЫ ИНФОРМАТИКИ И ПРОГРАММИРОВАНИЯ. 187 Scrollbar2.Max := Height. [Левая позиция верт ика 1ьной полосы прокрутки равна ширине всего окна (формы) за вычет ом ширины рамки и ширины самой полосы прокрутки) ScrolIbar2.I .eft := Width - Гi ame - Scrollbar2. Width; । Начальная позиция горизонтальной полосы прокрутки равна высоте всего окна(формы) за вычет ом ширины рамки (I тате), заголовка, меню и ши рины вертикальной полосы прокрут ки } S< rollbarl.Top := Height - ScrollBar2. Width - Frame - C aption - Menu; {Ширина гори юнтальной полосы прокрутки равна ширине всего окна (формы) за вычетом ширины рамки (Frame) и ширины вертика шной полосы прокрутки} Scrollbar! .Width := Width - Scrollbar2.Width - Frame; [Высота вертика 1ьной потосы прокрутки равна высоте всего окна (формы) за вычетом ширины рамки (Frame) и заголовка, меню и высоты горизонт атьной полосы прокрутки } Scrollbar2 Height := Height - Frame - Caption - Menu - Scrollbar! Height; End; Procedure TForml.LxitChck(Sender; TObject); {Закрытие формы} Begin Close: end; Procedure TForml.Fon.iMouseDov.rtSender: TObject; Button 1 MouseButton; Shift: TShifl State; X, Y: Integer); Begin IfXQoOthen Canvas.TextOut(xO,yO,' '); Canvas.TextOut(x, у, 'X- ' + IntToStr(x) -t ' у = ' + IntToStr(y)); XO x; YO .- y; End; End. Рис. 19. Ви т, диалогового окна приложения «1 Вменение свойств визуальных ком- понентов» Одним из важнейших событ ий в цикле работы программы, созданной средствами Delphi, является собы гие OnPaint. Оно возникает в тех случаях, когда
188 П aba 5. Технология создан и; программ е сг ь DELPHI. ядру Windows необходимо перерисовать содержимое формы. Причиной этому может быть получение формой фокуса, или переход формы в видимое состояние из невидимо! о (метод Show) г юрод каждым использованием вы юва Gthtl. 5.11. Свойства, методы и события CANVAS Все графические операции выполняют ся с использованием свойства С ап - vas, которое поддерживается многими компонентами. Например, свойство Canvas есть у формы. Свойство Canvas олицетворяет интерфейс графических ус гройств Windows (Graphics Device interface - GDI) и обеспечивает независимою от уст- ройств область рисования графических объектов в окнах. Свойство Canvas ис- пользуется. • для конфи! урации графического объекта в результате присваивания свойствам и подсвойствам Canvas цветов, шаблонов, шрифтов и дру- 1 их значений; • для создания графических фигур пу тем вы юва графических методов. В процессе разработки свойство Canvas недоступно в окне Object Inspec- tor. Чтобы использовать Canvas, надо написать операторы, которые присваиваю> свойствам Canvas значения и вызывают методы Canvas в обрабстчике события OnPaint. Событие OnPaint возникает в тех случаях, когда ядру Windows необхо- димо перерисовать содержимое фирмы. 11ричиной этому может быть получение формой фокуса или переход формы в видимое состояние из невидимого (был вы- зван метод Show). Свойства Canvas нельзя предварительно сконфигурировать в обработчике события OnC reate. 5.11.1. Основные свойства класса TCanvas Свойство Brush Это свойство позволяет задат ь цвет и шаблон запо тнения (кисть при графических операция х). Эт о свойство имеет тип fBrush и представ- ляет собой экземпляр этою класса. О свойствах класса 1 Brush рассказывается ниже. В данном примере показано, как и вменить цвет кисти на красный: Canvas Brush.Color := clRed; Свойство CopyMode. Устанавливает режим копирования - т о, как класс TCanvas будет воспрои гводит ь графические изображения. По умолчанию исполь- зуются значение cmSreCopy, указывающее на то. что изображение просто копи- руется, замещая текущее изображение. С помощью и гмеиения значений свойс гва CopyMode можно добит ься различных визуальных эффектов. Свойство 1'ont. Свойство Fonl является экземпляром класса ТЕ.mt и по- зволяет указать параметры текс га, отображаемого к гассом TCanvas. В приведенном ниже примере показано, как измени гь ат рибуты шриф га With Canvas do Begin Pen.Width := 20; Rectangle( 10, 10, 100, 100): End; Свойство Pen. Свойство Pen позволяет задать тип '‘карандаша'' - инстру- мента, используемого для отрисовки линий и границ геометрических фигу р. Свойство Реп является экземпляром класса 1 Реп. Свойство PenPos. Свойство РепРоз задает текущую позицию "каранда- ша”. Для изменения значения этого свойс гва используется метод MoveTo. Срав- нивая это свойст во с атрибутом дисплейного контекста Current Pen Position, мож-
Высокоуровневые методы информатики и программирования. 189 но увидеть - они имеют одинаковое назначение. Свойство Pixels. Свойство Pixels представляет собой массив, содержащий цвета пикселей, находящихся в классе Tcanvas. Этот массив является двумерным. Для доступа к отдельным пикселям достаточно указать их X- и Y- координаты. Пример 10. Отобразит ь прямую линию, не прибегая к использованию метода LineTo. Чтобы отобра 5ить прямую линию, надо создать обработчик события фор- мы Form OnPaint и в тексте процедуры написать операторы для рисования на форме: Procedure TForml.FormPaint(Sender: TObject); Var I := Word; Begin With Canvas do Begin For I1 to 100 do Pixelsjl, 10J := clBlue. End, End, End; Примечание. Обычно массив Pixels используется для изменения значений отдельных пикселей. Для отображения геометрических фигур удобнее воспользо- ваться методами класса TCanvas. 5.11.2. Методы класса TCanvas Прежде чем, рассмотреть методы класса 1 Canvas, следует отметит ь, что эти методы, в большинстве случаев, являются прямыми аналогами соответст- вующик функций Windows API и имеют почти всегда те же параметры. Метод Аге С помощью этого метода отображается дуга эллипса. Центром эллипса считается центр охватывающего прямоугольника, левый верхний угол которого имеет координаты X1,Y1, а правый нижний угол - координаты X2.Y2. Дуга ото- бражается из точки с координатами X3,Y3 в точку с координатами X4,Y4 против часовой стрелки. Если начальная и конечная точки имеют одинаковые координа- ты, то вместо дуги отображается полный эллипс (окружность в случае, если охва- тывающий прямоугольник является квадратом). Этот метод эквивалентен стан- дартной функции Аге. 11ример работы фрагмента программы, представленный ниже, показан на рис. 20. Procedure TForm 1 .FormPaint(Sender: TObject); Begin W ith Canvas do Begin Pen.Width ;= 5; Arc( 10,20, 200, 100, 100,0,0 ); End; End;
190 Глава 5 Технология создания программ в среде DELPHI. Рис. 20. Пример использования функции А1 с Метод Chord С помощью это1 о мет ода рисуется хорда - прямая линия, соединяющая две точки эллипса. Центром эллипса считается центр охватывающего прямо- угольника, левый верхний угол которого имеет координаты XI, \1, а правый нижний угол - координаты Х2. Y2. Хорда отобража< гея из т очки с координатами ХЗ, Y3 в точку с координатами Х4, Y4. Этот метод эквивалентен с гандартт эй функции Choi d. Рис 21. Пример использования функции С hoi d I [ример работы фрагмента программы, предс гав тенный ниже, показан на рис. 21. Procedure ТFormi .FormPaint(Sender: TObject); Begin With Canvas do Begin Pen Width := 5; Chord( 10. 20.200, 100, 100. 100.0, 0), End: End; Метод CopyRect С помощью метода CopyRect выполняется i опирование фрэгмен га изо- бражения. Этот метод реапи туе г те же дейс гвия, что и ме год Сору. Единственным отличием является возможност в задания прямоугольной области CopyRect явля • ется аналогом стандарт ной функции StretchBlt. Ниже показано, как скопировать изображение и s одной формы в другую.
ЗЛСОКОУРОВ! 2ВЫЕ МЕТОДЫ Щ ФОРМЕНКИ И ПРОГРАММИРОВАНИЯ 191 Form2 Canvas CopyMode := cinNotSrcCopy; Form2 Canvas.CopyRectt ClientRect, Canvas, ClientRect); Метод Draw >гот метод используется для отображения графического объекта типа TGraphic в точке, заданной координатами (X, Y). Метод DrawFocusRect Метод 1 )rawFocusRect используется для отрисовки прямоугольника, кото- рый обычно применяется при отрисовке кнопки по ту чившей фокус. >тот метод является аналогом стандартной функции DrawFocus Rect. Метод Ellipse Метод Ellipse используется для от рисовки эллипса, заданного охваты- вающим прямоугольником. Координата левого верхнего угла прямоугольника задается парой (XI Y1), а координата правого нижнего >гла- парой (X2,Y2j Этот метод является аналогом стандартной функции эллипс. ] тример использования этого метода показан ниже (пример 11), а результат работы фрагмента кода - на рис. 22. Пример 11 Нарисовать на форме желтый эллипс с координатами (10,10), (100,100) , заполненный голубыми диа1 ональными ш грихами, Procedure 1 Forml .FormPaint(Sender: 1 Object); Begin Vv ith Canvas do begin Pen.Coloi := cl Yellow; Brush.Color .= clBlue; Brush.Style := bsBDiagonal; Ellipse! 10,10,100,100); End; End; Рис. 22 Пример использования метола Ellipse
192 Глава 5. Технологи ] создания г°р рамм в с °ед е DElPHI Метод FillRect С помощью метода FillRect выполняется заливка указанного прямоуголь- ника цветом. 1 оторый задан значением свойствам Brush Coloi. Это г метод являет- ся аналогом стандартной функции FillRect Ниже показано, как использовать этот метод (пример 12). Пример 12. Нарисовать на форме красный прямоугольник с координатами (20,20). (150.150). Procedure TForml.FormPaint(Sender. TObject); Var R: I Rect; Begin R. Rect(20, 20, 150, 150); With Canvas do begin Brush.Color := clRed; FillRect( R); End; end; Метод FloodFill Метод F loodbill используется для заполнения области цветом, заданным значением свойства Brush Заполнение начинается с точки с координатами X.Y. Каким образом будет происходить запо тнение, определяется значением парамет- ра FillStyle . 1 гли свойство FillStyle имеет значение fsBorder, то область, которая будет заполнена, ограничена ивет ом. заданным параметром Color. Если же свой- ство FillStyle имеет значение fsSurface, то область заполняется до тех пор, пока в ней присут ствует цвет, заданный параметром С< >1ог. Обычно значение fsSur1 асе используется для заполнения областей, имеющих многоцветную границу. Этот метод является анало1 ом стандартной функции ExtFloodFill. Метод LineTo Метод LineTo используется для отрисовки прямых линий. Линия отобра- жается из текущей точки (определяемой значением свойства РечРо1) в точку с координатами X. Y. После отображения прямой линии свойство PenPos принима- ет значение X. Y. Метод MoveTo Метод Move! о изменяет координаты текущей точки, определяемой зна- чением свойства PenPos. Для изменения координат текущей точки следуе г поль- зоваться именно ггим методом, а не непосредст венно изменять значение свойства PenPos. Этот метод явзяется аналогом стандартных функций MoveTo. Пример использования метода показан ниже (пример 13). Пример 13. Нарисовать треугольник с вершинами в точках (50.50). (150.50). (100 150) синим цветом и вывес ги на форму точку с координа сами вне тре) голышка. Procedure TForm 1 FormPaintl Sender: TObject)
Высокоуровневые методы информатики и программирования. 193 Begin W:th Canvas do begin Pen.Color;= clBlue. MoveTo(50.50); LineTo(] 50.50): LineTo(100.150); LineTo(50.50); Pixels[50,10J :=clBlack; {50<x< 150; 50 <у < 150} TextOut(60,l0,’X = 50' + + Y = 10’). end; End; Рис. 23. Пример рисования треугольника по заданным координатам Пример 14 Написать процедуру очистки экрана и рисования координатных осей. Клиентская область экрана ClientRect Procedure DelScr os; With Canvas do begin Brush.Color := clWhite Pen.Color := clBlack: FillRect(ClientRect); MoveTo(20, 20); LineTo(20. 300); LineTo(500.300); end; end; Метод Pie Метод Pie используется для отрисовки сегмента эллипса, заданного охва- тывающим прямоугольником с координатами XI.Y1 и X2.Y2. Сегмент определя- ется двумя линиями, соединяющими центр эллипса с точками с координатами X3,Y3 и X4.Y4. Этот метод является аналоюм стандартной функции Pie. Пример
194 Глава 5. Ti хпология созда) ия программ е сргд! D'-LPHI использования этого метода показан ниже (пример 15), а резу штат рабпты фраг- мен га кода - на рис. 24. Пример 15. Написать процедуру рисования сегмен га эллипса, заданноп охватываю- щим прямоугольником с координатами (10.10) и (200,2001 Сегмент определяется двумя линиями, соединяющими центр э. глипса с точками с координатами (60.3) и (200.60). Procedure TForml. Гонг Paint( Sender: TObject); Begin With Canvas do Pie( 10. 10, 200. 200. 60 3. 200. 60); end; End; Рис. 24. J 1ример использования метода Pie Метод Polygon Метод Polygon используется для отрисовки замкнутого много ранника. заданного массивом координат. Этот метод является аналогом стандарт ной фу нк- ции Polygon. Пример использования этого метода показан ниже (пример 16). а резуль гат рабо гы фрагмен га кода - на рис.25. Пример 16 11аписать процедуру рисования замкнуло) о мног о) ранника, заданно о массивом координат (10.10). (30,10). (130.30) и (240 1201 Procedure TF о-m l.FormPaint( Sender: TObject). Begin W tth C anvas do Begin Brush.Color := clRed; Polygon! | Point( 10. 10 ). Point( 30. 10 ). Point( 130, 30 ), Point( 240. 120 1 ] ); End; End;
Высокоуровневые метсдь инфсгмап ки и программ, рования. 195 Рис. 25. ] 1ример использования метода Polygon Метод PolyLine Метод Poly Line используется для отрлсовки незамкнутою многогранни- ка, заданного массивом координат. Этот мез од является аналогом стандартной функции PolyLine. Пример использования этого метода показан ниже (пример 17), а результат работы фра) мента кода на рис. 26 Пример 17. Написаз ь процедуру рисования незамкнуз ого многогранника заданного массивом координаз (5,5) , (”100,40), Г150 120) и (240, 200). (80. 100), ( 5 5). Procedure Т1 orml. Form Paint) Sunder 1 Object); Begin With Canvas do Begin Pen.Color := c IBlack; PolyLine( [ Point) 5, 5 ), 1 *oint( 100, 40 ), Point( 150, 120 ), Point) I 10, 200 ) Point) 80, 100 ), Pointf 5, 5 ) | ); End; End; Рис. 26. Пример использования мез ода PolyLine Метод Rectangle Метод Rectangle используез ся для отрисовки прямоу гольника, заданного координатами его левого верхнего (XI. VI) и правою нижнего углов (Х2. ^2) Этот метод является аналогом стандарз ной функции Rectangle. Метод RoundRect Метод RoundRect используезся для оз рисовки прямоуз ольника с закруг-
196 Глчса 5. Техкл .1Гия создания программ в ср -де DELPHI. ленными углами. Координаты левого верхнего угла задаются параметрами XI, Y1, правого нижнего - параметрами Х2, Y2, а размеры четвертей эллипса, кото- рые будут отображаться в углах прямоугольника, параметрами ХЗ (ширина) и Y3 (высота). Этот метод является аналогом стандартной функции RoundRect. Пример использования этого метода показан ниже (пример 18), а результат рабо- ты фрагмента кода на рис. 27. Пример 18. Написать процедуру рисования прямоугольника с закруглен- ными углами, заданного параметрами - массивом координат (15,15),(250,200),(50,50). Procedure Tlorml.FormPainti Sender: TObject), Begin Vv ith Canvas do Begin Pen. Width := 5; Pen.Color := clBlack; RiundRect( 15, 15. 250, 200. 50, 50 ); End; End; Метод StretchDraw Метод Stretchl )raw используется д is отображения графического изобра жения в указанном параметром Rect прямоугольнике. С его п эмощью возможно масштабирование графических изображений. Этот ме год вы зывае г метод 1 )raw экземпляра класса TGraphic, переданного ему в качестве параметра. Метод TextHeight Метод TextHeigth возвращает высоту' строки, переданной в параметре text, в пикселях. Высота строки высчитывается относительно текущего шрифта (свойство Font). Обычно это г метод используется для правильного позициониро- вания строки. Метод TextHeight является аналогом стандарт ной функции Def] ех- tExtent. Метод TextOut Метод TextOut выводит строку, переданную в параметре Text, в т очке, указанной координатами X, Y. Эта точка задзе г координаты левого верхнего у гла прямоугольной области, в которой будет размешен текст. Например, чтобь вы- вести строку "Delphi is environment for Windows programming" в точке с коор щ-
Высокоуровневые метсды инфо°магики и программирования 197 натами (10, 10), можно написать следующий код: Canvas.TextOut(20, 20, Delphi is environmeni loi W.ndows programming). Метод TextWidht Метод TextWidht возвращает ширин) строки, переданную в параметре Text, в пикселях. Ширина строки высчитывается относительно i ек) щего шрифта (свойство Font). Обычно этот метод используется для правильного позициониро- вания строки Данный метод является аналогом ст андартной функции GetTextEx- tent. Пример 19. Пусть имеется компонент типа TEdit, в котором предо > iai ает л отобра- жение различных строк Ниже показано, как. используя метод T extWidht. опреде- лить, требуется ли изменит ь горизонтальный размер компонента, чтобы в нем могла быть отображена вся строка. Требуется создать обработчик события формы Form OnPaint. В тексте процедуры необходимо написать операторы для рисования на форме. Procedure TForml. FormPaintlSender: TObject); Var S: String: Begin S := ' Delphi is environment for Windows programming If Canvas.TextWidhtl S ) > Edit! Widht then Fd'tl.Widht := Canvas.TextWidht( S ) + '0. Editl.TexI : S; End; End; 5.11.3. Рисование на поверхности формы с использованием свойства Canvas Пример 20. Выполнить вывод на поверхность формы изображения домика (см. рис. 28). Для построения и юбражения используются фигуры эл гипса, прямоу] ель- ника и многоугольника. Управление цвет ом и заливкой фигур осущест вляется с помощью классов кисти и пера. 1 Сод, выполняющий отображение рисунка, расположен в обработчике со- бытия OnResize формы, поэтому при изменении ее размеров рисунок перерисо- вывается заново, учитывая новые размеры формы Методы, выполняющие по- строение изображения. использ)тот координаты точек, которые заданы относи- тельно высоты и ширины формы, поэтому рисунок всегда занимает всю клиент- скую область формы, независимо от ее размеров Ниже приводится после цова- тельность действий, обеспечивающих решение задачи. 1. Создать при тожение с пустой формой File/New Application. 2. Создать обработчик события формы Form OnResize. В тексте процеду- ры напчеат ь операторы для рисования на форме. 2.1. Объявить переменные д тя координат (wm - ширина рису нка, hm- высота рисунка, w-ширина элемен га рисунка, h-высота элемента рисунка)
198 Глава 5.1 экология создания про pamij в среде DELPHI var w, h, wm, hm: integer; 2.2. В теле процедуры написать. Form I .Refresh; { Для обновления } Win := Foi ml .ClientWidth; w := wni div 8; { Определение размеров] Hm := form! .ClientHeight; h := hm div 10, 2.3. Написать оператор With ...для свойства Canvas фермы, что означает возможное гь рисования на форме: With Fonnl .Canvas do begin end; В этом операторе в операторных скобках begin .. .end поместит ь опера го- ры рисования на форме 2.4. Для рисования неба Brush.Color := clBlue; Brush.Style := bsDiagCross; Pen.Color := clBlue; Rectangle(O. 0, wm, h): 2.5. Для рисования травы: Brush.Color:- clGreen; Brush.Style := b.DiagCross; {bsl lorizontal;} Pen.Color := c IGreen; Rectangle(0, hm-h. wm. hm); 2.6. Для рисования солнца: Brush.Color :- cl Yellow; Brush.Sty le := bsSolid; Pen.ColorclY ellow; Ellipse(w, 2*h. 2*w. 2*h + w); 2.7. Для рисования домика" Brush.Coloi clGray; Brush.Style bsSolid; Pen Color clMaroon; Rectangle(2*w, hm -5*Ь, 6*w, hm-h); Polygont[Point(2*w, 1 im-5*h), Point(4*w, hm-7*h), Point(6*w, hm-5*h). Point(2*w', hm-5*h)]); Brush.Color := clW hite; Brush.Style := bsSolid; Pen.Color := clMaroon; Rectangle(3*w. hm-4*h 5*w, hm-2*h); 3. Сохранить модуль (Save...). О гкомпилировать программу. Выполнить Текст программы: Unit Unitl; Interface Uses Windows, Messages. SysUtils. Classes. Graphics. Controls. Forms, Dialogs; Type TForm 1 - class(TForm)
Высокоуровневые методы информатики и программирования. 199 Procedure Form Resized Sender: TObject); Private { Priv ate declarations } Public { Public declarations } End; Var Formi: TForml; Implementation {SR *.DFMJ Procedure TForml.FormResize(Sender. TObject); Var w, h. wm. hm integer; Begin Formi. Refresh wm := Formi.Client Width; w :~ wm div 8; hm := formi .ClientHeight; h : - hm div 10; With Form 1 .Canvas do begin // Небо Brush.Color := clBlue; Brush.Style := bsDiagCross; Pen.Color := clBlue; Rectangle(0,0,wm,h)- // Трава Brush.Color := clGreen; Brush.Style := bsDiagCross: ) bsHorizontal;} Pen.Color := clGreen; Rectangle(0, hm-h, wm, hm); // Солнце Brush.Color := clYellow; Brush.Style := bsSolid; Pen.Color :- clYellow; Ellipse(w, 2*h, 2*w, 2*h+w); // Домик Brush.Color := clGray; Brush.Style := bsSolid; Pen.Color := clMaroon; Rectangle(2*w, hm-5*h,6*w, hm-h); Polygon([Point(2*w, hm-5*h), Point(4*w, hm-7*h), Point(6*w, hm-5*h), Point(2*w. hm-5*h)]); Brush.Color .= cl White; Brush.Style bsSolid; Pen.Color := clMaroon; Rectanglc(3*w, hm-4 *h, 5*w, hm-2*h); End; End; End.
200 Глава 5. Технолог ия созда! ия программ в среде DELPHI Рис. 28. Вид окна приложения "Домик'' 5.12. Обработка исключительных ситуаций Исключительная ситуация — это изменение условий выполнения про- граммы. вызывающее прерывание или полное прекращение выполнения. Одним из источников исключительных ситуаций являются ошибки выполнения, т. е, ре- зультат неправильной работы функций, процедур или методов из библиотеки подпрограмм (Run-Time Library - RTL), библиотеки визуальных компонентов (Visual Component Library VCL), операционной системы (Operating System OS). Следует предвидеть ошибки, которые могут возникнуть при выполнении программы, и программировать их обработку. Интегрированная среда разработчика (Integrated Development Environment - IDE) Delphi содержит мощный набор средств отладки По умолчанию, если ис- ключительная ситуация возникает при работе программы в IDE. отображается сообщение об ошибке и указывается строка, в которой произошла ошибка. Встро- енный процесс обработки исключительных ситуаций состоит в открытии диало- гового окна с сообщением о типе возникшей исключительной ситуации. При ре- шении реальных задач следует предусматривать специальные обработчики ис- ключительных ситуаций. Для отладки программного обработчика исключитель- ных ситуаций нужно отключить опцию прерывания выполнения после исключе- ния. Для этого при работе в среде Delphi нужно вып олнить действия: • в меню IDE выберать команду Tools/Debugger options; тогда откроется диалоговое окно Debugger options; • выбера гь вкладку Language Exceptions; • отключить опцию Stop on Delphi Exceptions. В Delphi определены две конструкции для обработки локальных исключи- тельных ситуаций: Try ... Finally и Try ... Except.
лГ Вычисление определен»! >го интеграла методом трзг» :ций Вычисление определенного инт еграла на отрезке [а Ь] ат функции f(xl-ос Sinx не годом трапеции Рис. 29. Вид форм приложения но время выполнения Сверите значения а 50 Ь [50 ~ ь |о,О1 Дычиспить □пр интеграл на отрезке [-50 50] рае» я ?? (г 8 (Погрешность еынисления 0.01) N Ki | 1. J тЩ 14,0530386751175 —’ 49,9609375 -1 * 9812^19123837 3. 4. .49.94140625 -15 9030026556869 •49,921875 -16.8179738988762 5. •49,90234375 -17.7258115015696 6. •49.8828125 -18.6261743185658 7 •49.86328' 25 -19 5187243280104 гй Ь -43.8Л375 -20/03126/582654 -49 82421875 -21 2790502134377 Ю- 19.8046875 22 1461667975158 11 49.78515625 -23 0041522370719 иг 49.765625 -23 8526860024802 13 -49 746093"5 -24.69'451427F™3 14 -49 7265625 -25.5201 J532 /940 / 15. 49 70703125 -26 3384306170727 lift 49.6875 -27,1460314215633 , Выход «1 I с¥: чй ' И м:; В„.СОКОУРОЕ НЕВЫЕ НЕТОДЬ. И 1ФОРРАТИКИ И ПРО РАММИР^ВАНИЯ. Nj О
202 Глава 5. Технология создания программ в сре£е DELPHI, 5.12.1. Назначение конструкции Try ... Finally Конструкция Try ... Finally применяется д 1я перехвата исключительной ситуации, когда надо выполнит ь все полагающиеся перед завершением npoi рам- мы действия. Эта конструкция не обрабатывает ошибки, а освобождает ресурсы. Блок Finally 1 арантирует выполнение содержащихся в нем операторов, обработ ка иск. [ючит ельной операции передается на следующий уровень или передается гло- бальному обработчику. Схема со щания блока защищенных ресурсов: { Выделение памят и или других ресурсов } Try { Операторы, способные вызвать генерацию исключительной ситуации} Finally' { Освобождение ресурса} End; 5.12.2. Назначение конструкции Try... Except Конструкция Try' ... Except применяется для перехвата исключительной ситуации с последующей обработкой, предусматривающей освобождение экзем- пляра исключительной ситуации, после чего выполнение программы продолжает- ся как обычно. Схема создания блока защищенных операторов: {Незащищенные операторы} Try {Защищенные операторы, способные 1 енерировать исключительную ситуацию} Except {Обработка всех генерируемых исключительных ситуаций} on Е: Exception do {Операторы обработ ки исключительной ситуации определенного т ипа} else {Операторы обработ ки остальных исключительных ситуаций} end; В конструкции Try .. Except содержится необязательный элемент on ...do, с помощью которого можно определить фактический тип исключительной ситу'ации и указат ь действия. Иден гификатор L - ссылка на экземпляр об ьекта обработки исключительной ситуации. Конструкция On L: Exception указывает на исключительную сит уацию любого типа Класс! xception базовый для всех т и- пов исключительных ситуаций. В конкретных случаях можно проверить исклю- чительную ситуацию на принадлежность к типу, например: F.ConvertFrror - Ошибка преобразования; EzeroDivide - Попытка разделить значение с плавающей точкой на ноль: ERangeError - Значение за пределами диапазона дону с гимых значений; Г OverFlow - Переполнение значения с плавающей точкой; EOutOfMemory -11евозможно выделить память требуемого объема; EAccessViolation - Недос гаточно распределенной памяти. Таким образом, обработка ошибок в операторе Except ставит задачу' раз- решения исключительных ситуаций, которые могут возникнуть в стоке защи- щенных операторов, следующих за командой Ггу. 'Эти ситуации проиллюстриро- ванны в примере 21.
Высокоуровневые методы информатики и программирования. 203 Пример 21. Ввести чис. ювое значение в поле редактирования и обеспечить коррект- ность ввода для последующего преобразования ввс (енного значения в цеЖе чис- ло. Дл я решения этой задачи создается приложение, на форму помещается компонент TEditl. Даюе нужно организовать обработчик события OnChange компонента Tedit, для этого достаточно дважды щелкнуть на событии OnChange на вкладке Events Delphi аенерирует заготовку метода, который выглядит сле- дующим образом: Procedure TFormMati EditlChangefSender: TObject), Begin End; В эту процедуру требуется ввести операторы Procedure 7 FormMati .EditIChangei Sender: TObject); Begin Tiy n := SirToInt(Ednl .text) Except on E: EConvertError do Begin n := 0; End; End; End; В том случае, если в поле редактирования вводится символ, не являю- щийся цифрой, при выполнении процедуры преобразования StrToInl создается исключительная ситуация, и выполнение передается первому' оператору', с пе- дующему за командой Except В конструкции on ... do исключительная ситуация проверяется на принадлежность к типу EConvertError. Если экземпляр объекта обработки искпочительной ситуации относится к этому типу, то выполняется оператор, предусмотренный для случая некорректного ввода п := О 5.13. Примеры проектирования приложений 5.13.1. Разработка приложения, реализующего работу с таблицей, содержа- щей I рафическис данные Пример 22. Разработать приложение, реализующее работ с таблицей, со- держащей графические данные. Предметная облает ь: Информация о животных. Задание: Разработать приложение, позволяющее: • отображать и редактировать информацию из таблицы Animals.dbf базы данных DBDEMOS, предстазляющих символьные и числовые данные; • отображать поля BLOB (растровое изображение) таблицы Animals.dbf. Исходные данные: имя базы данных DBDEMOS; путь к базе данных - ...Delphi\Demos\Data\; структура записей приведена в таблице 15
204 Глава 5. Технолога создания программ в среде DELPHI. Структура записи таблицы Animals.dbf (Животные) 1 аблица 15. Идентифика гор поля Формат 11римечание Name СЮ Название Size N2 Размер Weight N2 Вес Area C20 Область Bmp В Изображение Памятка. Для перехода между окном Редактора кода и Проектировщика форм нужно нажат ь на клавишу F12. Для вызова окна Object Inspector - нажать на клавишу Fl 1. Для выполнения задания следует использовать следующий алгоритм: 1. Создать приложение в среде Delphi. Для этого выбрать из меню File команду New Application. 2. Добавить в приложение модуль данных (форму Data Module) для обеспечения доступа к данным. Для этого в меню File выбрать команду New Data Module. В результате в проект добавится форма Data Module2. 3. Сохранить проект и его модули в отдельной папке, выбрав из меню File коман- ду Save As. 4. Поместить на форму Data Module2 компоненты Table и DataSource со страницы Data Access палитры компонентов. Наст рои гь компоненты для работы с таблицей Anitnals.dbf.: • Выделить на форме компонент TTablel, и в окне Object Inspector уста- новить значения свойств: В строке DataBaseName выбрать из списка DbDemos; В строке TableName выбрать из списка Animals.dbf; В строке Name написать tbAnimals; В строке Active выбрать значение 1 rue. • Выделит ь на форме компонент 1 DataSource 1. и в окне Object Inspector ус гановш ь значения свойств: В строке DataSet выбрать из списка tbAnimals; В строке Name написать dsAnimals. В результате этих действий будет обеспечен доступ к данным таблицы из Animals.dbf базы данных DbDemos. 5. Перейти на форму Formi. Подсоединить к форме Formi модуль данных Data Module2. Для этого в меню File выбрать команду Use Unit... и далее в диалоговом окне указать присоединяемую форму Data Module2. В результате в редакторе ко- да формы Form 1 в разделе implementation добавится оператор Uses unit2. 6. Проектирование интерфейса формы Formi. 6.1. В окне Object Inspector установить значения свойства Caption для формы. Для этого в строке Caption написать: Сведения о животных. 6.2. Поместить на верхнюю часть формы со страницы Data Controls компонент dbNavigator. Он предназначен для навигации по набору данных Animals.dbf. Выделить компонент TdbNavigatorl для настройки компонента на набор данных. Для этого в окне Object Inspector в с гроке DataSource выбрать из списка DataModule2.dsAnimals. Для того, чтобы озображазась подсказка при выборе кнопок Навигатора, надо установить свойство Show Hint True (по умолчанию False).
ВКСОКОУРОВНЕРЫЕ МЕТОДЫ ИНФОРМАТИКИ И ПРОГРАММИРОВАНИЯ. 205 6.3. Поместить на форму со страницы Data Controls компонент таблицы данных TdbGrid. Он предназначен для отображения и редактирования данных таблицы Animals.dbf. Для присоединения компонента к данным таблицы, выделить компонент dbGridl. и в окне Object Inspector установить значения свойств, в строке DataSource выбрать из списка DataModule2.dsAnimals. В результате на форме должны появит ься данные в столбцах таблицы Animals.dbf. 6.4. Поместить на форму со страницы Data Controls компонент dblmage. Он пред- назначен д. 1я отображения поля таблицы с растровым изображением Blob, обо- значенного Bmp в таблице Animals.dbf. Для присоединения компонента к данным таблицы, выделить компонент 1 dblmage 1. и в окне Object Inspector установить значения свойств: в с троке DataSource выбрать из списка DataModule2.dsAnimals. В результате на форме должны появиться данные в ст олбцах таблицы Animals.dbf: в строке DataField выбрать и з списка название поля Bmp. В результате на форме до 1жно появиться изображение в окне данных. В результате проектирования формы будет разработано приложение, предназначенное для просмотра и редактирования данных т аб .ицы Animals dbf из БД DBDemos. Для проверки работ ы приложения можно сохрани гь приложение на дан- ном этапе разработки и откомпилировать его. Д. 1я сохранения модуля и проекта выбрать в меню File команду Saxe. Для компиляции выбрать кнопка Run на пане- ли инструментов или команд) Run в меню Run. Рис 30. Вид формы приложения во время выполнения 7. В результате проектирования формы будет разработ ано приложение, предна- значенное: • для просмогра и редактирования данных таблицы Animals.dbf из БД DBDemos, представляющей данные о животных; • реализована возможность графического изображения полей записей таблицы.
206 Приложена f ПРИЛОЖЕНИЕ 1. Краткое описание команд главного меню Delphi Меню File В меню File находятся команды для выполнения операций с проектами, модулями и файлами (см. табл. 16). Iаблица И Команда Клавиши Описание команды New... Отображает диалоговую панель New' Items, по- зволяющею выбрать тип со (даваемого ълемен- т а New Application Создает новый проект, состоящий из формы, модуля, фай ла проекта New Form Создает новую форму и добавляет ее к проекту New Frame Создает новый композитный компонент и до- бавляет его г проекту Open... Отображает диалоговую панель Open, позво- ляющую открыть проект, модуль, форму, файл Open Project... Ctrl + Fl 1 Отображает диалог ову ю панель Open, позво- ляющую откры гь проект Reopen Позволяет повторно откры гь ранее закры гые проекты и моду ги Save Ctrl + S Сохраняет текущий проект с заранее заданным именем Save As... Сохраняет текущий моду гь с новым именем Save Project As... Сохраняет текущий проект с новым именем Save All С охраняет все открыт ые файлы - проект и ис- пользуемые модули Close Закрывает текущий проект и ассоциированные с ним модули и формы Close All Закрывает Вч е открытые фай ты Use Unit... Добавляет имя указанного модуля в список ис- пользуемых модулей (Uses) текущего активно- г о модуля Print... 1выводит содержимое активного файла на уст- ройство печати Exit Закрывает открыт ый проект и завершает работу D, Iphi Меню Edit В меню Edit находятся команды, осуществляющие операции редактиро- вания, работы с областью обмена данными, отмены действий, управления ото-
Вь ДЖОУРОВНЕВЫЕ МЕТОДЕ ИНС РМАТИКИ И ПРОГРАММИРОВАНИЯ 207 бражением компонентов (см. таблице 17) Таблица 17 Команда Клавиши Описание Lndo Ctrl + Z Отменяет выполненные действия Redo Shift + Ctrl + Z Восстанавливает выполненные действия Cui Ctrl + X Вырезает выделенный объект и номещае г его в область обмена данными Copy Ctrl + C Копирует выделенный объект и помещает его в область обмена данными Paste Cti 1 + V Копирует содержимое области обмена дан- ными в редактор и ти на форму Delete Ctrl + Del Удаляет выбранный объект Select All I [омечает все компонен гы на форме как вы- бранные или текст в редакторе кода как вы- деленный Align to Grid Выравнивает выбранный компонент Bring to ] 'rant 11еремещает выбранный компонент поверх других компонен гов Send to 1 lack Отменяет действия команды Bi ing to Front Align... Выравнивае г компонент ы Size... Изменяет размер компонентов Scale... Изменяет размер все> компонентов на фор- ме Tab Order... 11зменяет порядок табуляции компонен гов в активной форме Creation Order... Задает порядок следования невизуиьных компонентов Flip Children ► All Selected Меняет расположение компонен гов справа налево и наоборот Lock Controls Запрещает перемещение компонентов внут- ри формы Add to inter- face Определяет процедуру. функцию, свойс гво для ActiveX компонента Меню Search Меню Search предоставляет команды дтя поиска и замены, а также ко манды для поиска указанных символов и строк, содержащих ошибки, найденные компилятором (см. табл 18).
208 П ’ИЛОЖсНИЯ. Таб шца 18 Команда Клавиши Описание Find... Ctrl + F Поиск указанного текста Find in Files... 11оиск указанной строки ь файлах проек га Replace Ctrl 4 R 11оиск указанного текста и замена его на новый текст Search Again F3 Повторный поиск Incremental Search Ctrl + E 11ог ск 1 екста по мерс его ввода Goto Line Number... Alt 4 G Перемещение курсора на указанну ю ст рс ку Find Error... Поиск ошибки времени исполнения Browse Symbol... 1 [Омск указании! о символа Меню View В меню View содержатся команды для отображения различной информа- ции и вызова менеджера проектов, инспектора объектив и дру! их информацией - ных утилит (см. табл. 19). Т аблица 19 Команда Клавиши Описание Project Manager Ctrl + Alt + Fl 1 Менеджер проектов Object Inspector Fll 11нспектор объект ов Alignment Palette 11алитра выравнивания компонен- тов Browser Брау зер объектов Code F xplorei Проводник по коду Component List Список компонен гов Window List... A lH-0 Список окон Debug Windows Окно отладчика Toggle Form/Unit F12 Список форм и ни моду лей Units... Cld 4 F12 Список модулей Forms... Shift + Fl 2 Список форм New Edit Win- dows Новое окно редактора Toolbars На< тройка панели инстру ментов Меню Project Меню Project содержит команды для компиляции и сворки проектов, а также для установки опций текущего проек га (см. табл 20).
209 Высокоуровневые методы i'h-popma^hi и и программ» роьае ия 1 аблица 20 Команда Клавиши Описание Add to Project... Shift + Fl 1 Добави гь фай т к проекту Remove from Proj ect... Удалить файл из проекта Import Type Li- brary... Отображает диа юговую панель Import Type Library Add to Repository Добавить проект в репозиторий объектов View Source Исходный т екст проекта Add New Project... Отображает диалоговую панель New Items Add Existing Proj- ect... Отображает диалоговую панель Open Project Information Информация о проекте Compile All Projects Компилирует модули проекта Build All Projects Сборка проекта Options 1 Shift 4 Ctrl + Fll Отображает диатогову ю панель настройки опций компилят ора и компоновщика Project Options Меню Run В меню Run находятся команды для отладки npoi рамм. Эти команды по- зволяют управлят ь различными функциями встроенного отладчика (см. т абл. 21). Таблица 21 Команда Клавиши Описание Run Компилирует и выполняет программу Parameters... Задает параметры командной ст роки Step Over F8 Пошаговое выполнение программы Trace Into F7 Пошаговое выполнение npoi раммы с заходом в подпрограммы Trace to Next Source Line Shift + F7 Пошаговое выполнение npoiраммы до следующей с гроки исходного текста Run to Cursor Г4 Выполняет программу до строки в окне редактора, на которой находится курсор Команда Клавиши Описание Run Until Return Shift + F8 Выполнить до конца процедуры Show Г xecution Point Отображает с дедующую строку, кото- рая будет выполняться вслед за теку- щей строкой Program Pause Приостанавливае г выполнение про граммы Program Reset Ctrl + F2 Завершает выпопнение программы Fvalu- ate/Modify. . Ctrl + F7 I [озволяет узнать или изменить значе- ние переменной Add Watch... Ctrl ь Г5 Добав. гяет точку слежения за перемен- ными Add Breakpoint Добавляет точку останова _
210 Приложения Меню Component Меню Component содержит команды для создания i омпопентов. ус ганов- ки новых компонентов, перекомпоновки библиотеки компонен гов и конфигура- ции палитры компонент ов (см. т абл. 22). Таблица 22 Команда Клавиши Описание Nev» Component... Вызывает окно Мем Component Install Component... Устанав. швает новый компонент Import Active Control. . Добавить в па штру компонентов ActiveX компонент Create Component Template Создает ш< блок компонента Install Packages... Позволяет добавит ь и у .талить биб тиотеку компонен гов Configure Palette Вызывает диа юговую панель конфигурации палитры компо- нентов Меню Database Меню Database содержит среде гва Ьля работ ы с базами данных (см. табл. 23). Таб шца 23 Команда Клавиши Описание Explore Вызову ти тит ы SQL Explore! bQL Monitor Вызов у ти тит ы SQL Monitor Form Wizard Вызов Мастера форм для работы с таб- лицами ЬД Меню Tools Меню Tools предоставляет средства настройки среды, дополнительные утилиты, входящие в состав Delphi (см. габл. 24). 1аблица 24 Команда К (авиши Описание Environment Op- tions... Вы бывает диалоговую панель настройки среды Editor Options... Вы 5ывает диалоговую панель настройки редактора Debugger Options... Вызывает диалоговую панель нас тройки отладчика Repository... Вызывает диалоговую панель репозито- рия объект ов Configure Tools... Вызывает диалоге iву ю панель нас тройки меню инструментов Tool Options Database Desktop Вызов у гилиты DBD дчя работы с базами данных Image Editor Вызов графического редактора Image Editor
ВЫСОКОУРОВНЕЬЬ - МГТОД >1 Mt ФОРМАТМКИ И ПРОГРАММИРОВАНИЯ 211 ПРИЛОЖЕНИЕ 2. Описание страниц палитры ком- понентов Страница Additional Страница Additional (см. рис. 31) содержит дополнительный набор ком- понентов Windows. Stamm Additional | Win32 ] Susrem| Da*a Across 1 Da's ’ onti ж | JDO ThtetBase j И da’ | ft за IS i* 44b'J rfoг ЯП Рис. 31. Дополнительный набор компонент Дополнит ельные компонен гы De.phi перечислены в табл. 25 с некоторы- ми комментариями по их применению Таблица 25 Кнопка Назначение компонен га |урк TBitBln - кнопка т ипа TButlon, на которой можно разместит ь картинку (glyph). TBitDtn имеет несколько предопределенных типов (bkClose, bkOK и , гр.), при выборе которых кнопка при- нимает соответству ющий вид TSpeedButton - кнопка для создания панели быстрого доступа к командам. На ней может отображаться только рисунок бе з над писи (gly ph). Например, группа кнопок на панели инструмен гов SpeedBai слева от Палитры Компонент в среде D, phi. |##1 TMaskEdit - аналог 1 Edit, но с возможностью форм атированно- 1 о ввода. Формат определяется в свойс гве EditMask. В редакто- ре свойств для EditMask есть заготовки некоторых форматов: даты, валюты и т.п. ab( 1 StringG’ id служит для представления т екстовых данных в виде таблицы. Доступ к каждому элементу таблицы происходит че- рез свойство Cell. = -д' TDrawGrid служит для представления данных любогс типа в ви те таблицы. Доступ к каждому элементу таблицы происходит через свойство CellRect. I TImage создает объект для отображения рису нка на форме. Воспринимает форматы BMP (растрового изображения). ICO. (пиктограммы), WME (метафайла). Если картинку подключить во время дизайна программы, то она прикомпилируется к EXE фай. iy.
212 Приложения. Кнопка Па та чение компонента TShape с тужи г для отображения простейших геометрических фшур на форме. Сво. ство Style позволяет отобразить1 эллипс, прямоугольник, квадрат. крзг. __________________ 1 Bevel - элемент для рельефною оформления интерфейса. Свойство Shape определяет, отображает ли элемент управления 1 Вез el линию фаски, блок или кадр._______________ IScrollBox создаст об. га.гь прокрутки в форме, которая может содержать любые элементы управления. В этой области авто- мата ч ески отображаются линейки прокрутки,______________ TCheckListBox создает список аналогично компоненту ListBox с тем отличием, что перед каждым элемен гом списка распола- гается флажок.__________________ TSplitter (линия разбиения) позволяет динамически изменять размер элементов управления во время выполнения программы. TStaticText создает объект "нередактируемый текст”. аналогич- ный создаваемому компонентом Label с тем отличием, чго он имеет свой дескриптор окна. TControlBar предназначен для управления расположением па- нелей инсгр) ментов ТApplication Events добавляет компонент, перехватывающий события уровня приложения. 1 го можно использовать для оп- ределения на стадии проектирования обработчиков событий уровня приложения или для назначения обработчиков событий каждой отдельной форме приложения. 1 Chart служил для добав тения в пршрамму профессионально оформленных диаграмм и графиков. Страница Win32 Страница Win32 (см. рис. 32) представляет дос гуп к общим компонентам пользовательского интерфейса для Windows 95Z98/NT. Рис. 32. Набор компонент страницы Win32 Наиболее част о вст речающиеся компоненты страницы Win32 перечисле-
BolCOkOyPObrlLBclE Г El ОДЫ И1 ФОРНАТИКИ И ПР.ГРАМ WPOEA 1ИЯ 213 ны в табл. 26 с некот орыми комментариями по и к применению. Таблица 26 Кпопка Назначение компонента : » ITabControl отображает вкладки вдоль верхней границы, но не имеет встроенных с границ. Название вкладки задается в свойств Caption. Булево свойст во MultiLine управ тяет поведением вкладок. —4 X. TPageControl используется для создания многостранично! о диалога в ] »амках одного окна. Чтобы добавить с границ}' во время разработ - ки притожения, надо щелкнуть правой кнопкой на выбранном эле- менте управления и указать в контекстном меню New Page. j Tlmagelist создает объект - список, являющийся набором изобра- жений одинакового размера. Каждый элемент списка может быть дос гу пен по его индексу. Этот элемент управления используется при организации доступа к большому числу пиктограмм или рас- тровых изображений. Для добавления изображений в список с те- дуст вызвать редактор Image 1 ,ist Editor, выполнив на вставленном компоненте двойной щелчок мышью. 7^1 TRichEdit предназначен для создания поля редактирования с под- держкой форматирования, что включае г в себя во шожность вы- бора имени шрифта, размера, цвета, определения выравнивания, отступов, табуляции (свойство Paragraph), перемещения мышью выделенного фрагмента текста ^свойство Sei Attributes управляет атрибутами текста внутри выдетенною интервал символов, DefAttributes - управ тяет атрибутами остального текста; III TTrackBar позволяс г интерак гивно изменять текущее значение посредством перемещения мышью указателя полосы значений. rProgressBar представляв г собой индикат ор хода выполнения про- цесса. Чтобы использова гь этот элемент управления, надо опреде- лит ь его свойс гва Min и Мах, а затем обновить значение свойства Position по ходу' выполнения операции. FUpDown предназначен для интерактивною увеличения или умень- шения значения в присоединенном элементе управления дтя редак- тирования текста при щелчке соответственно по стрелке вверх или вниз. Чтобы привязать элемент управления UpDoun к компоненту для редактирования текста, надо выбрать для первого имя соответст- вующего компонента i раскрывающемся списке свойства Associate. itT 888888S8 THotKey предназначен для указания горячих клавиш для бьк трою перехода на данный компонент. Чтобы указать, какая клавиша - модификатор принимается по умотчанию (hkShift, hkCtil, hkAlt, hkExt) нужно определить набор Modifiers, например, как | hkC tri].
214 Приложения. Кнопка Назначение компонента 7 Animate создает окно анимации для проигрывания видеоклипа (несжатые AVI файлы без зву ка) в фоновом режиме. | [в| г» П TDateTimePicker предназначен для выбора дат и времени Ото- бражает окно списка, позволяющее выбрать дату или время. ДЩ1Г » 7 MonthCalendar отображает помесячный календарь. D gj п TTreeVievv создает объект, позволяющий отображать множество объектов на основе их иерархии как некоторое свертываемое и развертываемое дерево. 1*М« г-и! mJ TListView отображает список в удобном для пользователя виде (таблица, отчет, пиктограммы). Свойство Items содержит список, свойство ViewStyle определяет стиль. LmmmmmnJsJ THeaderControl создает объект, который отображает один или не- сколько заголовков столбцов. Каждый заголовок может быть оп- ределен как некоторая командная кнопка, при нажатии на кото- рую выполняется заданная функция. F "хй rStatusBar создает область для отображения строки состояния. Строка состояния может быт ь разделена на отдельные панели, в каждой из которых появляется своя информация. uj? TTooIBar оконный элемент управления, позволяющий быстро соз- давать кнопки панели инструментов, выравнивая их по рядам, ре- гулируя их размеры и расположение. 1 »; TCoolBar это компонент, кот орый сделан по типу панели инстру- ментов MS Internet Explorer. CoolBar создает контейнер для ото- бражения различных элементов управления внутри перемещае- мых и изменяющих свой размер полос CoolBands Edi*l 7 PageScrollei содержит в клиентской облас ги неко горые объекты, которые можно прокручивать вертикально или горизонтально.
Высокоуровневые методы информатики и программирования 215 Страница System Страница System (см. рис. 33) содержит специальные системные компоненты. Win32 System | Dal э Access i Data Controls | «30 I InterBase | Midas | InternetExoress | Рис. 33. 11абор компонент с границы System Компоненты страницы System перечислены ниже в табл. 27 с некоторыми коммен гариями по их применению. Таблица 27 Кнопка Назначение компонента 1 PaintBox создает область рисования на форме. TMediaPlayer отображает управляющую панель для проигрыва- ния и записи мультимедийных видео- и звуковых файлов. flLF TOleContainer создает в форме OLE-контейнер, Пп TDdeClientConv устанавливает связь с клиентом при DDE (Di- namic Data Exchange) обмене 3 DdeClientltem определяет данные клиен га, передаваемые сер- веру при DDE обмене. i TDdeServerConv устанавливает связь с сервером при DDE (Di- namic Data Exchange) обмене. 1 DdeServei Item определяет данные сервера, передаваемые кли- енту при DDE обмене.
216 П >ИЛОХЕГ HJ . Страница Dialogs Страница Dialogs (см. рис. 34) со, (ержит компоненты, которые служат для добавления диалогов Windows, обеспечивающих стандартный ингерфгйс для та- ких действий, как открытие, сохранение и печа гь фай тов. ADO I InterBase | Hidas J Метте'Ё wares. j internet F&tlMe De i$io iCdbe| ОЯэоо-t Dialogs I Рис. 34. Набор компонент страницы Dialogs Компоненты строг ицы I )ialogs перечислены ниже в табл. 28 с некот. >ры- ми комментариями по их применению. Таблица 28 Кнопка Назначение компонента 1 SaveDialog отображает стандарт ный . ща тог сохранения файла. TOpenPictureDialog отображает стандарт ный диалог для выбора и открытия графических фай тов. Этот диалог имеет панель для просмотра изображения. TSavePirtureDialog отображает стандартный диалог для сохра- нения графических файлов. Этот диалог имеет панель для про- смотра изображения П ontDialog реализует стандартный диалог выбора шрифта. Вы- бранный шрифт возвращается в свойстве Font TColorDialog представляет ст ан дартное диалоговое окно для вы- бора цвета. Выбранный цвет возвращае гея в свойстве С olor. IPnntDialog выводит стандартный диалог Print, в потиром со- держатся опции для у прав гения печатью. Свойс гво Options по- зволяет нас гроить пове тение диалога печати.
Высокоуровневые MEi 3' । ин норма '.1КИ 1 । рограмм.1рова1 и;. 217 Кнопка Назначение компонента TPrinterSetupDialog отображает с гандартный диалог 1 ’) inter Setup для настройки принтера до нача та выдачи информации на пе- чать. I Find! Jiaiog представляет стандарт ный текстовый диал л поис- ка. Свойство Find I ext содержит строку, которою будет искать прикладная программа. Событие Onl ’ind вы бывает ся после щелчка на топке Find Next. С помощью свойства Options можно настроить поведение диалога.___________ TReplaceDialog формирует стандартное диалоговое окно поиска и замены. Свойство ReplaceText содержит текст, который при- кладная прщрамма использует в качестве замены для текста, опре 1еленно1 о в I indText. Страница Data Access Страница Data Access (см. рис. 35) содержит невизу альные компоненты, предназначенные для дос гупа к базе данных. Win32 1 System Data Access Рис. 35. Г 1абир компонен г страницы Data Access Компоненты страницы Data Access перечислены ниже в табл 29 с неко- торыми комментариями по их применению. Таблица 29 Кнопка Н ^значение компонен га 1 эд ТТаЫе обеспечивает доступ к таблице базы данных для ч гения, изменения, добавления, уд зления данных. Полученная таблица передается компоненту TDataSource, который перенаправляет данные сот вет, гвующим компонентам у правления. 1 TQuery создает запрос, определяемый SQL-оператором для досту- па к таблицам базы данных. Полученный набор данных (подмно жесгво ст рок и столбцов таблицы или соединения таблиц) переда- ет ся компоненту' TDataSource, который перенаправляет данные соответствующим компонент ам управления. TStoredProc предназначен для использования в приложении хра- нимых процедур сервера баз данных. TDatabase устанавливает соединение приложения с базой данных и создается автоматически при запуске программы получающей дос- туп к ЕД. Явное использование компонента обеспечивает устойчивое соединение с базой дачных, осуществляет управление авторизацией пользователей к БД, производит управление транзакциями.
218 Г1РИ1 ожсния Кнопка На значение компонен га ]' Ч1 TSession осуществляет общее управление соединениями польза вателей к базе данных. Объект TSession создается автоматически для каждого Delphi-приложсния работы с базой данных. Этот компонент используется то щко для многопоточных приложений баз данных: для каждо! о потока баз данных создается своя собст- венная сессия. hnWi Il ! TBatcl Move предназначен для выполнения операций над группа- ми записей в наборах данных. Он позволяет копировал ь, ; далять, модифицировать информацию одни) о набора (приемника) в соот- ветст вии записями, содержащимися в др} том 1 источнике). SQL Tl JpdateSQL позволяет для наборов данных, созданных с досту- пом только для ч гения, поддерживать возможность и х обновления посредством SQL- опера горов. TNestedTable инкапсулируе г в себе набор свойств вложенной таб- лицы (она размещается как поле в другой таблице). Компонент служит дл я извлечения данных в поля с вложенными наборами данных. Страница DataControls Страница DataControls (см. рис. 36) содержи г компоненты управления для работы с полями баз данных. Win32 Su$teri| Data Access Dat э Controls | ДОО | InterBase} Midas | hlenetlxD'ess J Рис. 36. Набор компонент страницы DataControls Компоненты страницы DataControls перечислены ниже в табл. 30 с неко- торыми комментариями по их применению. Таблица 30 Кнопка _______ Назначение компонен га_______________ IDBGrid отображает данные из по геи разы данных в табличной форме. Свойство Options, посредством активизации вложенных в него простых свойств, позволяет устанавлива гь парамг тры функ- ционирования (например. возможность редактирования dbEditing). С помощью свойства Columns производится индивиду- альная настройка любого столбца таблицы._____________________ TDBNavidator позволяет перемещаться по набору данных, встав лять. редактировать, удаля гь записи, регистрировал ь или отменять изменения.
219 Высокоуровневые методы hhcjpmaihk^ и программирования Кнопка Назначение компонента TDBText подобно компоненту Label выводит текст только для чтения. [а'ЙГ . TDBEdit служит для отображения и редактирования полей дан- Е ных. TDBMemo служит для редактирования и отображения много- строчных текстов (memo-полей данных). lip,iiL"j TDBImage служит для редактирования и отображения графиче- : ских изображений. TDBListBox представляет прокручиваемый список значений для редактирования поля набора данных. Элементы списка задаются в ' свойстве Items. ' 5« -ЛйЙягЙ-J TDBComboBox представ 1яет собой поле со списком (комбиниро- ванный список). Элементы списка задаются в свойстве Items. | Свойство Style определяет внешний вид и функционирование комбинированного списка Jx TDBChecKBox позволяет с помощью независимого переключателя i отображать и редактировать поля типа Boolean. 111 TDBRadioGroup функционирует также как и компонент DBList- Вох. но элементы в нем представлены в виде переключателей 8 (группа радиокнопок). €РтН gp TDBLockupListBox служит для выбора элементов в списке. В отличие от списка компонен га TDBLisibox, список этого ком- 1 понента не задается в свойстве Items, берется из другого набора 8 данных. Eft TDBLookupComboBox служит для выбора элементов в списке. Для отображения списка элементов из другого набора данных ис- пользуется комбинированный список. Кроме выбора значения 1 можно ввести это значение
220 ГН к 0Ж1 Н.'Я На значение компонен га IDBRichEdit используется для отображения и редактирования форматированного текста мемо-по. гей. TDBCulGrid покатывает набор полей из набора записей г.а от- дельных панелях в табличной форме. Каждая панель является контейнером, в котором могут быть размещены различные эле- менты управления для работы с записями. TDBChart используется для отображения графиков и диаграмм, которые строятся на основании значений из набор данных. Страница QReport Страница QReport (см. рис. 37) содержит компоненты, предназначенные для визуального проектирования отчетов. ADO | InterBase I Mtdas | InternelExoress nterael | FaslNet | Decision Cube QFspo” | Diabos 12x1 Рис. 37. Набор компонент страницы QReport Компоненты страницы DataControls перечислены ниже в табл. 31 с неко- торыми комментариями по их применению. Таблица 31 ___________________Н азначение компонента________________ TQuickRep - это визуальный компонент, определяющий прямо- угольную область текущего выбранною размера страницы На основе этой формы строятся все отчеты. Для создания отчета сле- дует на >тог компонент поместить ком юненгы TQRBand и все печатаемые компоненты сое, гинив их с набором данных. TQRSubDetail испо тьзуется для отображения детальных записей в отчете типа "главный/подробный" (master/detail). Главными свой- ст вами эт ого компонен га являю гея 1 JataSet (указывает на подроб- ный набор данных) и Master (указывает на с гпоку. связанную с основным набором данных! TQRStringsBand используется, щя размещения полос, содержащих строки формируемого оз чет а
Высокоуровневые методы информатики и програ* mhpobaj ия 221 Кнопка ____________________Назначение компонента__________________ TQRBand предназначен для размещения области от че, а Ни компо- ненте TQuickRep. На гначение об тас ги определяется значением свойства BandType. TQRChildBand использ] ется для создания облает и. кот орая связана с другой областью Используется для размещения одних компонен- тов под друт ими. а также при слишком д шннь'х полосах протя- женностью в несколько страниц Свойство ParentBand используется для свя ш дочерней иб iac ги с ее родительской облас-ч ю.__ TQRGroup используется для группирования в пределах отчета. С войстьо Expression содержит выражение, сигнализиру ющее об окончании группирования. Свойство Master испо шзуе гея для ука- зания. откуда TQRGroup должен полу ча гь данные TQRLabel служит для отображения статического текста, опреде- ляемого значением свойства Caption. TQRDKlexI испо тьзу ется для отображения значения поля (свой- ство DataF.eldj и т набора данны к (свойство DataSource). TQRExpr позволяет выводить значение выражения, которое зада- ется в свойстве Expression. FQRSysData предназначен информации об отчете или операцион- ной системе. Печатаемые данные определяю гея свойст вом Data а предшествующий текст - свойс гвом Text. IQRMemo используется для вывода в отчете большого текста не и т набора т< иных. TQRExprMemo позволяет программно формировать содержание, используя выражения Quid Report. IQRRichlexI позволяет встраивать в отчет форматированный текст (RTF файлы)
222 Приложения. Кнопка Назначение компонента TQRDBRichText выводит форматированный набор строк из набо- ра записей. TQRShape рисует в отчете простые геометрические фигуры, та- кие, как линия, прямоугольник, круг. TQRImage отображает в отчете рисунок (растровое изображение, пиктограмма, метафайл). TQRDBImage позволяет добавля гь в отчет графику из набора дан- ных. TQRCompositeReport предоставляет возможность объединить не- сколько отчетов. TQRPreview используется для создания собственной формы пред- варительного просмотра и печати отчета вместо стандартного про- смотра QuickReport. TQRTextFilter позволяет экспортировать содержание отчета в тек- стовый формат. TQRCSVFilter позволяет экспортировать в файл базы данных со- держание отчета в формате, использующем запятые как раздели - тели. TQRHTMLFilter позволяет экспортировать содержание отчета в HTML. TQRChart предназначен для включения в отчет диаграмм.
Высокоуровневые mf ы информатики и >о -лмйиросагш 223 ПРИЛОЖЕНИЕ 3. Описание работы с окном про- смотра Print Preview генератора отчетов в среде Delphi Таблица 32 Кнопка Коман. га ( одержан и г Ы First page Перейти на первую страницу при просмотре отче- та Previous page Перейти на предыд; щую страницу при просмот- ре отчета ► Next page Зерей' и на следующую страницу при просмотре отчета м Last page 11ерей' и на последнюю с границу при про. мот ре отчета 100% 100% масштаб изображения страницы отчета в окне предварительного просмотра Pr.nt Preview о Zoom to fit У меньшит ь масштаб изображения страницы от- чета в окне предварит сльнт о просмот pa Print Preview Zoom to width Увеличить масш габ и юбражения страницы от- чета в окне предварительного просмотра Рал’ Preview Printer Setup Вызов диалогового окна настройки прин .ера в режиме просмотра отчета в окне предваритель- но! о просмотра Print Preview в Print 11ечать отчета из режима п| >осм утра отчета в о, - не лпедвари тельного просмотра Print Preview БД Save Report Вызов циалпгово! о окна для сохранения отчета из окна предварительного просмотра Print Pre- view Gr3^ Load Report Вызчв диалогового окна для загрузки отчета в окно предвари тельного просмотра Print Preview Close Close Выход из режима предварите 1ьно о просмотра Print Preview
224 Приложения. Г операция отчета отображается в окне предварительного просмотра Print Preview. В левом нижнем углу окна просмотра имеется индикатор, который ото- бражает динамику процесса формирования отчета: ...% ... Page 1 of 5 Рекомендуется дождаться конца формирования отчета, а затем можно пе- ремещаться по страницам отчета с помощью кнопок навигации на панели инст- рументов окна Print Preview. Возможен досрочный выход из режима формирова- ния отчета. Для этого достаточно нажать на кнопку Close на панели инструмен- тов. Назначение кнопок на панели инструментов окна Print Preview приведено в табл. 32. Отчет можно распечатать, нажав на кнопку Print. Если требуется, можно выполнить настройку принтера перед печатью, нажав на кнопку Printer Setup. На экране появится стандартный диалог установки параметров принтера. Отчет можно сохранить, нажав на клавишу Save Report. При этом на экране появится стандартное окно сохранения файла. Отчет будет сохранен в файле с именем *. QRP. Вместо символа * требуется указать имя. Этот отчет может быть повторно загружен в окно предварительного просмотра в диалоге, возникающем при нажа- тии на кнопку Load Report Для выхода из режима просмотра и печати отчета на- жать кнопку Close на панели инструментов.
225 ОГЛАВЛЕНИЕ ВВЕДЕНИЕ - 3 ГЛАВА 1. НОВЕЙШИЕ НАПРАВЛЕНИЯ В ОБЛАСТИ СОЗДАНИЯ ТЕХНОЛОГИЙ ПРОГРАММИРОВАНИЯ - 4 1.1. Структурное программирование - 4 1.2. Нисходящее проект ирование - 4 1.3. КОНЦЕПЦИЯ МОДУЛЬНОГО программирования - 6 1.4. Объектно-ориентированное пр< )граммирование (ООП) - 6 1.5. CASE-СИСТЕМЫ - 6 1.6. ТЕХНОЛОГИЧЕСКАЯ СХЕМА РЕШЕНИЯ задач 1.7 ИНДУСТРИЯ ИСКУССТВЕННОГО ИНТЕЛЛЕКТА - 8 1.8. Экспертные системы - 9 1.9. ЗАКО11Ы ЭВОЛЮЦИИ ПРОГРАММНОГО ОБЕСПЕЧЕН1ИЯ - 12 ГЛАВА 2. СОЗДАНИЕ МОДУЛЬНЫХ ПРОГРАММ, ЭЛЕМЕ11ТЫ ТЕОРИИ МОДУЛЬНОГО ПРОГРАММИРОВАНИЯ -15 2.1. С груктура модулIИ Пас ка. гя -17 2.2. 3AI ()Л<)ВОК МОЛ УЛЯ И СВЯЗЬ МОДУЛЕЙ ДРУГ С ДРУГОМ - 17 2.3. ИНТЕРФЕЙСНАЯ ЧАСТЬ -18 2.4. Ист К ТЛНЯЕМАЯ ЧАС 1Ь - 18 2.5. И11ИЦИАЛИ ЗИРУ ЮЩАЯ ЧАСТЬ - 19 2.6. КОМПИЛЯЦИЯ МОДУЛЕЙ -20 2.7. ДОСТУП К ОБЪЯВЛЕННЫМ В МОДУЛЕ ОБЪЕКТАМ - 21 2. 8. СТАНДАРТНЫЕ МОДУЛИ - 23 Модуль SYSTEM - 23 Модуль PRINTER - 23 Модуль CRT -23 Модуль GRAPH -24 Моду ль DOS - 24 Модуль OVERLAY -24 2.9. ИСПОЛЬЗОВАНИЕ СТАНДАРТНО] О МОДУ. 1Я CRT -24 2.9.1. Программирование клавиатуры 2.9.2. Текстовый вывод на экран - 28 2.9.3. Программирование звукового генератора -36 2.10. Использование с г андлгт ною модуля Graph -37 2.10.1. 1 lepexo i в графический режим и возврат в текстовый - 37 2.10.2. Краткая характеристика графических режимов работы дисплейных адаптеров - 37 2.10.3. Процедуры и функции -38 2.10.4. Координаты, окна, страницы - 44 2.10.5. Многоугольники -48 2.10.6. Дуги, окружности, эллипсы - 51 2.10.7. Краски, палитры, заполнения -53 2.10.8. Сохранение и выдача изображений -66
226 2.10.9. Вывод текста - 67 2.10.10. Включение драйвера и шрифтов в тело программы - 73 2.11. CTAI[ДАР1ИЫЙ М( >ДУ. lb SYSTEM - 75 2.11.1. Константы модуля S YSTEM - 75 2.11.2.1 [временные модуля SYS1 ЕМ - 76 2.11.3 Сгандаря ные проц? [уры и функции модуля SYSI ЕМ - 77 2.12. МОДУЛЬ DOS -81 2.12.1. Kohci ан гы модуля DOS - 81 2.12.2. Типы модуля DOS - 82 2.12.3. Переменные моду пл DOS - 83 2.12.4. Процедуры и функции модуля DOS - 83 ГЛАВА 3. ОББЕК1 НО-< )РИЕН 1ИРОВАННОЕ IIPO1 РАММИРОВА11ИГ - 85 3.1. Oi ИОВНЫЕ ПРИНЦИПЫ ООП - 86 Инкапсуляция - 86 Наследование - 86 Полиморфизм - 87 3.2. Создание объектов - 87 3.3. Использование объекг<>в - 9 4 3.4. «Нетрадиционные » возки >Ж1 к)сти Турьо Паска.гя - 98 3.4.1. Внешние процеду ры (функции) - 98 3.4.2. Испо. шзование встроенных машиных кодов - 99 3.4.3. Обращения к функциям операционной системы - 101 3.4.1. Поддержка процедур обработки прерываний -103 3.4.5. Запуск внешних программ -105 3.4.6. Оверлей - 107 3.4.7. Прямое обращение к памят и и порт а и ввода - вывода - 112 3.4.8 Длинные строки -112 3.5. Вс ТРОЕННЫЙ A Cl ЕМБ ПЕР - 118 3.5.1. Общее описание МП 8086'8088 - 119 3.5.2. Регистры - 119 3.5.3. Адресация -122 3.5.4. Система команд -123 3.5.5. С пецифика^ия встроенного Ассемблера -132 3.5.6. Оператор ASM -133 3.5.7. Список ассемблерных коман д -134 1.5.8. Операции встроенного Ассемблера -140 3.5.9. Директивы Ассемблера - 142 3.5.10. Ассемб lepHbte подпрограммы -143 ГЛАВА 4. ОСОБЕ! 1НОСТИ 11РОГРАММИРОВА11ИЯ В OKOIIH1 .IX OI1ЕРАЦ11ОН11ЫХ С РЕДАХ - 145 4.1. СТРУКТУРА СРГДЫ ПРОГРАММИРОВАНИЯ - 1 45 4.2. ОБЗОР ПАЛИТРЫ КОМПС)НГ hlOB - 1 4° 4.3. ПРЕ( )БРАЗ< >ВАНИЕ „ IAE НЫХ <' ФОРМАТИРОВАНИЕМ -151 4.4. Ввод данных -153
227 4.5. ВыводяАНПЫХ -154 4.6. 11РОГР АММПРОВ М1ИЕ В DELPHI - 156 ГЛАВА 5. 7 ЕХН< Ъ1О1 ИЯ СОЗДАНИЯ ПГО1 РАММ В СРЕДЕ DPI PHI - 1 58 5.1. СТРУК RP А ПРОСТО! О ПРОЕКТА - 1 58 5.2. TJ X! КТЛОГИЯ 1 АЗРАБОГКИ ПРИЛОЖЕНИЯ - 160 5.3. Форма i iphл >жт тия -160 5.4. Компоненты формы -162 5.5. С()БЫ'1 ИГ И ПРОЦЕДУ РА ОБРАБОТКИ <ОЬЫГИЯ - 1 65 5.6. Редактор кода DI 1 РН1 -166 5.7. Pxboja с Code explorer -167 5.8. К(JMI1И. 1ЯЦИЯ И ВЫПОЛНЕНИЕ ПРОГРАММЫ - 1 6' 5.8.1. Сохранение проекта -167 5.8.2. Компиляция - 168 5.8.3. Запуск приложении из среды программирования - 169 5.8.4. Ошибки выполнения при южепия -170 5.8 5. Окончательная настройка приложения - 1 70 5.8.6. Установка приложения -172 5.9. Гр афические компонен гы -172 5.9.1. Компонент Image -172 5.9.2. Компонен г Shape -173 5.9.3. Компонен г Bevel -175 5.9.4. Компонен г TPaintBox - 176 5.10. Свои< ТВ А ГР \ФИЧЕ< Л :их КОМПО1 IE! ITOB - I 78 5.10.1. Проектирование интерфейса 1рограммы -178 5.10.2. Изменение свойств ви дальних компонентов во время выполнения программы - ] 79 5.10.3. Программирование п этос прокрутки окна -182 5.11. Свойства, мет оды и собы ги я CANV A S -188 5.11.1. Основные свойства класса TCanvas - 188 5.11.2. Мет оды класса 1 Canvas - 1 89 5.11.3. Рисование на поверхности формы с испо тьзованием свой< тва Canvas - 197 5.12. ObP АБО I КА ИСКЛЮЧИТ ЕЛЬНЫХ СИТУ А ЦП I -200 5.12.1. Назначение конструкции Try ... Finally -202 5.12.2. Назначение конструкции Try . . Excepl -202 5.13. ПРИМ! РЫ ПРОЕКТИРОВАН! [Я ПРИЛОЖЕНИЙ -203 5.13.1. Разработка приложения, реализующего работу с таб шцей, содержащей графические данные - 203 ПР! 1Л( )Ж ЕНИН 1. КРАП :О1 ОПИСАНИЕ КОМАНД ГЛАВНО! о mehkjDelpiii - 206 ПР11ЛОЖЕ1 1ИЕ 2. Ol 1ИСАНИЕ С 1 РА! !ИЦ ПА. ТИТ РЫ КОМПОНЕНТОВ - 21 1 11РИЛОЖЕ11ИЕ 3. ОПИСАНИЕ РАБОТЫ С ОКНОМ ПРОСМОТРА PRINT PREVIEW ГЕНЕРАЛ )РА О ГЧЕ ТОВ В СРЕДЕ DELPHI - 223
228 ИСТОМИН Евгений Петрович V 53 года рождения д'ктор Text ических наук, профессор по кафедре вычисл/’’erbhoiX < и "ем и информатики Имее’ около 100 н дурных тоуЛЗЕ в том числе. 3 монографии, 4 учебника. 11 учебных пособий, 5 изобретений и более 70 научных статей и тезисов докладов Область нау* ных интересов - современные инФоомациог ные техголо(ии. теория управления государством i принятие оешений в социально-экономических системах. Хобби - путешествие с семьей на автомобиле, литература и лолд тш а. НОВИКОВ Владимир Витальевич, доктор технических наук, профессор кафедры прикладной информа ики и анализа экономических систем Санкт-Петербургского Института экономики и права Спечиалист в области информационна х систем, прогоаммиопвания и эффективности сложных ооганизационных и техничес .их систем Является автором более 90 научных работ Научный руководитель многих научно-, исследовательских работ и защищен ь х кандидатских диссертаций НОВИКОВА Маргарита Вячеславовна кандидат технических наук, доцент i эфедры прикладной информатики i анализа экономических систем Санкт-Я“тербур| с :ого Института экономики и права. Сг ециалист в обг.а ,ги информационных технологий, программирования и сист ем контроля электро сны < вычмс: ителы „> машин Является ав-.ором более 20 нау зных трудов. ООО «Андреевский издательский дом» основан в 1998 году, выпускает периодические издания, учебную и научную гитературу В 2005 году издательский доч начал выпуск ДВУХ серий научной и i чебной литературы для специалистов, преподавателей и студен гов ВУЗов: 1. БИБЛИОТЕКА ТЕХНОЛОГА - УЛЬТРАЗВУКОВИКА, включающая 1 книги. Первые две книги bi гшли в 2005 1 оду И. В. Пет ушко. Оборудование для ультразвуковой обработки И.В Пет ушко. Оборудование для ультразвуковой очистки Издание остальны < кни1 эт ой серии планируется в 2006 i оду. 2. БИБЛИОТЕКА МЕНЕДЖЕРА, состоящая из 9 учебных ищаний. Первые три книги вышли в 2005 году. - Е.П. Истомин, А Г Соколов Управленческие решения Учебник. Л.О Евдокимова, Л С Слесарева Инновационный менеджмент Учебное пособие М М. Глазов. Анализ и диагностика финансово-хозяйственной деятельности предприятия Учебник Издание остальных книг этой серии планируется в 2006 и 2007 годах. В 2006 1 оду наря ту с из. ганием спланированных серий и гдательский том запускает в прои (воде гво трел ю серию- ПРИКЛАДНАЯ ИНФОРМАТИКА . - Е.П. Истомин С.Ю. Неклюдов, В И. Романченко. Информатика и программирование Учебник. Е.П. Истомин, В.В Новиков, Г/1 В. Новикова Высокоуровневые методы информатики и программирования. Учебник В серии ПРИКЛАДНАЯ И11Ф< ЭРМАТИКА г панируется 6 книг. Все учебные изтания проходят экспертизу и имеют гриф УМО. Авторы книг - доктора и кандидаты наук, представляющие различные научные школы России, имеют большой научный и педаго! ический опыт. Приглашаем к сотрудничеству авторов и оптовых п экупэтелей Наши контакты: 1 -mail: biomtanm.ru Те тефон. 8-921-643-78-68 (812)743 8"’-86