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

Глава 4. Отображаемые элементы

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

Из глав 1 и 2 и знакомства с интегрированной средой вы уже

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

программы Turbo Vision. Но что скрывается за сценой ? Это предмет

обсуждения в главах 4 и 5.

"Мы будем управлять экраном телевизором..."

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

При работе с Turbo Vision вам больше не придется выполнять

запись информации непосредственно на экран. Вместо использования

библиотечных функций printf и puts, для передачи информации поль-

зователю, вам следует передать ее Turbo Vision и можете быть уве-

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

Основным блоком в построении прикладных программ Turbo

Vision является отображаемый объект. Отображаемый объект - это

объект в языке C++, который управляет прямоугольной областью эк-

рана. Например, строка меню в верхней части экрана является отоб-

ражаемым объектом. Любое действие программы, выполняемое в данной

области экрана (например, нажатие кнопки "мыши" на строке меню),

будет реализовано через отображаемый объект, управляющий этой об-

ластью.

Отображаемыми объектами являются меню, окна, строка состоя-

ния, кнопки, полосы прокрутки, панели диалога, и часто даже

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

программе Turbo Vision должно быть отображаемым объектом, и его

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

экране. Так, например, если вы хотите составить систему меню, вы

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

содержащую определенные команды, а Turbo Vision выполнит все не-

обходимые действия.

Наиболее наглядным примером отображаемого объекта является

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

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

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

