Модификация поведения видимых элементов.
До этого момента Вы видели как ведут себя стандартные видимые элементы по умолчанию. Но иногда Вам потребуется, чтобы видимые элементы выглядели или действовали несколько по-другому и Turbo Vision предоставляет такую возможность. Этот раздел объясняет способы модификации стандартных видимых элементов. Каждый видимый элемент Turbo Vision имеет 4 поля, которые можно использовать для изменения поведения этого элемента. 3 из них описаны здесь: слово Options, байт GrowMode и байт DragMode. Четвертое поле - слово EventMask описано в главе 5. Существует так же слово State, содержащее информацию о текущем состоянии видимого элемента. В отличие от других полей State используется только для чтения. Его значение должно изменяться только методом SetState. Для дополнительных деталей смотри раздел "Флаг State и SetState".
Модуль App.
Модуль App (предоставлен в исходных кодах) обеспечивает элементы оболочки Turbo Vision. 4 очень мощных объектных типа определены в App, включая объекты TApplication и TProgram, которые служат в качестве программ Turbo Vision и объект панели экрана, который управляет большинством элементов в оконных программах.
Типы.
------------------------------------------------------------- Тип Использование ------------------------------------------------------------- TApplication Объект-программа с монитором событий, монитором экрана, обработкой ошибок и управлением памятью TBackGround Цвет фона для панели экрана TDeskTop Групповой объект для окон и диалоговых окон TProgram Абстрактный объект-программа -------------------------------------------------------------
Переменные.
------------------------------------------------------------- Переменная Тип Начальное Назначение значение ------------------------------------------------------------- Application PProgram nil Указатель на текущую программу DeskTop PDeskTop nil Указатель на текущую панель экрана StatusLine PStatusLine nil Указатель на текущую строку статуса MenuBar PMenuView nil Указатель на текущую полосу меню -------------------------------------------------------------
Модуль Dialogs.
Модуль Dialogs определяет большинство элементов наиболее часто используемых при создании диалоговых окон. Это включает сами диалоговые окна (которые являются специализированными окнами) и различные элементы управления, такие как кнопки, метки, зависимые и независимые кнопки, строки ввода и списки истории.
Типы.
------------------------------------------------------------- Тип Использование ------------------------------------------------------------- TButton Нажатия кнопок для генерации команд TCheckBoxes Кластеры с включением и выключением кнопок TCluster Абстракный тип для зависимых и независимых кнопок TDialog Специализированное окно для диалоговых окон THistory Список предыдущих элементов для строки ввода TInputLine Редактор текстового ввода TLabel Метка для кластера или строки ввода TListBox Скроллингуемый список для выбора пользователем TParamText Форматированный статический текст TRadioButtons Кластер или кнопки, только одна из которых может быть нажата TSItem Элементы строк в связанном списке, используемые кластерами TStaticText Простой текст -------------------------------------------------------------
Константы.
Флаги кнопок.
------------------------------------------------------------- Константа Значение Назначение ------------------------------------------------------------- bfNormal $00 Обычная кнопка bfDefault $01 Кнопка по умолчанию bfLeftJust $02 Кнопка текста может быть выровнена влево -------------------------------------------------------------
Процедуры и функции.
------------------------------------------------------------- Функция Операция ------------------------------------------------------------- NewSItem Создает новый элемент строки для окна списка -------------------------------------------------------------
------------------------------------------------------------- Процедура Операция ------------------------------------------------------------- RegistersDialogs Регистрирует все объекты в модуле Dialogs для использования с потоками -------------------------------------------------------------
Модуль Drivers.
Модуль Drivers содержит все специализированные драйверы Turbo Vision, включая драйверы мышки и клавиатуры, поддержку экрана и систему обработки ошибок с монитором событий для программ, управляемых событиями.
Типы.
------------------------------------------------------------- Тип Использование ------------------------------------------------------------- TEvent Тип записи события TSysErrorFunc Функциональный тип обработчика системных ошибок -------------------------------------------------------------
Константы.
Маски состояния кнопок мышки.
------------------------------------------------------------- Константа Значение Назначение ------------------------------------------------------------- mbLeftButton $01 Левая кнопка мышки mbRightButton $02 Правая кнопка мышки -------------------------------------------------------------
Коды событий.
------------------------------------------------------------- Константа Значение Назначение ------------------------------------------------------------- evMouseDown $0001 Кнопка мышки нажата evMouseUp $0002 Кнопка мышки освобождена evMouseMove $0004 Мышка изменила положение evMouseAuto $0008 Автоматический повтор события от мышки evKeyDown $0010 Событие - нажатие клавиши evCommand $0100 Событие - команда evBroadcast $0200 Событие - общее сообщение -------------------------------------------------------------
Маски событий.
------------------------------------------------------------- Константа Значение Назначение ------------------------------------------------------------- evNothing $0000 Событие очищено evKeyboard $0010 Событие пришло от клавиатуры evMouse $000F Событие пришло от мышки evMessage $FF00 Событие - сообщение или команда -------------------------------------------------------------
Маски клавиатуры.
------------------------------------------------------------- Константа Значение Назначение ------------------------------------------------------------- kbRightShift $0001 Нажат правый Shift kbLeftShift $0002 Нажат левый Shift kbCtrlShift $0004 Нажат Ctrl и Shift kbAltShift $0008 Нажат Alt и Shift kbScrollState $0010 Установлен Scroll lock kbNumState $0020 Установлен Num lock kbCapsState $0040 Установлен Caps lock kbInsState $0080 Включен режим Insert -------------------------------------------------------------
Коды стандартных команд.
------------------------------------------------------------- Команда Значение Назначение ------------------------------------------------------------- cmValid 0 Проверка правильности нового элемента cmQuit 1 Завершение программы cmError 2 Неопределено cmMenu 3 Активность полосы меню cmClose 4 Закрывает текущее окно cmZoom 5 Масштабирует окно cmResize 6 Изменяет размеры окна cmNext 7 Делает активным следующее окно cmPrev 8 Делает активным предыдущее окно -------------------------------------------------------------
Стандартные команды TDialog.
------------------------------------------------------------- Команда Значение Назначение ------------------------------------------------------------- cmOK 10 Нажата кнопка OK cmCanced 11 Нажата кнопка Cancel или Esc cmYes 12 Нажата кнопка Yes cmNo 13 Нажата кнопка No cmDefault 14 Нажата кнопка по умолчанию или Enter -------------------------------------------------------------
Режимы экрана.
------------------------------------------------------------- Константа Значение Назначение ------------------------------------------------------------- smBW80 $0002 Черно-белый режим smCO80 $0003 Цветной режим smMono $0007 Монохромный режим smFont8x8 $0100 Режим 43 или 50 строк (EGA/VGA) -------------------------------------------------------------
Переменные.
Инициализированные переменные.
------------------------------------------------------------- Переменная Тип Начальное Назначение значение ------------------------------------------------------------- ButtonCount Byte 0 Число кнопок мышки MouseEvents Boolean False Указывает на выбор мышкой DoubleDelay Word 8 Максимальное время задержки между двойными нажатиями RepeatDelay Word 8 Задержка между автоматическим повтором события от мышки -------------------------------------------------------------
Неинициализированные переменные.
------------------------------------------------------------- Переменная Тип Назначение ------------------------------------------------------------- MouseIntFlag Byte Только для внутренного использования MouseButtons Byte Какая кнопка была нажата MouseWhere TPoint Позиция курсора мышки StartupMode Word Режим экрана при запуске программы ScreenMode Word Текущий режим экрана ScreenWidth Byte Ширина экрана в колонках ScreenHeight Byte Высота экрана в строках CheckSnow Boolean Определяет "снежность" для CGA HiResScreen Boolean Экран может отображать 43 или 50 строк (EGA/VGA) ScreenBuffer Pointer Указатель на видеобуфер экрана CursorLines Word Начало и окончание строк просмотра для установки типа курсора -------------------------------------------------------------
Переменные обработчика системных ошибок.
------------------------------------------------------------- Переменная Тип Начальное Назначение значение ------------------------------------------------------------- SysErrorFunc SysErrorFunc SystemError Функция, вызываемая монитором системной ошибки при ее возникновении SysColorAttr Word $4E4F Видеоатрибуты для сообщений об ошибках на цветном экране SysMonoAttr Word $7070 Видеоатрибуты для сообщений об ошибках на монохромном экране CtrlBreakHit Boolean False Указывает, нажата ли пользователем Ctrl-Break SaveCtrlBreak Boolean False Статус проверки Ctrl-Break при запуске программы -------------------------------------------------------------
Процедуры и функции.
Процедуры монитора событий.
------------------------------------------------------------- Процедура Операция ------------------------------------------------------------- InitEvents Инициализирует монитор событий DoneEvents Закрывает монитор событий ShowMouse Отображает курсор мышки HideMouse Стирает курсор мышки GetMouseEvent Создает запись события от мышки GetKeyEvent Создает запись события от клавиатуры -------------------------------------------------------------
Процедуры управления экраном.
------------------------------------------------------------- Процедура Операция ------------------------------------------------------------- InitVideo Инициализирует монитор экрана DoneVideo Закрывает монитор экрана SetVideoMode Выбирает режим экрана (цветной, черно-белый, монохромный, высокого разрешения) ClearScreen Очищает экран при любом видео режиме -------------------------------------------------------------
Функция по умолчанию обработчика системной ошибки.
------------------------------------------------------------- Функция Операция ------------------------------------------------------------- SystemError Отображает сообщение об ошибке в нижней строке экрана и подсказки для завершения или повтора -------------------------------------------------------------
Процедуры обработчика системной ошибки.
------------------------------------------------------------- Процедура Операция ------------------------------------------------------------- InitSysError Инициализирует монитор системных ошибок DoneSysError Закрывает монитор системных ошибок -------------------------------------------------------------
Функции поддержки клавиатуры.
------------------------------------------------------------- Функция Операция ------------------------------------------------------------- GetAltChar Возвращает символ от клавиатуры GetAltCode Возвращает скан-код от клавиатуры -------------------------------------------------------------
Процедура форматирования строки.
------------------------------------------------------------- Процедура Операция ------------------------------------------------------------- FormatStr Форматирует строку -------------------------------------------------------------
Процедуры копирования буфера.
------------------------------------------------------------- Процедура Операция ------------------------------------------------------------- MoveBuf Копирует буфер в другой буфер MoveChar Копирует одну или более копий символа в буфер MoveCStr Копирует строку управления в буфер MoveStr Копирует строку в буфер -------------------------------------------------------------
Функция длины строки.
------------------------------------------------------------- Функция Операция ------------------------------------------------------------- CStrLen Возвращает длину строки, игнорируя "~" -------------------------------------------------------------
Инициализация драйвера.
------------------------------------------------------------- Процедура Операция ------------------------------------------------------------- InitDrivers Инициализирует драйверы модуля -------------------------------------------------------------
Модуль HistList.
Модуль HistList содержит все переменные, процедуры и функции необходимые для реализации списков истории.
Переменные.
------------------------------------------------------------- Переменная Тип Начальное Назначение значение ------------------------------------------------------------- HistoryBlock Pointer nil Буфер памяти для всех элементов списка истории HistorySize Word 1024 Размер блока истории HistoryUsed Word 0 Смещение в блоке истории, указывающее число использованных блоков -------------------------------------------------------------
Модуль Memory.
Модуль Memory содержит процедуры монитора памяти Turbo Vision, которые обеспечивают функции управления кучей.
Переменные.
------------------------------------------------------------- Переменная Тип Начальное Назначение значение ------------------------------------------------------------- LowMemSize Word 4096 div 16 Размер пула надежности -------------------------------------------------------------
Процедуры и функции.
------------------------------------------------------------- Процедура Операция ------------------------------------------------------------- InitMemory Инициализирует монитор памяти DoneMemory Закрывает монитор памяти GetBufMem Распределяет кэш-буфер для группы FreeBufMem Удаляет кэш-буфер для группы -------------------------------------------------------------
------------------------------------------------------------- Функция Операция ------------------------------------------------------------- LowMemory Указывает распределен ли буфер надежности MemAlloc Распределяет память с проверкой буфера надежности -------------------------------------------------------------
Модуль Menus.
Модуль Menus обеспечивает все объекты и процедуры для системы меню Turbo Vision, включая выпадающие меню и активные элементы строки статуса.
Типы.
------------------------------------------------------------- Тип Использование ------------------------------------------------------------- TMenu Связанный список записей TMenuItem TMenuBar Связанный с меню горизонтальный заголовок TMenuBox Выпадающие окна меню TMenuItem Запись, связывающая метку текста, горячую клавишу, команду и контекстную подсказку TMenuStr Строковый тип для меток меню TMenuView Абстрактный объектный тип для полосы и окон меню TStatusDef Запись, связывающая контекстных подсказки со списком элементов строки статуса TStatusItem Строка сообщения внизу экрана программы, включающая список записей TStatusDef TStatusLine -------------------------------------------------------------
Процедуры и функции.
Функции TMenuItem.
------------------------------------------------------------- Функция Операция ------------------------------------------------------------- NewItem Создает новый элемент меню NewLine Создает строку окна меню NewSubMenu Создает подменю полосы меню или окна меню -------------------------------------------------------------
Процедуры TMenu.
------------------------------------------------------------- Процедура Операция ------------------------------------------------------------- NewMenu function Распределяет меню в куче DisposeMenu procedure Удаляет меню из кучи -------------------------------------------------------------
Функции TStatusLine.
------------------------------------------------------------- Функция Операция ------------------------------------------------------------- NewStatusDef Определяет диапазон контекстных подсказок и указатель на список элементов статуса NewStatusKey Определяет элемент строки статуса и связывает его с командой и горячей клавишей -------------------------------------------------------------
Модуль Objects.
Модуль Objects содержит основные определения объектов Turbo Vision, включая базовый объект иерархии Turbo Vision TObject, а так же все невидимые элементы Turbo Vision: потоки, коллекции и ресурсы.
Модуль TextView.
Модуль TextView содержит несколько специализированных видимых элементов для отображения текста в окне скроллинга.
Типы.
------------------------------------------------------------- Тип Использование ------------------------------------------------------------- TTerminal TTY подобный текстового устройства TTerminalBuffer Круговой текстовый буфер для TTerminal TTextDevice Абстрактный объект текстового усройства -------------------------------------------------------------
Процедура.
------------------------------------------------------------- Процедура Операция ------------------------------------------------------------- AssignDevice Назначает устройство текстового файла для ввода и/или вывода -------------------------------------------------------------
Модуль Views.
Модуль Views содержит основные компоненты видимых элементов. Это оба абстрактных типа, таких как TView и TGroup и полезные компоненты более сложных групп, таких как рамки окон и полосы скроллинга. Более сложные видимые элементы находятся в модулях Dialogs и TextView.
Типы.
------------------------------------------------------------- Тип Использование ------------------------------------------------------------- TCommandSet Разрешает и запрещает группы команд TDrawBuffer Буфер, используемый для методов отрисовки TFrame Рамка объекта, используемая окнами TGroup Абстрактный объект для сложных видимых элементов TListViewer Базовый тип для окон списков и т.п. TPalette Тип палитры, используемой всеми видимыми элементами TScrollBar Объект определяющий полосу скроллинга TScrollChars Символьные компоненты полосы скроллинга TScroller Базовый объект для скроллинга текста в окнах TTitleStr Строка заголовка, используемая TFrame TVideoBuf Видеобуфер, используемый монитором экрана TView Абстракный объект; основа всех видимых объектов TWindow Базовый объект для окон изменяющих размеры -------------------------------------------------------------
Нахождение активного элемента.
Активный видимый элемент обычно подсвечивается на экране. Например, если Вы открыли на панели экрана несколько окон, активное окно окружено двойной рамкой, а остальные одинарной. Внутри диалогового окна активный элемент управления (а элемент управления это тоже видимый элемент) ярче других, указывая на то, что он будет действовать когда Вы нажмете Enter. Т.е. активный элемент управления также является элементом управления по умолчанию. (На монохромных мониторах Turbo Vision добавляет символы стрелок для указания активного элемента).
Не-объекты в потоке.
Вы можете писать в поток данные, которые не являются объектами, но Вы должны использовать при этом другой подход. Стандартные методы Get и Put требуют, чтобы Вы сохраняли или загружали объект, порожденный от TObject. Если Вы хотите создать поток не-объектов, перейдите прямо на низкоуровневые процедуры Read и Write, каждая из которых читает или пишет заданное число байт в поток. Этот же механизм используется в Get и Put для чтения и записи данных объектов; Вы просто обходите механизм VMT, используемый в Get и Put.
Неиспользованное время.
Другое преимущество центрального местонахождения TApplication. GetEvent в том, что он вызывает метод TApplication.Idle, если нет готовых событий. TApplication.Idle - это пустой метод, который Вы можете перекрыть для того, чтобы выполнять параллельную обработку одновременно с текущим видимым элементом. Например предположим, Вы определили видимый элемент, названный THeapView, который использует метод UpDate для отображения доступной в данный момент памяти кучи. (Пример просмотра кучи включен в демонстрационные программы на Ваших дистрибутивных дисках.) Если Вы перекрываете TApplication.Idle, следующим кодом пользователь сможет увидеть отображение доступной памяти в куче вне зависимости от его нахождения в программе.
procedure TMyApp.Idle; begin HeapViewer.Update; end;
Ненужные события.
Обычно каждое событие обрабатывается каким-либо из видимых элементов Вашей программы. Если ни один из видимых элементов не обработал событие, модальный видимый элемент вызывает EventError. EventError вызывает EventError владельца видимого элемента и так до тех пор, пока не будет вызван TApplication.EventError. TApplication.EventError по умолчанию ничего не делает. При необходимости Вы можете перекрыть EventError для вызова диалогового окна с ошибкой или подачи сигнала. Поскольку конечный пользователь Вашей программы не отвечает за ошибки программы, обрабатывающей событие, такое диалоговое окно вероятно должно быть удалено из коммерческой версии программы. ClearEvent так же помогает видимым элементам взаимодействовать друг с другом. Сейчас запомните, что Вы не закончите обработку события до тех пор, пока не вызовите ClearEvent.
Несколько видимых элементов в окне.
Давайте продублируем интерьер и создадим окно с двумя скользящими видимыми элементами для текстового файла. Мышка или клавиша Tab автоматически выбирает один из двух интерьеров. Каждый видимый элемент скользит независимо и имеет собственную позицию курсора. Чтобы сделать это, расширьте метод MakeInterior так, чтобы он знал, какая часть окна является активным интерьером (поскольку различные части ведут себя несколько по-разному) и сделайте 2 вызова MakeInterior в TDemoWindow.Init.
{ TVGUID09.PAS }
{ Не забудьте изменить объявление MakeInterior } procedure TDemoWindow.MakeInterior(Bounds: TRect; Left: Boolean); var Interior: PInterior; R: TRect; begin Interior := New(PInterior, Init(Bounds, StandartScrollBar(sbHorizontal), StandartScrollBar(sbVertical))); if Left then Interior^.GrowMode := gfGrowHiY else Interior^.GrowMode := gfGrowHiX + gfGrowHiY; Insert(Interior); end;
constructor TDemoWindow.Init(Bounds: TRect; WinTitle: String; WindowNo: Word); var S: string[3]; R: TRect; begin Str(WindowNo, S); TWindow.Init(Bounds, WinTitle + ' ' + S, wnNoNumber); GetExtent(Bounds); R.Assign(Bounds.A.X, Bounds.A.Y, Bounds.B.X div 2 + 1, Bounds.B.Y); MakeInterior(R, True); R.Assign(Bounds.B.X div 2, Bounds.A.Y, Bounds.B.X, Bounds.B.Y); MakeInterior(R,False); end;
Рис. 2.6. Окно с несколькими панелями.
+-----------------------------------------------------------+ |***********************************************************| |*+=[ю]================ Demo Window 1 ================[ш]=+*| |*| | while not Eof(F) and (LineCountш*| |*|var | begin #*| |*| LineCount: Integer;| Readln(F, S); #*| |*| Lines: array[0Max| Lines[LineCount] := NewStr(S)#*| |*| | Inc(LineCount); #*| |*|type | end; #*| |*| TMyApp = object(TAp| Close(F); #*| |*| procedure HandleE|end; #*| |*| procedure InitMen| ю*| |*| procedure InitSta|procedure DoneFile; #*| |*| procedure NewWind|var #*| |*| end; | I: Integer; #*| |*| |begin щ*| |*+=====================+=<ю############################>-+*| |***********************************************************| +-----------------------------------------------------------+
Заметим, что Вы изменили форму и содержимое MakeInterior. Вместо объявления двух статических полос скроллинга и передачи их в метод Init, Вы просто включили вызовы StandardScrollBar в качестве параметров Init. Предыдущая форма несколько яснее, но эта более эффективно. Если Вы уменьшите окна в TVGUID09.PAS, Вы заметите, что вертикальная полоса скроллинга будет перекрыта левым интерьером видимого элемента, если Вы передвините правую сторону окна слишком близко к левой. Чтобы предотвратить это, Вы можете установить нижнюю допустимую границу на уменьшение окна. Вы делаете это, перекрывая метод SizeLimits в TWindow.
{ TVGUID10.PAS }
{ Не забудьте добавить SizeLimits в TDemoWindow. Это виртуальный метод} procedure TDemoWindow.SizeLimits(var Min, Max: TPoint); var R: TRect; begin TWindow.SizeLimits(Min, Max); GetExtent(R); Min.X := R.B.X div 2; end;
Заметим, что Вы не вызываете SizeLimits, Вы просто перекрываете его и он будет вызываться в соответствующее время. Здесь делается то же, что Вы делали с методом Draw: Вы говорите видимому элементу как его рисовать, но не когда. Turbo Vision уже знает когда вызвать Draw. Это же применимо и к SizeLimits: Вы устанавливаете границы, а видимый элемент знает тот момент, когда необходимо проверить их.
Невидимые элементы.
Семейство невидимых элементов, порожденное от TObject, содержит потоки, файлы ресурсов, коллекции и списки строк.
Невидимые объекты.
Невидимые объекты - это любые другие объекты программы, отличные от видимых элементов. Они "невидимы", поскольку сами ничего не выводят на экран. Они производят вычисления, связь с периферией и выполняют другую работу прикладной программы. Когда невидимому объекту необходимо вывести что-либо на экран, он должен выполнить это, связавшись с видимым элементом. Эта концепция очень важна для поддержания порядка в программе Turbo Vision: только видимые элементы могут взаимодействовать с дисплеем.
Примечание: Ничто не запретит Вам вывести из невидимого объекта на экран информацию с помощью операторов Write и Writeln. Однако, если Вы сами выводите на экран, Ваш текст будет разрушать текст, выводимый Turbo Vision, а текст, который выводит Turbo Vision (например, передвигая или изменяя размер окон) будет затирать Ваш текст.
Номера ID объектов.
Поле ObjType - это единственная часть записи, которую Вы должны знать. Каждый новый тип, определенный Вами, будет требовать своего собственного уникального номера типа. Turbo Vision резервирует регистрационные номера от 0 до 99 для стандартных объектов. Вы можете использовать регистрационные номера от 100 до 65,535.
Примечание: Вы ответственны за создание и поддержку библиотеки номеров ID для всех новых объектов, которые используются в потоках В/В и должны сделать ID доступными для пользователей Ваших модулей. Как и константы команд, номера, назначаемые Вами могут быть абсолютно произвольными, главное, чтобы они были уникальными.
Нормальные кнопки и по умолчанию.
Когда Вы создаете кнопку, Вы устанавливаете ее флаг bfNormal или bfDefault. Большинство кнопок bfNormal. Кнопка, помеченная как bfDefault, будет кнопкой по умолчанию, т.е. она "нажимается", когда Вы нажимаете клавишу Enter. Turbo Vision не проверяет, используете ли Вы только одну кнопку по умолчанию - за это отвечаете Вы. Если Вы назначите более, чем одну кнопку по умолчанию, результат будет непредсказуемым. Обычно кнопка "OK" в диалоговом окне - это кнопка по умолчанию и пользователь просто нажимает Enter, чтобы закрыть диалоговое окно и использовать сделанные изменения.
Новые понятия.
Turbo Vision - это объединение видимых элементов, событий и невидимых объектов.
Новый взгляд на разработку программ.
Вы, вероятно, использовали библиотеки процедур и функций и ранее, а на первый взгляд Turbo Vision выглядит во многом как обычные библиотеки. Кроме того, библиотеки могут быть разработаны для поддержки меню, окон, мышки и т.д. Но под внешним сходством кроется существенное различие. Во-первых, не забывайте, что Вы сейчас работаете с объектами. В традиционном структурном программировании, когда инструмент, такой как монитор меню не полностью Вас удовлетворяет, Вы модифицируете исходный код инструмента, если он есть. Изменение исходного кода - это шаг, который труден для возврата, если Вы не фиксируете точно, как выглядел оригинальный код. Более того, измененный исходный код (особенно исходный код, написанный кем-либо другим) - это прекрасный путь внести новые ошибки в систему. С Turbo Vision Вы никогда не модифицируете исходный код. Вы "изменяете" Turbo Vision РАСШИРЯЯ его. TApplication остается неизменной внутри APP.TPU. Вы добавляете к нему, порождая новые типы объектов, и изменяете так, как Вам требуется, перекрывая унаследованные методы методами, которые Вы пишите для новых объектов. Кроме того, Turbo Vision - это иерархия, а не разрозненный набор инструментов. Если Вы используете любой из них, Вы должны использовать ВСЕ из них. Здесь дается представление каждого компонента Turbo Vision и как они работают вместе. Эти рекомендации лежат в основании принципов разработки на Turbo Vision: полностью используйте объектно-ориентированную технику и используйте все элементы Turbo Vision в Вашей программе. Это означает играть по "правилам" Turbo Vision и использовать его типы объектов. Мы создали Turbo Vision, чтобы уберечь Вас от большого количества ненужной повторяющейся работы и предоставить Вам оболочку прикладных программ.
Объект диалоговое окно.
Другим важным объектом, используемым в Hello, является диалоговое окно. Поскольку диалоговое окно не выполняет ничего специального, Hello использует экземпляр объекта TDialog. Не требуется порождать специального объекта из TDialog. Сам TDialog не содержит интерактивных элементов. Это ничего более, чем оболочка; Вы предоставляете поля или элементы управления, взаимодействующие с пользователем. THelloApp.GreetingBox строится на основе TDialog, вставляя 4 кнопки, которые являются видимыми элементами Turbo Vision. (Вспомним, что все элементы программы, которые выводят что-либо на экран, должны быть видимыми элементами Turbo Vision!) Это обычная ситуация при использовании диалоговых окон. Обычно Вы просто вставляете элементы управления, которые необходимы в диалоговом окне. Все остальное, что должно быть в диалоговом окне (включая обработчик событий) встроено в TDialog.
Объект TSample Модуль объекта
+---------+ | TObject | +----+----+ +====+====+ | TSample | +====+====+ +------+------+ | TDescendant | +-------------+
Поля
Этот раздел приводит список всех полей объекта. Кроме объявления поля и объяснения его использования приводится назначение "только чтение" и "чтение/запись". Поля "только на чтение" - это поля, которые устанавливаются и поддерживаются методами объектов и которые не должны использоваться в левой части оператора присваивания.
AField AField: SomeType; Только чтение AField - это поле, которое содержит некоторую информацию об этом объекте. Этот текст объясняет как оно функционирует, что это означает и как Вам его использовать. См. так же: Связанные поля, методы, объекты, глобальные функции и т.д.
AnotherField AnotherField: Word; Чтение/Запись Это поле содержит информацию подобную информации для поля AField.
Методы
Этот раздел приводит все методы, которые либо определены в этом объекте, либо перекрывают унаследованные методы. Для виртуальных методов указывается, как часто требуется перекрывать метод: никогда, редко, иногда, часто или всегда.
Init constructor Init(AParameter: SomeType); Init создает новый экземпляр объекта, устанавливая поле AField в АParameter.
Zilch procedure Zilch; virtual; Перекрывается: Иногда Процедура Zilch выполняет некоторые действия. См. так же TSomethingElse.Zilch
Объекты коллекции.
Поскольку коллекция - это объект и, следовательно, имеет методы, встроенные в него, она имеет 2 дополнительные возможности по сравнению с массивами Паскаля - динамический размер и полиморфизм.
Объекты скроллинга.
Объект TScroller это видимый объект для скроллинга, который действует как ворота в другой больший "фоновый" видимый элемент. Скроллинг возникает в ответ на ввод с клавиатуры или действия в связанных объектах TScrollBar. Скроллеры имеют два поля, HScrollId и VScrollId, идентифицирующих управление горизонтальной и вертикальной полосами скроллинга. Поле Delta в TScroller определяет смещение скроллинга по X и Y вместе с полями в связанных полосах скроллинга. Объекты TScrollBar обеспечивают вертикальное или горизонтальное управление. Ключевые поля: Value - позиция индикатора полосы скроллинга, PgStep - смещение скроллинга, требуемое в ответ на нажатие мышки или клавиш PgUp, PgDn; ArrStep - смещение скроллинга, требуемое в ответ на нажатие мышки или клавиш курсора. Скроллер и его полосы скроллинга обычно принадлежат объекту TWindow, что приводит к сложному набору обрабатываемых событий. Например, изменение размера окна должно приводить к соответствующей перерисовке скроллером. Значения полосы скроллинга должны так же изменяться и перерисовываться.
Объекты вообще.
Вспомним, что каждый объект (кроме базового объекта TObject и двух специальных объектов TPoint и TRect) наследует поля и методы родительского объекта. Порожденные Вами объекты будут так же наследовать поля и методы предка. Многие стандартные объекты имеют абстрактные методы, которые должны быть перекрыты в порожденном объекте. Другие методы виртуальные, что означает, что обычно Вам необходимо перекрыть их. Существуют так же методы, которые выполняют полезное действие, если они не были перекрыты.
Оболочка оконной программы.
Turbo Vision - это оболочка оконной программы, управляемой событиями. Здесь нет ни грамма мяса, только сильный гибкий скелет. Вы наращиваете мышцы на скелет, используя расширенные возможности объектно-ориентированного программирования Turbo Pascal. Turbo Vision предоставляет Вам прикладной объект TApplication и Вы создаете порожденный объект от TApplication - назовем его MyApplication, который действует как Ваше приложение. Затем Вы добавляете в MyApplication все, что Вам требуется для необходимой работы. На очень высоком уровне это все, что нужно сделать. Весь блок begin.end Вашей программы выглядит:
begin MyApplication.Init; { начальная установка } MyApplication.Run; { выполнение } MyApplication.Done; { закрытие } end;
Обработка nil указателей на объект.
Вы можете записать nil объект в поток. Однако, когда Вы делаете это, в поток записывается слово со значением 0. При чтении ID = 0, поток возвращает nil указатель, поэтому 0 зарезервирован и не может использоваться как ID номер объекта.
Обработка ошибок потока.
TStream имеет метод Error(Code, Info), который вызывается, когда поток обнаруживает ошибку. Error просто устанавливает поле Status в одну из констант, приведенную в разделе "Константы stXXXX" главы 14. Поле ErrorInfo за исключением ситуации, когда Status равен stGetError или stPutError, неопределено. Если Status - stGetError, поле ErrorInfo содержит номер ID незарегистрированного типа в потоке. Если Status - stPutError, поле ErrorInfo содержит смещение VMT для типа, который Вы пытаетесь поместить в поток. Вы можете перекрыть TStream.Error для создания любой обработки ошибок, включая ошибки времени выполнения.
Обработка событий.
После того, как Вы определили команду и установили элемент управления, который генерирует ее - например, элемент меню или кнопка диалового окна - Вам нужно научить Ваш видимый элемент, как реагировать, когда возникает эта команда. Каждый видимый элемент наследует метод HandleEvent, который уже знает, как реагировать на большую часть ввода пользователя. Если Вы хотите, чтобы видимый элемент делал что-то специфическое для Вашей программы, Вам необходимо перекрыть HandleEvent и научить новый HandleEvent двум вещам - как откликаться на определенные Вами команды и как откликаться на события от мышки и клавиатуры нужным Вам образом. Метод HandleEvent определяет поведение видимого элемента. Два видимых элемента с идентичными методами HandleEvent будут одинаково откликаться на события. Когда Вы порождаете новый тип видимого элемента, Вы обычно хотите, чтобы его поведение более или менее соответствовало его предку с некоторыми изменениями. Наиболее простой способ достичь этого - вызвать HandleEvent предка в методе HandleEvent нового объекта. Общий вид HandleEvent наследника:
procedure NewDescendant.HandleEvent(var Event: TEvent); begin {Код, изменяющий или ограничивающий унаследованное поведение} Parent.HandleEvent(Event); {Код, выполняющий дополнительные функции} end;
где Parent - тип предка. Другими словами, если Вы хотите, чтобы новый объект обрабатывал события не так, как это делал его предок, Вы должны перехватить определенные события до передачи события в метод HandleEvent предка. Если Вы хотите, чтобы Ваш новый объект вел себя также, как его предок, но с дополнительными функциями, Вы должны добавить код после вызова процедуры HandleEvent предка.
Общие события.
Общие события это обычно общие сообщения или пользовательские сообщения. Общие события не направляются как позиционированные или активные события. По определению обшие события не знают своего назначения и посылаются всем видимым подэлементам текущего модального видимого элемента. Текущий модальный видимый элемент получает событие и начинает передавать его подэлементам в Z-порядке. Если любой из этих пдэлементов - группа, он также передает событие своим подэлементам и также в Z-порядке. Процесс продолжается до тех пор пока все видимые элементы принадлежащие (прямо или косвенно) модальному видимому элементу не получат сообщения. Общие сообщения обычно используются для взаимодействия видимых элементов. Например, когда Вы отмечаете полосу скроллинга в просмотре файла, полоса скроллинга должна сказать видимому элементу просмотра, что он должен показать другую часть себя. Это значит что когда видимый элемент выдает общее сообщение "Я изменился!", другие видимые элементы, включая текст, будут получать сообщение и реагировать на него. Дополнительные детали смотри в разделе "Межэлементное взаимодействие". Примечание: Общие сообщения могут быть направлены объекту функцией Message.
Обзор видимых элементов.
Видимый элемент - это любой объект, который может быть нарисован (отображен) в прямоугольной части экрана. Тип видимого объекта должен наследоваться от TView. Сам TView - это абстрактный объект, представляющий пустую область экрана. Имея TView в качестве предка каждый порожденный видимый элемент имеет по крайней мере прямоугольную часть экрана и минимальный виртуальный метод Draw. При программировании в Turbo Vision Вы будете использовать более специализированные потомки от TView, но функциональность TView распространяется на весь Turbo Vision и Вам необходимо понимать его свойства.
Очистить бит.
Очистить бит так же просто, как и установить. Вы просто используете другую операцию. Лучший способ сделать это - использовать комбинацию двух побитовых операций and и not. Например, чтобы очистить бит dmLimitLoX в поле DragMode метки АLabel используйте
ALabel.DragMode := ALabel.DragMode and not dmLimitLoX;
Как и при установке Вы можете очистить несколько бит в одной операции.
Очистка событий.
Когда метод Handle видимого элемента обработал событие, он заканчивает этот процесс вызовом метода ClearEvent. ClearEvent устанавливает поле Event.What равным evNothing и Event.InfoPtr в @Self, что указывает на очищенное событие. Если это событие будет передано другому объекту, то он должен игнорировать "пустое" событие.
Одна из многих.
Давайте добавим набор зависимых кнопок в диалоговое окно, чтобы Вы могли сравнить их с независимыми кнопками. Следующий код устанавливает набор из 3 зависимых кнопок:
+--------------+ | [*] Solid | | [ ] Runny | | [ ] Melted | +--------------+
R.Assign( , , , ); B := New(PRadioButtons, Init(R, NewSItem('~S~olid', NewSItem('~R~unny', NewSItem('~M~elted', nil))) )); Insert(B);
Главное отличие между независимыми и зависимыми кнопками в том, что Вы можете выбрать только одну зависимую кнопку в группе и что первый элемент в списке зависимых кнопок выбран по умолчанию. Поскольку Вам не требуется знать состояние каждой зависимой кнопки (только одна может быть выбрана, так, что Вам требуется знать только какая именно), данные о зависимых кнопках не побитовые. Это означает, что Вы можете использовать более 16 зависимых кнопок, но поскольку данные хранятся в слове, Вы ограничены 65,536 зависимыми кнопками на один кластер. Значение 0 указывает, что выбрана первая зависимая кнопка, 1 - вторая и т.д.
Окна.
Объекты TWindow, с помощью ассоциированных объектов TFrame - это прямоугольники с рамкой, которую Вы можете перемещать, изменять ее размеры и удалять, используя методы, унаследованные от TView. Поле Frame указывает на объект TFrame этого окна. Объект ТWindow так же может изменять размер и закрываться, используя свои методы. TWindow обрабатывает клавиши Tab и Shift-Tab для выбора следующего или предыдущего видимого подэлемента в окне. Обработчик событий TWindow обрабатывает команды закрытия и изменения размера. Пронумерованные окна могут быть выбраны горячими клавишами Alt-n.
Окно списка.
TListBox наследуется от TListViewer. Он владеет TCollection, который должен быть указателями на строки. TListBox поддерживает только одну полосу скроллинга. Пример окна списка - список выбора файлов в интегрированной среде Turbo Pascal или список файлов, используемый TFileDialog в STDDLG.PAS. При получении или установке данных окна списка удобно использовать тип записи TListBoxRec, который хранит указатель на список строк и слово, указывающее на текущий выбранный элемент списка.
Опять итераторы.
Метод ForEach проходит по всей коллекции и передает каждый элемент в предоставленную Вами процедуру. Продолжая предыдущий пример, процедура PrintWord получает указатель на отображаемую строку. Заметьте, что PrintWord вложенная (или локальная) процедура. Print использует метод ForEach для передачи каждого элемента коллекции в процедуру PrintWord.
procedure Print(C: PCollection);
procedure PrintWord(P : PString); far; begin Writeln(P^); end;
begin { Print } Writeln; Writeln; C^.ForEach(@PrintWord); end;
Вызов PrintWord выглядит привычно. Это просто процедура, которая берет указатель на строку и передает его значение в Writeln. Заметим директиву far в объявлении PrintWord. PrintWord не может быть методом - она должна быть процедурой. (Процедура CallDraw в TVGUID20.PAS показывает как вызвать метод в вызове итератора). Она так же должна быть вложенной процедурой. Вы можете использовать более одной процедуры, такой как PrintWord, но каждая должна быть вложена в Print и должна быть дальней процедурой.
Определение команд.
Turbo Vision имеет ряд предопределенных команд и Вы можете определить еще больше своих. Когда Вы создаете новый видимый элемент, Вы также создаете команду, которая используется для вызова этого видимого элемента. Команды могут быть названы произвольно, но по соглашениям Turbo Vision идентификатор команды должен начинаться с "cm". Механизм создания команд прост - Вы только создаете константу:
const cmConfuseTheCat = 100;
Turbo Vision резервирует команды от 0 до 99 и от 256 до 999 для собственного использования. Ваша программа может использовать под команды номера от 100 до 255 и от 1000 до 65535. Причина того что Вы имеете два диапазона для команд только в том что команды от 0 до 255 могут быть запрещены. Turbo Vision резервирует некоторые команды, которые могут быть запрещены и некоторые команды которые не могут быть запрещены для своих стандартных команд и внутренней работы. Вы имеете полный контроль над оставшимися командами.
Таблица 5.1. Диапазоны команд Turbo Vision.
------------------------------------------------ Диапазон Зарезервировано Может быть запрещено ------------------------------------------------ 099 Да Да 100255 Нет Да 256999 Да Нет 100065535 Нет Нет ------------------------------------------------
Основные потребители.
Функция Valid так же может обрабатывать "основных потребителей", т.е. видимые элементы, которые распределяют память больше, чем размер пула надежности, как например при чтении всего файла в память. Основные потребители должны проверять LowMemory сами вместо того, чтобы ожидать когда они закончат все создание, а после этого позволят ValidView сделать это за них. Если основной потребитель доходит до нехватки памяти в процессе своего создания, он устанавливает свой флаг, который указывает, что встретилась ошибка (как например флаг ErrorEncountered в предыдущем примере) и больше не пытается распределить память. Этот флаг будет проверяться в Valid и видимый элемент будет вызывать Application^.OutOfMemory и возвращать False из вызова Valid. Очевидно, что делать предположение о работе Ваших констракторов - это не лучший вариант, но это единственный способ управлять создание видимых элементов, которые превышают размер пула надежности. Программа FILEVIEW.PAS демонстрирует использование этой техники для реализации надежного просмотра файла.
Открытие окон.
Используемые объекты: TRect, TView, TWindow, TGroup, TScroller, TScrollBar. Если Вы программист, Вы можете сразу перейти на этот раздел, как только Вы откроете книгу. Кроме того, что может быть более важно для написания оконных программ, чем создание окон? Это было бы так, если бы Turbo Vision была набором традиционных библиотечных программ. В этом случае переход на этот раздел и попытка начать работать была бы хорошей идеей. Но Turbo Vision - не традиционная библиотека. Если Вы читали предыдущие разделы, Вы уже знаете об этом. Для того, чтобы программировать в Turbo Vision необходимо выполнить некоторые действия до того, как создавать окна. Вам необходимо понимать, что такое окно Turbo Vision (а это объект!) и чем оно отличается от окон, которые Вы использовали раньше. Когда Вы сделаете это, Вы продвинитесь вперед гораздо дальше, чем Вы можете вообразить. Поэтому, если Вы открыли книгу в этом месте, Вам необходимо вернуться к предыдущим разделам и прочитать их.
Откуда приходят события.
Как сказано в главе 1, главный цикл обработки в TApplication, метод Run вызывает TGroup.Execute, которая основана на цикле:
var E: TEvent; E.What := evNothing; { указывает что нет событий } repeat if E.What <> evNothing then EventError(E); GetEvent(E); { упаковывает запись события } HandleEvent(E); { направляет событие в нужное место } until EndState <> Continue;
По существу GetEvent смотрит вокруг и проверяет, не случилось ли что либо, что должно быть событием. Если случилось, GetEvent создает соответствующую запись события. Затем HandleEvent направляет событие в соответствующие видимые элементы. Если событие не обработано (и не очищено) за время пока оно не вернется в этот цикл, то вызывается EventError, чтобы указать на ненужное событие. По умолчанию EventError ничего не делает.
Отладка программ на Turbo Vision.
Если Вы попытаетесь трассировать какой-нибудь из примеров этого руководства, Вы, вероятно, заметите, что Вы не можете зайти очень далеко. Поскольку программы на Turbo Vision управляются событиями, большая часть программного времени тратится на цикл в TGroup.Execute ожидая когда произойдет какое-либо событие. В результате трассировка этой точки имеет мало смысла.
Примечание: Ключем к отладке программ на Turbo Vision являются точки прерывания и только точки прерывания.
Давайте посмотрим как лучше разместить точки прерывания, чтобы обнаружить проблемы в программе на Turbo Vision.
Отсортированные коллекции.
TSortedCollection реализует коллекцию, отсортированную по ключу. Сортировка определена через виртуальный абстрактный метод Compare. Следовательно Ваш порожденный тип может задавать требуемую упорядоченность для коллекции объектов любого типа. Метод Insert добавляет элементы, поддерживая это упорядочение и ключи могут быть быстро найдены методом двоичного поиска Search.
Иногда Вам необходимо иметь Ваши данные в определенном порядке. Turbo Vision обеспечивает специальный тип коллекции, который позволяет Вам упорядочить Ваши данные любым способом: TSortedCollection. TSortedCollection порожден от TCollection и автоматически сортирует получаемые объекты. Он так же автоматически проверяет коллекцию, когда добавляется новый элемент и отвергает дублированные элементы. TSortedCollection - это абстрактный тип. Чтобы использовать его, Вы должны вначале решить, какой тип данных Вы будете помещать в коллекцию и определить 2 метода, соответствующие способу сортировки. Чтобы сделать это, Вам нужно породить новый тип коллекции от TSortedCollection. В нашем случае назовем его TClientCollection. Ваш TClientCollection уже знает как делать всю работу над коллекцией. Он может вставить новые записи клиентов и удалить существующие, поскольку наследует все основы поведения от TCollection. Вам необходимо только научить TClientCollection, какое поле использовать как ключ сортировки и как сравнивать двух клиентов и определять, какой из них находится перед другим в коллекции. Вы делаете это, перекрывая методы KeyOf и Compare и реализуя их как показано здесь:
PClientCollection = ^TClientCollection; TClientCollection = object(TSortedCollection) function KeyOf(Item: Pointer): Pointer; virtual; function Compare(Key1, Key2: Pointer): Integer; virtual; end;
function TClientCollection.KeyOf(Item: Pointer): Pointer; begin KeyOf := PClient(Item)^.Name; end;
function TClientCollection.Compare(Key1, Key2: Pointer): Integer; begin {необходимо использовать приведение типа для ключей, поскольку они - нетипированные указатели } if PString(Key1)^ = PString(Key2)^ then Compare := 0 else if PString(Key1)^ < PString(Key2)^ then Compare := -1 else Compare := 1; end;
KeyOf определяет, какое поля или поля должны использоваться как ключ сортировки. В нашем случае - это поле Name клиента. Compare берет 2 ключа сортировки и определяет какой из них должен стоять первым. Compare возвращает -1, 0 или 1 взависимости от того, является ли Key1 меньше, равным или больше Key2. Этот пример использует алфавитную сортировку строк ключей. Заметим, что поскольку ключи, возвращаемые KeyOf и передаваемые Compare - нетипированные указатели, Вам необходимо выполнить приведение типа в PString до ссылки на них. Это все, что Вы должны определить! Сейчас, если Вы переопределите ClientList как PClientCollection вместо PCollection (изменив объявление var и вызов New), Вы распечатаете Ваших клиентов в алфавитном порядке.
{ TVGUID18.PAS } var ClientList: PClientCollection; . begin ClientList := New(PClientCollection, Init(50, 10)); . end;
Заметьте как просто сделать распечатку списка клиентов, отсортированного по номерам, а не по имени. Вам необходимо просто изменить метод KeyOf на возврат поля ACount вместо поля Name.
Ответ: потоки.
Turbo Vision позволяет Вам обойти обе трудности, а так же предоставляет некоторые дополнительные возможности. Потоки предоставляют простой, чрезвычайно элегантный способ хранения данных объекта вне программы.
Палитры цветов.
Когда видимый элемент в Turbo Vision рисует себя, он запрашивает прорисовку не определенным цветом, а цветом, заданным позицией в его палитре (палитры для всех стандартных видимых элементов описаны в главе 13). Например, палитра TScroller имеет вид:
CScroller = #6#7;
Палитра цветов в действительности хранится в строке, что позволяет определять ее в качестве гибких массивов с переменной длиной. Так, CScroller - это двухсимвольная строка, содержащая 2 элемента палитры. Палитра TScroller определена:
{ Палитра } { 1 = Нормальный } { 2 = Подсвеченный }
Но удобнее рассмотреть ее в виде:
Рис. 4.18. Палитра по умолчанию для TScroller.
1 2 +---+---+ CScroller | 6 | 7 | +---+---+ | | | +--------- Подсвеченный текст +------------- Нормальный текст
Это означает, что известно как отображать по крайней мере 2 типа текста объекта скроллер: нормальный и подсвеченный. Цвет по умолчанию определяется элементами палитры. Когда отображается нормальный текст, метод Draw должен вызвать GetColor(1) означающий, что он хочет выбрать цвет, указанный первым элементом палитры. Чтобы показать подсвеченный текст, будет вызываться GetColor(2). (GetColor - это метод TView). Если Вы хотите отображать цветами по умолчанию, это все, что Вам необходимо знать. Палитра устанавливается так, что любая комбинация объектов должна создавать хорошие цвета.
Панель экрана.
Панель экрана - это исключительно важный объект, но он требует от Вас очень небольших действий. Вы не должны перекрывать унаследованный метод инициализации. Пусть TApplication.InitDeskTop обрабатывает его. DeskTop принадлежит MyApp и когда MyApp устанавливает новый видимый элемент в ответ на ввод пользователя, она должна подключить новый элемент пользователя к DeskTop. Панель экрана знает как управлять видимыми элемента.
TDeskTop - это нормальный фоновый видимый элемент, обеспечивающий привычную панель экрана пользователям, обычно окруженную полосой меню и строкой статуса. Обычно TApplication владелец группы, содержащей объекты TDeskTop, TMenuBar и TStatusLine. Другие видимые элементы, такие как окна и диалоговые окна, создаются, отображаются и манипулируются на панели экрана в ответ на действия пользователя (события от мышки и клавиатуры). Большая часть работы программы происходит внутри панели экрана.
Панель экрана, полоса меню и строка статуса.
Используемые объекты: TView, TMenuView, TMenuBar, TMenuBox, TStatusLine, TGroup, TDeskTop. Панель экрана, полоса меню и строка статуса в TFirst создаются методами InitDeskTop, InitMenuBar и InitStatusLine из TApplication. Эти 3 метода вызываются в TApplication.Init и Вам никогда не нужно вызывать их напрямую. Вместо этого метод Init Вашей программы будет вызывать TApplication.Init в первой строке. Например
procedure TMyApp.Init; begin TApplication.Init; { код инициализации для Вашей программы } end;
Заметим, что Вам необходимо добавить некоторые модули Turbo Vision в оператор uses Вашей программы. Для того, чтобы использовать меню, строку статуса и определения стандартных клавиш, Вам необходимо кроме App использовать Objects, Menus и Drivers. (Объекты и их модули описаны в главе 12.) Если Ваша программа не требует какой-либо специальной инициализации, Вы просто используете унаследованный метод Init. Поскольку Init и методы InitDeskTop, InitMenuBar и InitStatusLine виртуальные, вызов унаследованного Init вызывает соответствующие методы InitStatusLine и InitMenuBar. Вы увидите это в TVGUID02.PAS. InitDeskTop, InitMenuBar и InitStatusLine устанавливают зхначения глобальных переменных DeskTop, MenuBar и StatusLine соответственно. Давайте посмотрим каждую из них.
Передача событий.
Видимые элементы Turbo Vision работают по принципу "Говори только когда к тебе обратятся". Это не похоже на активный поиск ввода, они скорее пассивно ожидают, когда монитор событий скажет им, что произошло событие, на которое требуется отклик. Для того чтобы Ваша программа на Turbo Vision делала то что Вы хотите, Вы должны не только сказать видимым элементам, что делать, когда случается определенное событие, но и должны понимать как события передаются в Ваши видимые элементы. Главное в получении событий в нужном месте - это правильная маршрутиризация событий. Некоторые события передаются всем элементам программы, другие направляются точно в определенные части программы.
Перекрытие цветов по умолчанию.
Очевидный способ изменить цвета - это изменить палитру. Если Вам не нравится цвет нормального текста скроллера, Вы можете захотеть изменить элемент 1 (нормальный текст) в палитре скроллера, например с 6 на 5. Нормальный текст скроллера отображается в элемент окна для элемента управления полосы скроллера (по умолчанию синий-на-бирюзовом). Запомните: 5 - это не цвет! Все, что Вы сделали - это сказали скроллеру, что его нормальный текст должен выглядеть так же, как полосы скроллинга вокруг него! Что делать, если Вы не хотите желтый-на-синем? Измените элемент палитры для нормального текста окна в TApplication. Поскольку это последняя не nil палитра, элементы в палитре программы определяют цвета, которые будут появляться во всех видимых элементах окна, т.е. цвета не являются абсолютными, а определяются палитрами владельца. Это имеет смысл: вероятно Вы хотите, чтобы Ваши окна выглядели одинаково. Вероятно Вы не захотите указывать каждому отдельному окну какого цвета оно должно быть. Если Вы захотите изменить его позже (или разрешить пользователю настраивать цвета), Вам придется изменить элементы для каждого окна. Так же скроллер или другой интерьер не должен беспокоиться о его цветах, если он вставляется в какое-то окно, отличное от того, в какое Вы хотели вставить его первоначально. Например, если Вы поместили скроллер в диалоговое окно вместо окна, он не будет (по умолчанию) того же цвета, а вместо этого будет цвета нормального текста в диалоговом окне. Чтобы изменить палитру видимого элемента, перекройте метод GetPalette. Чтобы создать новый тип объекта скроллера, который рисует себя цветом рамки окна вместо цвета нормального текста, объявление и реализация объекта будут включать:
type TMyScroller = object(TScroller) function GetPalette: PPalette; virtual; end;
function TMyScroller.GetPalette: PPalette; const CMyScroller = #1#7; PMyScroller: string[Length(CMyScroller)] = CMyScroller; begin GetPalette := @PMyScroller; end;
Заметим, что константа палитры - это строковая константа, поскольку Turbo Vision использует тип String для представления палитры. Это позволяет более просто манипулировать палитрой, поскольку все строковые функции могут использоваться с палитрами.
Примечание: Типы TPalette и String полностью взаимозаменяемы.
Перекрытие GetEvent.
GetEvent текущего модального видимого элемента вызывает GetEvent владельца и так далее проходя весь путь по дереву видимых элементов до TApplication.GetEvent, который ищет следующее реальное событие. Поскольку Turbo Vision всегда использует TApplication.GetEvent для поиска событий, Вы можете модифицировать события всей Вашей программы, перекрывая только один метод. Например, для реализации клавиатурных макро Вы можете просматривать события, возвращаемые GetEvent, перехватывать определенные нажатия клавиш и развертывать их в макро. С точки зрения остальной программы поток событий будет приходить прямо от пользователя.
procedure TMyApp.GetEvent(var Event: TEvent); begin TApplication.GetEvent(Event); end;