Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
РУКОВОДСТВО TURBO VISION ДЛЯ C++ TV Turbo Visio...doc
Скачиваний:
2
Добавлен:
01.04.2025
Размер:
5.2 Mб
Скачать

Глава 10. Дополнительная информация

-----------------------------------------------------------------

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

более эффективному использованию Turbo Vision. Поскольку объект-

но-ориентированное программирование и программирование, управляе-

мое по событиям, представляют собой совершенно новые концепции

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

дать некоторые рекомендации по использованию данных концепций.

Отладка прикладных программ Turbo Vision

-----------------------------------------------------------------

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

примерами программ, то, вероятно, заметили, что узнали не так

много. Поскольку программы, написанные с использованием Turbo

Vision, управляются по событиями, большая (если не основная)

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

цикле TGroup::execute в ожидании наступления какого-либо события.

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

программами на этом этапе.

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

ванием Turbo Vision, служат точки прерываний и только они.

Рассмотрим, как размещение точек прерываний в нужных местах

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

Vision.

Невыполнение команд

Одной из проблем при отладке прикладной программы может быть

невыполнение какой-либо части программы. Например, вы выбираете

элемент в строке состояния или команду меню, которая должна вы-

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

Инстинктивно вы попытаетесь просмотреть программу, дойти до

нужной команды и выяснить, какую функцию вместо ожидаемой она вы-

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

его на том же месте.

Наилучшим подходом здесь является установка точек в методе

handleEvent, который будет вызывать невыполняемый фрагмент прог-

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

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

события, чтобы определить, что это именно ожидаемое вами событие.

С этого места вы можете также начать просмотр фрагмента програм-

мы, т.к. handleEvent и любой фрагмент, реагирующий на команды,

является именно разработанным вами фрагментом и, следовательно,

вы можете его просматривать.

Turbo Vision для С++ = 6 =

Скрытие под маской

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

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

ему для обработки. Первой и явной ошибкой здесь будет оставить

тип события за пределами маски события вашего объекта. Если вы не

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

бытия, он даже не будет замечать это событие!

"Украденные" события

Второй фактор, который вы должны учитывать, состоит в том,

что какой-либо другой объект может "украсть" событие. Это означа-

ет, что событие будет обрабатываться и очищаться не тем объектом,

который вы для него предназначали.

Это может быть вызвано двумя причинами. Первой из них явля-

ется дублирование объявлений команд: если двум командам было

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

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

ется отслеживание, каким константам какие значения вы присваива-

ли; и прежде всего в случае повторного использования модулей

программы.

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

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

иваете команду cmJump, а в каком-либо другом объекте имеется ме-

тод handleEvent, который уже реагирует на команду cmJump, о кото-

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

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

гой объект события, которые казались "утраченными".

Влияние предков

И, наконец, следует удостовериться, что событие не будет об-

рабатываться в процессе вызова предка объекта. Часто, метод

handleEvent порожденного типа при обработке событий будет пола-

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

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

тесь перехватить событие перед вызовом метода handleEvent объек-

та-предка.

Программа не выполняет ожидаемых действий

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

"мусор", либо то, чего вы не ожидали. Это означает, что событие

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

ется либо неправильной, либо переопределенной. В данном случае,

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

Turbo Vision для С++ = 7 =

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

жете нормально проследить по программе причины этого.

"Зависание" программы

Ошибки, связанные с "зависанием" программы, наиболее трудно

отслеживаются, однако их можно обнаружить. Вначале можете исполь-

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

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

ния. Далее, следует отыскать указатели, от которых дважды осво-

бождались. Это происходит, когда владелец освобождается от объек-

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

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

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

и неправильное приведение типов данных из коллекций.

Turbo Vision для С++ = 8 =

Перенос прикладных программ в среду Turbo Vision

-----------------------------------------------------------------

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

среду Turbo Vision, то первым предполагаемым шагом здесь может

показаться перенос интерфейса Turbo Vision в прикладную программу

или размещение уровня Turbo Vision "поверх" прикладной программы.

С вашей стороны это будет напрасным трудом. Программы Turbo

Vision управляются событиями, и большинство существующих приклад-

ных программ не будут подходить под эту концепцию.

Удаление старой программы

Существует, однако, и более простой способ. Вы уже знаете,

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

сосредоточена в методах draw и handleEvent. Наилучшим подходом к

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

терфейса Turbo Vision параллельно с имеющимися у вас и последую-

щее превращение прежней программы в новую программу. Большая

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

объектов draw и handleEvent.

Вы должны немного поразмыслить над сущностью вашей приклад-

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

программы от части, выполняющей основную функцию вашей прикладной

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

рассматривать программу под другим углом.

Выполнение переноса потребует переработки программы, чтобы

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

расывания большей части прежней интерфейсной программы. Это вызо-

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

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

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

ке пользовательского интерфейса. Когда вы начнете работать с

Turbo Vision, то большая часть ранее выполненной работы по реали-

зации пользовательского интерфейса просто исчезнет.

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

среды Borland в Turbo Vision. Мы освободили компилятор, редактор,

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

тельского интерфейса и привели их в соответствие с пользова-

тельским интерфейсом, разработанным в Turbo Vision.

Пересмотр организации вашей программы

-----------------------------------------------------------------

К программированию в соответствии с новой концепцией надо

привыкнуть. При традиционной технике программирования мы рассмат-

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