с пользователями. Далее вы увидите, что единые объекты (такие как

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

связанных отображаемых объектов.

Простые объекты типа отображаемого объекта

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

Как можно видеть из иерархической схемы на рисунке 3.1,

предшественником всех отображаемых объектов Turbo Vision является

TObject. Он даже нечто большее, чем общий предшественник всех

объектов. Само программное средство Turbo Vision действительно

Turbo Vision для С++ = 109 =

начинается с объекта TView.

Объект TView появляется на экране в виде пустого прямоуголь-

ника. Создавать экземпляр класса TView имеет смысл лишь в том

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

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

она содержит все основные методы и поля управления Turbo Vision.

Любой объект, порожденный от TView, должен быть способен вы-

полнять две следующие функции:

Первая - это способность к самоизображению в любой момент

времени. Объект TView определяет виртуальную метод draw, и каждый

порожденный от него объект должен также иметь этот метод. Это

имеет большое значение, т.к. часто отображаемый объект может быть

закрыт другим отображаемым объектом (или на него может быть нало-

жен другой отображаемый объект) и когда другой отображаемый объ-

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

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

Вторая функция - это способность обрабатывать любые встреча-

ющиеся события. Как было отмечено в главе 1, программы Turbo

Vision управляются по прерываниям. Это означает, что Turbo Vision

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

ветствующим объектам в программе. Отображаемые объекты должны

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

работке событий см. в главе 5.

Определение внешнего представления отображаемых объектов

Перед тем, как рассматривать, какие функции реализуются

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

самими и как они изображаются на экране.

Местоположение отображаемого объекта на экране определяется

двумя точками: левого верхнего угла (называемой его началом) и

нижнего правого угла. В объекте эти точки представляются полями

типа TPoint. Поле origin, являющееся полем типа TPoint, указывает

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

правый угол.

Примечание: описание TPoint дано в следующем разделе.

Имейте в виду, что поле origin является точкой в системе ко-

ординат отображаемого объекта-владельца: если вы открываете окно

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

окна x и y по отношению к началу рабочей области. С другой сторо-

ны, поле size является точкой по отношению к началу собственного

объекта. Оно определяет расстояние от начала до нижнего правого

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

ния начала отображаемого объекта внутри другого отображаемого

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

Turbo Vision для С++ = 110 =

угла отображаемого объекта.

Использование объекта TPoint

Тип TPoint чрезвычайно прост. Он имеет всего два поля, x и

y, которые являются его координатами и два метода. Последние яв-

ляются переопределенными операторами += и -= и позволяют увеличи-

вать и уменьшать координаты x и y соответственно:

TPoint& operator +=( const TPoint& adder );

TPoint& operator -=( const TPoint& subber );

Так если p1 и p2 точки с координатами (x1,y1) и(x2,y2), то

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

p1 += p2; // p1 сейчас = (x1 + x2, y1 + y2)

p1 -= p2; // p1 сейчас = (x1 - x2, y1 - y2)

Имеется также четыре friend-оператора ==, !=, +, -, которые

работают с двумя объектами TPoint, передаваемыми им в качестве

параметров:

p3 = p1 + p2; // p3 = (4, 6)

p3 = p2 - p1; // p3 = (2, 2)

if(p1 == p2) {// если точки равны ... }

if(p3 != p1) {// если точки не равны...}

Знакомство с объектом TRect

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

Turbo Vision непосредственным образом. Т.к. каждый объект типа

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

обычно обрабатываются вместе в объекте TRect. Объект TRect имеет

два поля, a и b, каждое из которых - типа TPoint. При определении

границ объекта типа отображаемого объекта они передаются

конструктору в объекте TRect.

Два класса TRect и TView располагают полезными методами для

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

хотите создать отображаемый объект, который как раз помещается в

окне, вы можете узнать размер окна, затем уменьшить этот размер и

присвоить его новому внутреннему отображаемому объекту.

void ThisWindow::makeInside()

{

TRect r = getExtent(); // установить r в размер ThisWindow

InsideView *inside;

r.grow(-1, -1); // сократить прямоугольник на 1

inside = new InsideView(r); // создать внутренний

// отображаемый объект

insert(inside); // включить новый отображаемый объект в окно

Turbo Vision для С++ = 111 =

// вы также можете использовать insert ( new InsideView(r) );

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

//другом месте

}

Примечание: обозначения (названия) ThisWindow и InsideView приняты

только для этого примера.

Метод getExtent является экземпляром TView, который устанав-

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

весь отображаемый объект. Метод grow является экземпляром TRect,

который увеличивает (или уменьшает при отрицательных параметрах)

горизонтальные и вертикальные размеры прямоугольника.

Координаты в Turbo Vision

Метод присвоения координат, принятый в Turbo Vision, может

отличаться от известных вам методов. Разница заключается в том,

что в отличие от большинства систем координат, в которых на экра-

не задается местоположение символов, в Turbo Vision координатами

задается сетка между символами.

Например, если r является объектом TRect, то выражение

r.assign(0, 0, 0, 0) определяет прямоугольник, не имеющий разме-

ров - это всего лишь точка. Наименьший прямоугольник, который мо-

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

нием r.assign(0, 0, 1, 1).

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

r.assign(2, 2, 5, 4).

0 1 2 3 4 5 6 7

0┌───┬───┬───┬───┬───┬───┬───┐

│ │ │ │ │ │ │ │

1├───┼───┼───┼───┼───┼───┼───┤

│ │ │ │ │ │ │ │

2├───┼───┼───┼───┼───┼───┼───┤

│ │ │ r │ r │ r │ │ │

3├───┼───┼───┼───┼───┼───┼───┤

│ │ │ r │ r │ r │ │ │

4├───┼───┼───┼───┼───┼───┼───┤

│ │ │ │ │ │ │ │

5└───┴───┴───┴───┴───┴───┴───┘

Рисунок 4.1. Система координат Turbo Vision.

Т.о., выражение r.assign(2, 2, 5, 4) определяет прямоуголь-

ник, содержащий 6 знакомест. Хотя подобная система координат

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

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

гих объектов.

Turbo Vision для С++ = 112 =

Определение внешнего вида отображаемого объекта

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

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

draw. Практически все новые отображаемые объекты должны иметь

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

жаемого объекта, который отличает его от других отображаемых объ-

ектов.

Имеются два правила, которые применимы ко всем отображаемым

объектам в соответствии с их внешним видом. Отображаемый объект

должен:

- охватывать всю область, на которую распространяется его

действие;

- иметь способность к самоотображению в любой момент времени.

Оба этих свойства имеют большое значение и заслуживают того,

чтобы их рассмотреть.

Область, занимаемая отображаемым объектом

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

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

ект должен нести ответственность за свою территорию. Отображаемо-

му объекту присваивается прямоугольная область экрана. Если он не

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

становится не определенным: в ней может быть представлена любая

информация и вы не сможете управлять этим процессом. На примере

программы TVGUID06.CPP из главы 2. показано, что произойдет, если

отображаемый объект не будет охватывать всю зону экрана.

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

Кроме того, отображаемый объект должен быть всегда способен

к самоизображению на экране. Это связано с тем, что другие отоб-

ражаемые объекты могут закрыть его часть, а затем быть убраны,

или же сам отображаемый объект может переместиться. В любом слу-

чае при необходимости выполнить эту операцию отображаемый объект

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

самоотображения.

Имейте в виду, что это может означать, что отображаемый объ-

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

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

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

объект не виден. Большинство подобных ситуаций обрабатывается ав-

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

Turbo Vision для С++ = 113 =

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

Такой подход существенно отличается от многих других схем

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

Вы выполняете запись в окне, и она в нем остается даже в том слу-

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

будет убран. В Turbo Vision вы не можете быть уверенными в том,

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

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

Реализация наилучшего поведения отображаемого объекта

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

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

обработчиком событий handleEvent. Ему передается запись события,

которое необходимо обработать одним из двух способов. Он может

либо выполнить какое-то действие в ответ на событие и отметить

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

мому объекту (если таковой имеется), который будет его обрабаты-

вать.

Ключевым в поведении отображаемого объекта является его

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

окне будет получено событие, содержащее команду cmClose, то можно

предположить, что окно закроется. Возможно реакция на эту команду

будет другой, но это маловероятно.

Примечание: подробнее обработка событий рассмотрена в главе 5.

Turbo Vision для С++ = 114 =

Комплексные отображаемые объекты

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

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

непосредственном порождении класса TView - классе TGroup. Класс

TGroup и его наследники имеют общее название - группы. Отображае-

мые объекты, которые не порождаются от класса TGroup, называются

терминальными (конечными) отображаемыми объектами.

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

рый содержит другие отображаемые объекты и управляет ими. В тех-

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

должна выполнять те же функции, что и отображаемый объект: управ-

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

любой момент времени и обрабатывать события в своей области экра-

на. Различие между ними заключается в способах выполнения этих

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

подобъектах.

Группы и отображаемые объекты

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

Отображаемый подобъект - это отображаемый объект, который

принадлежит другому отображаемому объекту. Это означает, что не-

который отображаемый объект (группа) выделил часть своей области

экрана для обработки другим отображаемым объектом, называемым его

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

Наглядным примером здесь может служить объект TApplication.

TApplication - это отображаемый объект, который управляет об-

ластью экрана - фактически всем экраном. TApplication является

также группой, которой принадлежат три ее отображаемых объекта:

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

ляет каждому из этих отображаемых подобъектов определенную об-

ласть экрана. Строка меню будет занимать верхнюю строку строка

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

между ними строки. На рисунке 4.2 показан типичный вид экрана

TApplication.

┌──────────────────────────────────────┐

│ Строка меню │

├──────────────────────────────────────┤

│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│

│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│

│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│

│░░ Рабочая область ░░░░░░░░░░░░░░░░░░░│

│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│

│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│

├──────────────────────────────────────┤

│ Строка состояния │

└──────────────────────────────────────┘

Turbo Vision для С++ = 115 =

Рисунок 4.2. Вид экрана TApplication.

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

экранного представления - на экране вы не увидите программу. Ее

внешний вид полностью определяется принадлежащими ей отображаемы-

ми объектами.

Включение в группу

Каким образом отображаемый объект присоединяется к группе?

Этот процесс называется включением. Отображаемые объекты созда-

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

тор класса TApplication создает три объекта и включает их в прог-

рамму:

createStatusLine ( cStatusLine );

createMenuBar ( cMenuBar );

createDeskTop ( cDeskTop );

if( createDeskTop != 0 ) insert(deskTop);

if( createStatusLine != 0 ) insert(statusLine);

if( createMenuBar != 0 ) insert(menuBar);

Вновь созданные отображаемые объекты становятся частью груп-

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

ражаемый объект TApplication разделил свою область экрана на три

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

объектов.

Однако это не значит что отображаемые объекты не могут пере-

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

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

перекрывающиеся окна в рабочей области. Группы, включая и рабочую

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

мые объекты.

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

объектов. Этот порядок называется Z-последовательность. Он

представляет последовательность, в которой изображаются отобража-

емые объекты и передаются в них события.

Turbo Vision для С++ = 116 =

Другие аспекты Z-последовательности

Термин Z-последовательность связан с тем, что отображаемые

объекты имеют трехмерное пространственное соотношение. Как вы уже

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

плоскости, в которой вы его видите (координаты x и y) определяе-

мые его полями origin и size. Однако, отображаемые объекты могут

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

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

бавить третью координату - Z.

Т.о., понятие Z-последовательности относится к последова-

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

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

вас по оси "Z" "внутрь" экрана. Последним включенным отображаемым

объектом будет "передний" видимый отображаемый объект.

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

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

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

па может быть представлена в виде "сэндвича" из отображаемых объ-

ектов как показано на рисунке 4.3.

┌──────────────────────┐

│ │

│ ┌──────────────────┼───┐

│ │ │ │ ^

│ │ │ ╞═▒═[ ]═╗

│ │ │ │ ▒ ║

TWindow ───>└───┼──────────────────┘ │ ▒ ║

│ This is some text │ ▒ ║

TScroller ───>└───╥──────────────────┘ █ ║

║ ▒ ║

TScrollbar ───> <▒█▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒> V ║

TFrame ───>╚══════════════════════════┘

Рисунок 4.3. Окно просмотра текстов.

Само окно является лишь "стеклянной пластиной", покрывающей

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

проекцией отображаемых объектов за стекло экрана, вы не сможете

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

если они не перекрываются.

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

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

"фоновым" отображаемым объектом. При создании прокручиваемой

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

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

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

"над" рамкой, закрывая часть рамки.

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

Turbo Vision для С++ = 117 =

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

не в окне, но при просмотре окна вы сможете увидеть этот текст.

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

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

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

собой сэндвичи помельче, как показано на рисунке 4.4.

┌──────────────────────┐

│ │

│ ┌──────────────────┼───────┐

│ │ │ │

│ │ ┌─────┐ │ │

│ │ │▒▒▒▒▒│ │ │

TDesktop ───>└───┼──┼─────┼─────────┘ │

│ │▒▒▒▒▒│ │

TWindow ───> │ └─────┘ │

│ │

TBackground ───>└──────────────────────────┘

Рисунок 4.4. Рабочая область.

Группа (в данном случае рабочая область) также представляет

собой "стеклянную пластину". Первым ее отображаемым объектом яв-

ляется область TBackGround, т.о. этот отображаемый объект будет

расположен "за" всеми остальными. Данный отображаемый объект по-

казывает также два окна в прокручиваемыми внутренними отображае-

мыми объектами в рабочей области (оперативном поле экрана).

Отображение групп

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

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

группа как таковая не отображает себя. Напротив, объект TGroup

требует чтобы его отображаемые объекты могли сами отображать се-

бя.

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

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

емый объект отображается также первым. В таком случае, при перек-

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

объект будет находиться впереди других.

Отображаемые объекты, входящие в группу, должны взаимо-

действовать, чтобы охватывать всю управляемую группой область.

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

екты - рамка, внутренняя часть, элементы управления и статический

текст - должны быть объединены, чтобы полностью "охватить" всю

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

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

(и нежелательные!) последствия.

Turbo Vision для С++ = 118 =

Процесс самоизображения отображаемых объектов группы автома-

тически прекращается на границах группы. Т.к. отображаемые объек-

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

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

границы группы. (Вы можете, например, захватить окно и удалять

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

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

зен, какая-то его часть должна оставаться видимой.) Оставаться

видимой будет лишь часть отображаемого объекта, находящегося в

границах группы которой он принадлежит.

Вы можете пожелать узнать, откуда берется отображаемый фон

рабочей области если она является объектом TGroup. При инициали-

зации рабочая область создает и владеет отображаемым объектом под

названием TBackGround, единственной целью которого является вы-

полнение изображения на едином фоне для всего экрана. Т.к. фон

является первым включаемым отображаемым объектов, он закрывается

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

Взаимоотношения между отображаемыми объектами

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

Отображаемые объекты взаимосвязаны между собой двумя разными

способами: они являются элементами иерархии классов Turbo Vision

и элементами дерева отображаемых объектов. Если вы только начина-

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

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

рисунке 4.5. Она имеет рамку, текстовое сообщение в одну строку и

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

библиотеки Turbo Vision это будет отображаемый объект TDialog,

которому принадлежат отображаемые объекты TFrame, TStaticText и

TButton.

╔═[█]═════ Sample dialog box ═══════════╗

║ ║

║ This is a dialog box text message ║

║ ║

║ OK ▄ ║

║ ▀▀▀▀▀▀▀▀ ║

╚════════════════════════════════════════╝

Рисунок 4.5. Простая панель диалога.

Turbo Vision для С++ = 119 =

Иерархия классов

Одной из форм взаимосвязи отображаемых объектов в иерархии

классов является связь, аналогичная связи родителей и детей. Об-

ратите внимание, что в приведенной на рисунке 3.2. диаграмме ие-

рархии, класс TButton является наследником класса TView. Объект

TButton фактически является классом TView, но он имеет дополни-

тельные поля и методы и поэтому является кнопкой. Объект TDialog

также является порождением класса TView (через классы TGroup и

TWindow), поэтому он имеет много общего с классом TButton. Эти

классы являются далекими "кузенами" в иерархии Turbo Vision.

Владение объектами

Другой формой взаимосвязи отображаемых объектов является де-

рево отображаемых объектов. Как видно из диаграммы, показанной на

рисунке 4.7, объект myTDialog владеет объектом myTButton. В этом

случае взаимоотношения устанавливаются не между классами иерархии

(myTDialog не является предшественником myTButton!), а между эк-

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

┌────────────┐

│ myTDialog │

└──┬───┬───┬─┘

┌─────────┘ │ └───────────┐

┌───┴──────┐ ┌────┴─────┐┌────────┴──────┐

│ myTFrame │ │ myTButton││ myTStaticText │

└──────────┘ └──────────┘└───────────────┘

Рисунок 4.7. Дерево отображаемых объектов простой панели диалога.

В процессе программирования вам потребуется взаимодействие

объекта myTButton с его владельцем по дереву отображаемых объек-

тов (myTDialog), и кроме того объект myTButton будет иметь

свойства, наследуемые от его предшественника (TView). Не следует

путать эти две формы взаимоотношений.

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

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

ражаемых объектов и владением другими отображаемыми объектами. По

мере открытия и закрытия окон вашей программой, дерево отображае-

мых объектов растет и уплотняется, т.к. экземпляры классов вклю-

чаются и удаляются. Естественно, иерархия классов растет только в

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

классов.

Turbo Vision для С++ = 120 =

Отображаемые объекты и деревья отображаемых объектов

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

Как было отмечено выше, отображаемый объект TApplication

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

ми. Такое взаимоотношение и есть пример образования дерева отоб-

ражаемых объектов. Application представляет собой "ствол", а

MenuBar, DeskTop и StatusLine являются "ветвями дерева" как пока-

зано на рисунке 4.8.

┌─────────────┐

│ application │

└──┬──┬───┬───┘

┌────────┘ │ └───────┐

┌───┴─────┐┌────┴────┐┌─────┴──────┐

│ menuBar ││ deskTop ││ statusLine │

└─────────┘└─────────┘└────────────┘

Рисунок 4.8. Базовое дерево отображаемых объектов Turbo Vision.

Однако, имейте в виду, что взаимоотношение отображаемых объ-

ектов, показанное на рисунке 4.8., не является иерархией классов,

а служит моделью структуры данных. Связи между отображаемыми объ-

ектами указывают на владение ими, а не наследование.

Владельцы и отображаемые объекты

В типичной прикладной программе, при нажатии кнопки "мыши"

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

мые объекты. Последние обычно появляются в рабочей области и об-

разуют новые ветви дерева.

Важно четко уяснить эти соотношения между владельцами и

отображаемыми объектами, т.к. и внешний вид и поведение отобража-

емого объекта в большой степени зависит от отображаемого объекта,

который им владеет.

Рассмотрим процесс образования дерева отображаемых объектов.

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

нит вызов окна просмотра файлов. Это окно станет отображаемым

объектом. Turbo Vision создаст окно и присоединит его к рабочей

области.

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

объектов: TFrame (рамка вокруг окна), TScroller (внутренний объ-

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

объекта TScrollBar. При вызове окна, оно создает отображаемые

объекты, владеет и управляет ими.

Примечание: этот же отображаемый объект класса изображен несколь-

ко иначе на рисунке 4.3.

Turbo Vision для С++ = 121 =

Теперь, к нашей увеличивающейся прикладной программе присое-

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

на рисунке 4.8.

┌────────────────────────────────────────────────┐

│ Строка меню │

├────────────────────────────────────────────────┤

│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│

│░░╔═[■]═══ File Viewer Window ══1═[]═╗ ░░░░░░░░│

│░░║ ^ ░░░░░░░░│

│░░║ ▒ ░░░░░░░░│

│░░║ File text ▒ ░░░░░░░░│

│░░║ █ ░░░░░░░░│

│░░║ ▒ ░░░░░░░░│

│░░║ V ░░░░░░░░│

│░░╚══════════<▒█▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒>══════┘ ░░░░░░░░│

│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│

├────────────────────────────────────────────────┤

│ Строка состояния │

└────────────────────────────────────────────────┘

Рисунок 4.8. Рабочая область с добавленным к ней окном

просмотра файлов

Дерево отображаемых объектов также приобрело более сложный

вид, как показано на рисунке 4.10 (связи между отображаемыми объ-

ектами здесь также отражают владение).

Turbo Vision для С++ = 122 =

┌─────────────┐

│ application │

└──┬──┬───┬───┘

┌────────┘ │ └───────┐

┌───┴─────┐┌────┴────┐┌─────┴──────┐

│ menuBar ││ deskTop ││ statusLine │

└─────────┘└────┬────┘└────────────┘

┌────┴───┐

│ window │

└┬─┬──┬─┬┘

┌─────┘ │ │ └──────┐

┌────┴──┐ │ │ ┌───┴──────┐

│ frame │ │ │ │ scroller │

└───────┘ │ │ └──────────┘

┌──┘ └──┐

┌─────────┴──┐ ┌──┴─────────┐

│ scrollBar │ │ scrollBar │

└────────────┘ └────────────┘

Рисунок 4.9. Дерево отображаемых объектов с добавленным к нему

окном просмотра файлов

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

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

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

рисунке 4.10.

┌────────────────────────────────────────────────────┐

│ Строка меню │

├────────────────────────────────────────────────────┤

│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│

│░░╔═══════ File Viewer Window ══1═════╗░░░░░░░░░░░░░│

│░░║ ^░░░░░░░░░░░░░│

│░░║ ╔═[■]═══ File Viewer Window ══2═[]═╗░░░│

│░░║ File te║ ^░░░│

│░░║ ║ ▒░░░│

│░░║ ║ File text ▒░░░│

│░░║ ║ ▒░░░│

│░░║ ║ █░░░│

│░░╚═════════║ ▒░░░│

│░░░░░░░░░░░░║ V░░░│

│░░░░░░░░░░░░╚══════════<▒█▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒>══════┘░░░│

│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│

├────────────────────────────────────────────────────┤

│ Строка состояния │

└────────────────────────────────────────────────────┘

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

файлов.

Собственно и дерево отображаемых объектов еще более усложня-

ется, как показано на рисунке 4.11.

Turbo Vision для С++ = 123 =

Рисунок 4.11. Дерево отображаемых объектов с добавленными к

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

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

┌─────────────┐

│ application │

└──┬──┬───┬───┘

┌────────┘ │ └───────┐

┌───┴─────┐┌────┴────┐┌─────┴──────┐

│ menuBar ││ deskTop ││ statusLine │

└─────────┘└──┬───┬──┘└────────────┘

┌───────────┘ └─────────────────┐

┌────┴───┐ ┌────┴───┐

│ window │ │ window │

└┬─┬──┬─┬┘ └┬─┬──┬─┬┘

┌─────┘ │ │ └─────┐ ┌─────┘ │ │ └───┐

┌────┴──┐ │ │ ┌───┴──────┐ ┌────┴──┐ │ │ ┌───┴──────┐

│ frame │ │ │ │ scroller │ │ frame │ │ │ │ scroller │

└───────┘ │ │ └──────────┘ └───────┘ │ │ └──────────┘

┌──┘ └──┐ ┌──┘ └──┐

┌─────────┴──┐ ┌──┴─────────┐ ┌─────────┴──┐ ┌──┴─────────┐

│ scrollBar │ │ scrollBar │ │ scrollBar │ │ scrollBar │

└────────────┘ └────────────┘ └────────────┘ └────────────┘

Как вы увидите далее, в главе 5, управление программой осу-

ществляется в направлении роста данного дерева отображаемых объ-

ектов. Предположим, что в предыдущем примере вы нажмете на строку

прокрутки в окне просмотра отображаемых объектов. Каким же обра-

зом это нажатие достигнет цели?

Программа Application воспримет нажатие кнопки "мыши", осоз-

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

ластью, и передаст его объекту рабочей области. В свою очередь,

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

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

и отошлет его к этому отображаемому объекту. Теперь окно просмот-

ра отображаемых объектов воспримет нажатие кнопки "мыши", иденти-

фицирует, что оно было выполнено на строке прокрутки и предоста-

вит отображаемому объекту строки прокрутки обработку этого нажа-

тия и посылку соответствующей команды.

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

имеет значения. Важно запомнить форму взаимосвязи отображаемых

объектов. Независимо от того, насколько сложной станет структура

дерева отображаемых объектов, все отображаемые объекты в конечном

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

Примечание: трассировка событий рассматривается в главе 5.

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

просмотра файла или на пункт меню закрытия окна (Close Window),

то второе окно просмотра файлов закроется. Далее Turbo Vision

Turbo Vision для С++ = 124 =

удалит его из дерева отображаемых объектов и ликвидирует. Окно

ликвидирует все свои отображаемые объекты и затем самоликвидиру-

ется.

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

мых объектов к исходным четырем отображаемым объектам и в ка-

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

тием Alt-X или выбором команды Exit в меню. TApplication уничто-

жит три своих отображаемых объекта и самоликвидируется.

Выбранные и выделенные отображаемые объекты

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

В каждой группе отображаемых объектов только один отображае-

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

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

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

объектом, т.к. в ней будет выполняться дальнейшая работа.

Когда в вашей рабочей области открыто несколько окон, то

выбранным окном будет то, в котором вы в данный момент работаете.

Это окно называется также активным окном (обычно самое верхнее

окно).

Выбранный выделенный объект в активном окне называется выде-

ленным видимым объектом. Выделенным объектом можно считать отоб-

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

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

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

объект с находящимся в нем текстом. В панели диалога выделенный

отображаемый объект - это выделенный элемент управления.

Примечание: выделенный отображаемый объект завершает цепочку выб-

ранных отображаемых объектов, начало которой нахо-

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

В программе, диаграмма которой приведена на рисунке 4.12

application - это модальный отображаемый объект, а deskTop - это

его выбранный отображаемый объект. В рабочей области выбранным

является второе окно (включенное позднее), поэтому оно является

активным. В этом окне прокручиваемая внутренняя часть является

выбранной, и т.к. этот отображаемый объект - терминальный (т.е.

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

ленным отображаемым объектом. На рисунке 4.12 представлено это же

дерево отображаемых объектов с цепочкой выделенных отображаемых

объектов, указанных двойными рамками.

Рисунок 4.12. Цепочка выделенных отображаемых объектов.

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

╔═════════════╗

║ Application ║

╚══╤══╤═══╤═══╝

┌────────┘ │ └───────┐

┌───┴─────┐╔════╧════╗┌─────┴──────┐

│ MenuBar │║ DeskTop ║│ StatusLine │

└─────────┘╚══╤═══╤══╝└────────────┘

┌───────────┘ └─────────────────┐

┌────┴───┐ ╔════╧═══╗

│ Window │ ║ Window ║

└┬─┬──┬─┬┘ ╚╤═╤══╤═╤╝

┌─────┘ │ │ └─────┐ ┌─────┘ │ │ └───┐

┌────┴──┐ │ │ ┌───┴──────┐ ┌────┴──┐ │ │ ╔═══╧══════╗

│ Frame │ │ │ │ Scroller │ │ Frame │ │ │ ║ Scroller ║

└───────┘ │ │ └──────────┘ └───────┘ │ │ ╚══════════╝

┌──┘ └──┐ ┌──┘ └──┐

┌─────────┴──┐ ┌──┴─────────┐ ┌─────────┴──┐ ┌──┴─────────┐

│ Scroll Bar │ │ Scroll Bar │ │ Scroll Bar │ │ Scroll Bar │

└────────────┘ └────────────┘ └────────────┘ └────────────┘

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

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

информацию с клавиатуры. Более подробно об этом см. в разделе о

выделенных событиях в главе 5.

Поиск выделенного отображаемого объекта

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

Отображаемый объект, который является в данный момент выде-

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

мер, если в вашей рабочей области открыто несколько окон, то ак-

тивным является окно с двойной рамкой; рамки других окон - оди-

нарные. В панели диалога изображение выделенного элемента управ-

ления (элементы управления - это тоже отображаемые объекты!) бо-

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

этот элемент будет действовать после нажатия клавиши Enter. Выде-

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

ным по умолчанию.

Примечание: в монохромных дисплеях для выделения элементов Turbo

Vision добавляет стрелочные символы.

Как происходит выделение отображаемого объекта?

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

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

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

Turbo Vision для С++ = 126 =

После создания группы отображаемых объектов, элемент-владе-

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

с помощью вызова метода select этого отображаемого объекта. Он

устанавливает выделение по умолчанию.

Пользователю может потребоваться изменить выделенный отобра-

жаемый объект. Обычным способом сделать это служит нажатие с по-

мощью кнопки "мыши" на другом отображаемом объекте. Например,

если в вашей рабочей области открыто несколько окон, вы можете

выбрать разные окна "нажатием" на них с помощью кнопки "мыши". В

панели диалога вы можете перемещать выделение между отображаемыми

объектами с помощью нажатия клавиши Tab, посредством которой мож-

но выполнить циклическое перемещение по всем имеющимся отображае-

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

мощью кнопки "мыши", или нажать управляющую клавишу.

Имейте в виду, что некоторые отображаемые объекты не могут

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

прокрутки. Когда вы создаете отображаемый объект, вы можете ука-

зать, является ли он выбираемым, а после этого отображаемый объ-

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

ример, на рамку окна с помощью кнопки "мыши", то рамка не будет

выделена, т.к. она не может быть выделенным отображаемым объек-

том.

Цепочка выделения отображаемых объектов

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

Если вы проследите по ходу выполнения главной прикладной

программы переход к ее выбранному отображаемому объекту и продол-

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

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

емом объекте. Эта цепочка отображаемых объектов от объекта

TApplication до выделенного отображаемого объекта называется це-

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

трассировки событий, таких как нажатия клавиш.

Примечание: подробнее об этом см. в главе 5.

Модальные отображаемые объекты

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

Режим - это способ действия или функционирования. В програм-

ме может быть несколько режимов работы, отличающихся элементами

управления или областями управления. Например, интегрированная

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

ляции и режим выполнения программы. В зависимости от того, какой

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

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

действий).

Turbo Vision для С++ = 127 =

Отображаемый объект библиотеки Turbo Vision может определять

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

ражаемым объектом. Классическим примером модального отображаемого

объекта является панель диалога. Обычно, когда панель диалога яв-

ляется активной, то вне ее ничего не функционирует. Вы не сможете

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

владеет панель диалога. Кроме того, нажатие с помощью кнопки "мы-

ши", вне панели диалога, не оказывает никакого воздействия. Па-

нель диалога управляет программой вплоть до ее закрытия. (Некото-

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

исключения.)

Когда вы создаете экземпляр отображаемого объекта и делаете

его модальным, то только этот отображаемый объект и его вложенные

отображаемые объекты смогут взаимодействовать с пользователем. Вы

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

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

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

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

дальным отображаемым объектом и его вложенным отображаемым объек-

том. Любой участок дерева отображаемых объектов, который не явля-

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

дет неактивным.

Примечание. Строка состояния всегда доступна, независимо от того

какой объект является модальным.

Имеется лишь одно исключение из этого правила - это строка

состояния. Здесь Turbo Vision допускает небольшой "обман" и дела-

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

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

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

диалога, которой не принадлежит строка состояния. События и ко-

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

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

та.

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

отображаемый объект. При запуске программы и часто в процессе ее

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

программа-объект TApplication в вершине дерева отображаемых объ-

ектов.

Изменение поведения, заданного по умолчанию

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

До сих пор вы могли наблюдать главным образом поведение

стандартных отображаемых объектов, заданное по умолчанию. Но

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

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

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

бы, с помощью которых можно изменять стандартные отображаемые

Turbo Vision для С++ = 128 =

объекты.

Каждый отображаемый объект Turbo Vision имеет четыре битовых

поля (флага), которые вы можете использовать для изменения пове-

дения отображаемого объекта. Здесь идет речь о трех из этих по-

лей: ushort options (16 бит), uchar growMode (8 бит) и uchar

dragMode (8 бит). О четвертом поле, слове eventMask, рассказыва-

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

Имеется также поле uchar state (16 бит), которое содержит

информацию о текущем состоянии отображаемого объекта. В отличие

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

нить только с помощью метода setState. Подробнее об этом см. в

разделе "Признак состояния и метод setState" в данной главе.

Поле флагов options

Поле флагов options - это битовое поле в любом отображаемом

объекте. Различные порождения класса TView имеют различные задан-

ные по умолчанию поля options.

Биты options определены на рисунке 4.14; далее следуют по-

яснения по возможным значениям флагов, содержащимся в поле

options.

Рисунок 4.14. Флаги поля options.

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

┌─────── TView::options ────────┐

msb lsb

┌─┬─────────────────── ofCentered

╔═╤═╤═╤═╤═╤═╤╧╤╧╤═╤═╤═╤═╤═╤═╤═╤═╗

╚╤╧═╧═╧═╧═╧╤╧╤╧╤╧╤╧╤╧╤╧╤╧╤╧╤╧╤╧╤╝

└────┬────┘ │ │ │ │ │ │ │ │ │ └─── ofSelectable

│ │ │ │ │ │ │ │ │ └───── ofTopSelect

Не определены │ │ │ │ │ │ │ └─────── ofFirstClick

│ │ │ │ │ │ └───────── ofFramed

│ │ │ │ │ └─────────── ofPreProcess

│ │ │ │ └───────────── ofPostProcess

│ │ │ └─────────────── ofBuffered

│ │ └───────────────── ofTileable

│ └─────────────────── ofCenterX

└───────────────────── ofCenterY

Флаг ofSelectable

Если установлена эта опция, то пользователь может выбирать

отображаемые объекты с помощью "мыши". Если отображаемый объект

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

"мыши" или клавиши Tab. Если вы помещаете на экран чисто информа-

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

Turbo Vision для С++ = 129 =

ватель мог его выбрать. Например, объекты статического текста и

рамки окон обычно не подлежат выбору.

Флаг ofTopSelect

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

поверх всех отображаемых объектов владельца. Эта возможность

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

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

Флаг ofFirstClick

Нажатие кнопки "мыши", с помощью которого выполняется выбор

отображаемого объекта пересылается далее к отображаемому объекту.

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

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

одним нажатием, поэтому кнопка имеет установку ofFirstClick. Од-

нако, если выполняется какое-либо "нажатие" на окне, вы можете не

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

"мыши" иначе, чем пересылкой его самому себе (т.е. выбора самого

себя).

Флаг ofFramed

Если установлена эта опция, то отображаемый объект будет ок-

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

даете, например, многочисленные "стекла" в окне.

Флаг ofPreProcess

Если установлена эта опция, то она делает возможным обработ-

ку отображаемым объектом выделенных событий до того, как выделен-

ный отображаемый объект их просмотрит. Подробнее об этом см. в

разделе "Фаза" главы 5, "Программирование, управляемое событиями".

Флаг ofPostProcess

Если установлена эта опция, то она позволяет отображаемому

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

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

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

ку и не прекратил его существование. Подробнее об этом см. в раз-

деле "Фаза" главы 5, "Программирование по событиям".

Флаг ofBuffered

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

Turbo Vision для С++ = 130 =

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

требуется отобразить себя, она автоматически сохраняет свой образ

в буфере, если установлен данный бит и имеется достаточный объем

памяти. В следующий раз, когда группе потребуется изобразить се-

бя, она скопирует буферированный образ на экран вместо того, что-

бы заставлять все отображаемые объекты изображать себя. Если вы-

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

ти, то диспетчер памяти Turbo Vision начнет ликвидацию буферов

этих групп до тех пор, пока не будут выполнены требования по объ-

ему памяти.

Если группа имеет буфер, то вызов метода TView::lock прекра-

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

TView::unlock. При вызове этого метода буфер группы будет выдан

на экран. Блокировка может уменьшить мерцание (нежелательное) в

процессе сложных изменений, выполняемых на экране. Например, ра-

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

ми отображаемыми объектами (каскадом отображаемых объектов или

одновременно открытыми отображаемыми объектами).

Флаг ofTileable

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

окнами или каскадировать (перекрывать) их. Если вы не хотите уп-

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

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

томатически.

Управление окнами или каскадирование отображаемых объектов

из TApplication::handleEvent выполняется достаточно просто:

switch(event.message.command)

{

. . .

case cmTile: tile();

break;

case cmCascade: cascade:();

break;

. . .

}

clearEvent(event);

Если требуется каскадировать слишком много отображаемых объ-

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

Примечание. Этот пример вы найдете в файле FVIEWER.CPP на дистри-

бутивных дискетах.

Флаг ofCenterX

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

Turbo Vision для С++ = 131 =

центрировать по координате x.

Флаг ofCenterY

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

центрировать по координате y. Это может быть важным шагом в реа-

лизации успешной работы окна в 25- и 43-строковых текстовых режи-

мах.

Флаг ofCentered

Отцентрировать отображаемый объект по координатам x и y,

когда он помещен в группу.

Turbo Vision для С++ = 132 =

Байт флагов growMode

Поле GrowMode отображаемого объекта определяет, как изме-

нится отображаемый объект, когда будут изменены размеры его груп-

пы-владельца.

Разряды growMode определяются следующим образом:

┌─── growMode ──┐

msb lsb

┌─┬─┬─┬─── gfGrowAll

╔═╤═╤═╤═╤╧╤╧╤╧╤╧╗

╚╤╧═╧╤╧╤╧╤╧╤╧╤╧╤╝

└─┬─┘ │ │ │ │ └─── gfGrowLoX

│ │ │ │ └───── gfGrowLoY

Не определены│ │ └─────── gfGrowHiX

│ └───────── gfGrowHiY

└─────────── gfGrowRel

Рисунок 4.14. Разрядные флаги growMode.

Флаг gfGrowLoX

Если установлена эта опция, то будет сохраняться постоянное

расстояние между левой границей отображаемого объекта и левой

границей его владельца.

Флаг gfGrowLoY

Если установлена эта опция, то будет сохраняться постоянное

расстояние между верхней границей отображаемого объекта и верхней

границей его владельца.

Флаг gfGrowHiX

Если установлена эта опция, то будет сохраняться постоянное

расстояние между правой границей отображаемого объекта и правой

границей его владельца.

Флаг gfGrowHiY

Если установлена эта опция, то будет сохраняться постоянное

расстояние между нижней границей отображаемого объекта и нижней

границей его владельца.

Флаг gfGrowAll

Если установлена эта опция, то размеры отображаемого объекта

будут постоянными и он будет перемещаться параллельно с нижним

Turbo Vision для С++ = 133 =

правым углом его владельца.

Флаг gfGrowRel

Если установлена эта опция, то размер отображаемого объекта

будет определяться размером его владельца. Эту опцию можно

использовать только для объектов TWindow (или их наследников),

которые включены в рабочей области. Окно будет сохранять свой от-

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

43/50 -строковый режим выполнения программы. Этот флаг не может

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

Байт флагов dragMode

Поле DragMode отображаемого объекта определяет поведение

отображаемого объекта при его перемещении.

Биты dragMode определяются следующим образом:

┌─── dragMode ──┐

msb lsb

┌─┬─┬─┬─────────── dmLimitAll

╔╧╤╧╤╧╤╧╤═╤═╤═╤═╗

╚╤╧╤╧╤╧╤╧═╧═╧╤╧╤╝

│ │ │ │ │ └─── dmDragMove

│ │ │ │ └───── dmDragGrow

│ │ │ └─────────── dmLimitLoX

│ │ └───────────── dmLimitLoY

│ └─────────────── dmLimitHiX

└───────────────── dmLimitHiY

Рисунок 4.15. Битовые флаги dragMode.

DragMode имеет следующие установки:

Флаг dmDragMove

Если установлена эта опция, то при нажатии на верхнюю часть

рамки окна вы можете ее сместить.

Флаг dmDragGrow

При установке этой опции отображаемый объект может увеличи-

ваться в размерах.

Флаг dmLimitLoX

При установке этой опции левая граница отображаемого объекта

Turbo Vision для С++ = 134 =

не может выходить за пределы видимого объекта владельца.

Флаг dmLimitLoY

При установке этой опции верхняя часть отображаемого объекта

не может выходить за пределы отображаемого объекта владельца.

Флаг dmLimitHiX

При установке этой опции правая граница отображаемого объек-

та не может выходить за пределы отображаемого объекта владельца.

Флаг dmLimitHiY

При установке этой опции нижняя часть отображаемого объекта

не может выходить за пределы отображаемого объекта владельца.

Флаг dmLimitAll

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

объекта не может выходить за пределы отображаемого объекта вла-

дельца.

Флаг состояния и метод setState

Отображаемый объект также имеет битовый флаг по имени state,

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

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

Turbo Vision для С++ = 135 =

Разряды флага state определены на рисунке 4.16.

┌───── TView::state Flags ──────┐

msb lsb

╔═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╤═╗

╚═╧═╧═╧═╧╤╧╤╧╤╧╤╧╤╧╤╧╤╧╤╧╤╧╤╧╤╧╤╝

│ │ │ │ │ │ │ │ │ │ │ └─── sfVisible = 0x001

│ │ │ │ │ │ │ │ │ │ └───── sfCursorVis = 0x002

│ │ │ │ │ │ │ │ │ └─────── sfCursorIns = 0x004

│ │ │ │ │ │ │ │ └───────── sfShadow = 0x008

│ │ │ │ │ │ │ └─────────── sfActive = 0x010

│ │ │ │ │ │ └───────────── sfSelected = 0x020

│ │ │ │ │ └─────────────── sfFocused = 0x040

│ │ │ │ └───────────────── sfDragging = 0x080

│ │ │ └─────────────────── sfDisabled = 0x100

│ │ └───────────────────── sfModal = 0x200

│ └─────────────────────── sfDefault = 0x400

└───────────────────────── sfExposed = 0x800

Рисунок 4.16. Битовый массив флага state.

Назначение каждого из флагов состояния приведены в главе 16

"Общие вопросы" под рубрикой "Константы sfXXXX". В данном разделе

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

Turbo Vision изменяет флаг состояния отображаемого объекта с

помощью метода setState. Если отображаемый объект становится или

перестает быть видимым, то Turbo Vision вызывает setState. Этот

способ отличается от способов обработки других флагов, т.к. те

устанавливаются при инициализации и в дальнейшем не изменяются

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

это сделать). Состояние отображаемого объекта, однако, часто ме-

няется в процессе его нахождения на экране. В связи с этим, Turbo

Vision имеет механизм, реализованный с помощью метода setState,

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

та, но и реагировать на эти изменения.

Метод setState получает информацию о состоянии (aState) и

флаг (enable), указывающие, является ли состояние установленным

или сброшенным. Если enable имеет значение True, то разряды в

aState устанавливаются в положение state. Если enable имеет зна-

чение False, то соответствующие разряды state очищаются. Таким же

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

поля проявится, если вам потребуется, чтобы отображаемый объект

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

Turbo Vision для С++ = 136 =

Действия отображаемых объектов при смене состояния

Отображаемые объекты часто предпринимают какие-либо действия

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

флагов. Например, кнопка просматривает поле state и изменяет цвет

на синий, когда она становится выделенной. Ниже приведен типичный

пример реализации метода setState для наследника TView.

virtual void TButton::setState(ushort aState,boolean enable );

{

TView::setState(aState, enable);

if(aState & (sfSelected | sfActive))

drawView();

if(aState & sfFocused)

makeDefault(enable);

}

Обратите внимание, что вы должны всегда вызывать TView::set-

State из нового метода setState. TView::setState выполняет факти-

ческую установку или очистку флагов состояния. Затем вы можете

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

отображаемого объекта. TButton::setState проверяет, находится ли

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

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

емый объект выделенным, и в этом случае он вызывает метод

makeDefault, который устанавливает или сбрасывает выделение отоб-

ражаемого объекта, в зависимости от параметра enable.

Если вам требуется внести изменения в отображаемый объект

или прикладную программу при изменении состояния отдельного отоб-

ражаемого объекта, то вы можете сделать это с помощью переопреде-

ления метода SetState отображаемого объекта.

При изменении состояния программист часто прибегает к помощи

Turbo Vision. Предположим, что вам требуется, чтобы блок-курсор

(курсор увеличенной высоты) появился в вашем текстовом редакторе,

например, когда включен режим вставки текста.

Во-первых, режим вставки текста будет привязанным к нажатию

клавиши - скажем, клавиши Ins. Когда текстовый редактор является

выделенным отображаемым объектом, а клавиша Ins нажата, то в

текстовый редактор посылается событие "нажата клавиша Ins". Обра-

ботчик событий текстового редактора handleEvent реагирует на на-

жатие Ins переключением внутреннего состояния отображаемого объ-

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

toggleInsMode. Turbo Vision выполнит все остальные операции.

toggleInsMode вызывает метод setState отображаемого объекта для

установки состояния sfCursorIns в положение True:

void TEditor::toggleInsMode

{

overwrite = Boolean(!overwrite);

setState(sfCursorIns,Boolean(!getstate(sfCursorIns)));

Turbo Vision для С++ = 137 =

}

Метод getState возвращает True, если командный аргумент

установлен в state. Бит sfCursorIns во флаге state определит вид

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

замены. Установка команд легко выполняется с помощью объектов ти-

па TCommandSet, которые, обычно, представляют собой переопреде-

ленные методы. Например:

TCommandSet s, command;

. . .

s += command;

добавляет command к списку s. Аналогично, -= удаляет command из

списка. Мы вводим такие команды как enabling и disabling. Опера-

торы == и != проверяют на равенство две команды.

Turbo Vision для С++ = 138 =

Какого цвета ваш отображаемый объект?

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

По вопросу наилучших цветов на экране компьютера всегда су-

ществуют разногласия. Поэтому Turbo Vision предоставляет возмож-

ность изменять цвета отображаемых объектов, которые вы помещаете

на экране. Чтобы упростить этот процесс Turbo Vision имеет палит-

ры цветов, которые управляются классом TPalette.

Палитры цветов

Когда отображаемый объект Turbo Vision выполняет свое отоб-

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

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

ре цветов. Например, палитра для TScroller выглядит следующим об-

разом:

#define cpScroller = "\x06\x07"

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

объектов приводится в главе 13.

Палитры цветов являются объектами класса TPalette. Они фак-

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

переменной длины. Т.о., cpScroller представляет собой двухсим-

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

ры.

Формат палитры TScroller определяется следующим образом:

// Палитра

// 1 = Нормальный

// 2 = Подсвеченный

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

1 2

┌───┬───┐

CScroller │ 6 │ 7 │

└───┴───┘

│ │

│ └───────── Выделенный текст

└───────────── Нормальный текст

Рисунок 4.17. Палитра цветов TScroller, принимаемая по умолчанию

Это означает, что объект "прокрутка" способен выдавать изоб-

ражение двух видов текста: нормального и выделенного. Цвет каждо-

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

изображении нормального (обычного) текста функция draw должна вы-

зывать getColor(1), что означает, что требуется цвет, указанный в

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

Turbo Vision для С++ = 139 =

выполняться вызов getColor(2).

Примечание: getColor - это метод класса TView.

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

цветах, заданных по умолчанию, то больше ничего знать не требу-

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

комбинация объектов выберет для себя подходящие цвета.

Примечание: описание выбора цветов, не заданных по умолчанию, да-

но в следующем разделе.

Внутренние палитры цветов

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

цветов их владельца, а не на сами цвета. Если объект "прокрутка"

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

зова цвета нормального текста в палитре объекта "прокрутка", ко-

торый содержит число 6. Чтобы перевести его в значение цвета, вы

должны найти позицию 6 в палитре владельца. На рисунке 4.19 пока-

зана палитра TWindow.

Рисунок 4.19. Отображение палитры объекта "прокрутка" в окне

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

┌───────────────────────────── Рамка пассивна

│ ┌───────────────────────── Рамка активна

│ │ ┌───────────────────── Пиктограмма рамки

│ │ │ ┌───────────────── Страница полосы прокрутки

│ │ │ │ ┌───────────── Элементы управления полосой

│ │ │ │ │ прокрутки

│ │ │ │ │ ┌───────── Нормальный текст объекта

│ │ │ │ │ │ прокрутки

│ │ │ │ │ │ ┌───── Выбранный текст объекта

│ │ │ │ │ │ │ прокрутки

│ │ │ │ │ │ │ ┌─ Зарезервированный

│ │ │ │ │ │ │ │

1 2 3 4 5 6 7 8

┌───┬───┬───┬───┬───┬───┬───┬───┐

│ 8 │ 9 │ 10│ 11│ 12│ 13│ 14│ 15│ cpBlueWindow

└───┴───┴───┴───┴───┴─┬─┴───┴───┘

┌───────────────────┘

┌─┴─┬───┐

│ 6 │ 7 │ cpScroller

└───┴───┘

│ │

│ └─────────────────────── Выделенный текст

└─────────────────────────── Нормальный текст

В палитре TWindow шестой позицией является число 13, которое

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

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

Turbo Vision для С++ = 140 =

ца, прикладной программы. Объект TDeskTop имеет палитру nil (ну-

левую), что означает, что она ничего не изменяет - ее можно

представить себе как "прямую" или "явную" палитру, в которой пер-

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

Прикладная программа имеет большую палитру цветов, содержа-

щую позиции для всех объектов, которые вы могли бы включить в

программу Turbo Vision. Ее 13-м элементом является 0x1E. Приклад-

ная программа завершает цепочку (она не имеет владельца, поэтому

отображение палитр на ней заканчивается).

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

признака текста, соответствующим цвету фона 1 и цвету изображения

0xE (или 14), в результате чего вы получите желтые символы на го-

лубом фоне. Однако, вы не должны использовать терминологию "жел-

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

мальном цвете для текста в окне.

Не считайте палитры наборами цветов. Они являются видами

отображаемых объектов.

Метод getColor

Отображение палитры цветов выполняется виртуальным методом

getColor объекта TView. Этот метод поднимается по дереву отобра-

жаемых объектов от объекта, изображаемого в его владельце, к вла-

дельцу владельца и т.д. до момента, когда он дойдет до объекта

прикладной программы. При продвижении по цепочке для каждого объ-

екта метод getColor вызывает getPalette. Конечным результатом

этого процесса является признак цвета.

Палитра цвета содержит смещение в палитру его владельца, за

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

наки цветов.

Переопределение цветов, заданных по умолчанию

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

Очевидным способом изменения цветов является изменение па-

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

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

(позиция цвета нормального текста) в палитре объекта прокрутки,

например, с 6 на 5. Нормальный текст объекта прокрутки будет за-

тем отображен в окне в цветовой гамме объектов управления строки

прокрутки (голубой на синем по умолчанию). Не забудьте: 5 - это

не цвет! Вы указали лишь, что цвет нормального текста объекта

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

вокруг него!

Что же вам надо сделать, если вы не хотите иметь сочетание

цветов желтый на голубом? Измените позицию палитры для нормально-

Turbo Vision для С++ = 141 =

го текста в окне в TApplication. Т.к. эта палитра является

последней не nil (не нулевой), то позиции в палитре прикладной

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

Пусть это будет вашим принципом установки цветов: цвета не явля-

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

Это имеет определенный смысл. По-видимому, вы хотели бы,

чтобы ваши окна выглядели похожими. И конечно же не хотели бы от-

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

свое намерение (или разрешите пользователям настройку цветов), то

вам придется изменять позиции для каждого окна.

Объект прокрутки или другой внутренний объект может на забо-

титься о своей расцветке, если он помещен не в то окно, в которое

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

объект прокрутки в окно диалога вместо окна, то он не будет (по

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

мального текста в панели диалога.

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

реопределить метод TView::getPalette. Чтобы создать новый тип

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

веткой рамки окна, а не с расцветкой нормального текста, объявле-

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

class TMyScroller : public TScroller

{

. . .

virtual TPalette& getPalette() const ;

. . .

};

virtual TPalette& TMyScroller::getPalette() const

{

static TPalette palette(cpFrame,sizeof(cpFrame) - 1);

return palette;

}

Конструктор TPalette имеет два параметра: строку, представ-

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

ры. По умолчанию этот метод возвращает стандартную палитру соот-

ветствующего класса.

Добавление новых цветов

Вам может потребоваться добавить дополнительные цвета в

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

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

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

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

в редакторе интегрированной среды. Вы можете это осуществить, по-

рождая новый тип класса из существующего класса TWindow и добав-

Turbo Vision для С++ = 142 =

ляя его к палитре, заданной по умолчанию, как показано ниже:

#define cpNewPalette cpBlueWindow "\x54"

class TMyWindow :public TWindow

{

. . .

virtual TPalette& getPalette() const ;

. . .

}

virtual TPalette& TMyWindow::getPalette() const

{

static TPalette palette(cpNewPalette,sizeof(cpNewPalette)

- 1);

return palette;

}

Примечание: палитры являются строками, поэтому вы можете исполь-

зовать строковые операции, такие как "+".

Теперь объект TMyWindow имеет новую палитру, которая содер-

жит этот новый тип выделения. cpBlueWindow - это строковая

константа, содержащая палитру TWindow, заданную по умолчанию:

#define cpBlueWindow "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"

Чтобы использовать это преимущество, придется изменить подп-

рограмму getPalette класса MyScroller:

virtual TPalette& TMyScroller::getPalette() const

{

const char *cpMyScroller = "\x06\x07\x09";

static TPalette palette(cpMyScroller,sizeof(cpMyScroller)

- 1);

return palette;

}

Позиция 3 палитры объекта прокрутки теперь является новым

цветом выделения (в данном случае это ярко-белый на красном).

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

cpMyScroller, который имеет доступ к девятому элементу в палитре

его владельца, то убедитесь, что владелец действительно использу-

ет палитру cpMyWindow. Если вы попытаетесь получить доступ к де-

вятому элементу в 8-элементной палитре, то результат будет неп-

редсказуемым.

Turbo Vision для С++ = 143 =