Turbo Vision для С++ = 9 =

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

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

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

редактируемого объекта. Именно это вы, в основном, выполняете в

среде - редактируете. Редактор будет выполнять редактирование и

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

Однако, в перспективе мы должны несколько изменить страте-

гию, чтобы наиболее полно использовать преимущества объектно-ори-

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

больший смысл сделать саму прикладную программу организующим объ-

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

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

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

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

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

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

тексте программы? Программа вызовет компилятор и получит от него

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

возвратит также имя файла и номер строки. Программа будет искать

для этого файла открытый редактор и в случае его отсутствия сама

его откроет. Она передаст информацию об ошибке, включая номер

строки, и создаст строку сообщений об ошибках для редактора.

Редактору не требуются сведения о компиляторе, а компилятору

- о редакторе. Центром их деятельности является сама программа.

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

связывает их воедино. Если бы мы продолжили рассматривать прог-

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

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

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

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

В целом, разработка интегрированной среды с помощью Turbo

Vision занимает столько же времени, сколько и запись среды из ра-

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

обнаружите эти же преимущества.

Turbo Vision для С++ = 10 =

Использование битовых полей

-----------------------------------------------------------------

Примечание. Опытные программисты на Cи могут пропустить этот раз-

дел.

Во многих случаях Turbo Vision использует битовые поля. Это

означает, что для обозначения различных свойств используются от-

дельные биты байта или слова. Отдельные биты обычно называются

флагами, т.к. будучи установленными (равны 1) или сброшенными

(равны 0) они указывают, активировано ли указанное свойство.

Например, каждый отображаемый объект имеет битовое поле с

именем options. Каждый отдельный бит слова имеет для Turbo Vision

различное значение. Определения битов в слове options даны в гла-

ве 13.

Значения флагов

Позициям битов назначаются мнемоники. Так, например, четвер-

тый бит называется ofFramed. Если он установлен в 1, то это озна-

чает, что вокруг отображаемого объекта имеется видимая рамка.

Если бит установлен в 0, то отображаемый объект не имеет рамки.

Для вас не играют роли фактические значения битов флагов,

если только вы не собираетесь определить ваши собственные значе-

ния. В этом случае требуется лишь, чтобы определения были уни-

кальными. Например, шесть старших бит в слове options в настоящий

момент не определены Turbo Vision. Вы можете определить любой из

них, чтобы он что-либо означал для порождаемых отображаемых объ-

ектов.

Маски бит

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

битовых флагов. Например, Turbo Vision определяет маски для раз-

личных видов событий. Маска evMouse просто содержит все четыре

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

"мышью", поэтому, если отображаемому объекту требуется узнать,

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

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

событий, связанных с мышью в отдельности.

Поразрядные операции

Операторы Cи и C++, поддерживающие поразрядные операции,

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

ния отдельными битами .

Turbo Vision для С++ = 11 =

Установка бита

Для установки бита используется оператор |. Например, следу-

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

options режим myButton:

myButton.options |= ofPostProcess;

// Это аналогично следующему :

// myButton.options = (myButton.options | ofPostProcess);

Не следует использовать оператор + для установки битов. Нап-

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

следующий:

myButton.options += ofPostProcess;

(Примечание: Этого делать не следует!)

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

ofPostProcess имел бы значение 0. Если бы он был установлен до

того (имел значение 1), как вы добавили другой бит, то двоичное

сложение будет перенесено в следующий бит (ofBuffered), устанав-

ливая или сбрасывая его, в зависимости от исходного состояния. И

так далее до конца флага.

Прежде, чем завершить разговор об установке бит, отметим,

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

фрагмент программы установит два флага с различными режимами

роста одновременно в прокручиваемом объекте myScroller:

myScroller.growMode |= (gfGrowHiX | gfGrowHiY);

Сброс бита

Сброс бита также прост, как и его установка. Для этого

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

является комбинация двух операций, & (поразрядное AND) и ~ (по-

разрядное инвертирование). Например, для сброса бита dmLimitLoX в

поле dragMode метки aLabel вы должны использовать выражение:

aLabel.dragMode &= ~dmLimitLoX;

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

с помощью одной операции.

Переключение бит

Биты могут быть переключены (1 установлен в 0, а 0 установ-

лен в 1), при помощи операции ^ (поразрядное XOR):

myButton.options ^= ofPreProcess;

Turbo Vision для С++ = 12 =

// переключение флага ofPreProcess

myView ^= (gfGrowHiX | gfGrowHiY);

// переключение двух флагов

Проверка бит

Довольно часто отображаемому объекту требуется выполнить

проверку факта установки битового флага. Для этого используется

операция & (AND). Например, чтобы узнать, может ли управление ок-

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

образом проверить значение флага ofTileable:

if (aWindow.options & ofTileable) { ... }

Использование масок

Как и для проверки отдельных бит, операцию & (AND) можно

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

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

какое-либо событие, связанное с "мышью", вы должны выполнить сле-

дующее:

if (event.what & evMouse) { ... }

Резюме

-----------------------------------------------------------------

Битовые операции обобщены в следующем списке:

Установка бита:

field |= flag;

Сброс бита:

field |= ~flag;

Переключение бит

field ^= flag;

Проверка установки флага:

if (field & flag) { ... }

Проверка наличия флага в маске:

if (flag & mask) { ... }

Turbo Vision для С++ = 13 =