Я:
Результат
Архив

МЕТА - Украина. Рейтинг сайтов Webalta Уровень доверия



Союз образовательных сайтов
Главная / Учебники / Учебники на русском языке / Компьютерные науки / Borland Pascal 7.0 & Objects - Руководство по ObjectWindows


Компьютерные науки - Учебники на русском языке - Скачать бесплатно


Автор неизвестен
Borland Pascal 7.0 & Objects - Руководство по ObjectWindows
------------------------------------------------------------------------
B.Pascal 7 & Objects/OW - 1 -

Введение.......................................................25
Что такое ObjectWindows?.......................................25
Для чего предназначена ObjectWindows?..........................26
Что нужно знать................................................26
Как работать с данным руководством.............................27
О чем рассказывается в данном руководстве......................27
Часть 1. Изучение ObjectWindows................................28
Глава 1. Знакомство с Windows..................................28
Шаг 1: Создание базового приложения............................28
Требования к приложению........................................29
Определение типа приложения....................................30
Инициализация основного окна...................................30
Объект основного окна..........................................32
Что такое объект окна?.........................................32
Описатели......................................................33
Порождающие и дочерние окна....................................33
Создание нового типа окна......................................33
Реакция на сообщения...........................................34
Завершение прикладной программы................................36
Переопределение CanClose.......................................37
Дальнейшее изменение закрытия..................................38
Глава 2. Заполнение окна.......................................41
Шаг 2: Отображение текста в окне...............................41
Вывод в контексте дисплея......................................41
Что такое контекст дисплея?....................................42
Получение контекста дисплея....................................42
Использование контекста дисплея................................43
Освобождение контекста дисплея.................................43
Координаты Windows.............................................44
Параметры сообщений............................................44
Очистка окна...................................................45
Шаг 3: Изображение линий в окне................................47
Буксировка линии...............................................48
Сообщения wm_MouseMove.........................................48
Реакция на сообщения буксировки................................49
Изображение точек и линий......................................50
Перехват "мыши"................................................50
Изменение размера пера.........................................51
Отслеживание размера пера......................................51
Получение пера нового размера..................................52
Глава 3. Меню и диалоговые ресурсы.............................56
Шаг 4: Добавление строки меню..................................56
Ресурсы меню...................................................57
Загрузка ресурса меню..........................................60
Перехват сообщений меню........................................61
Определение методов реакции на команду.........................62
Связывание клавиш с командами..................................62
Реакция на команды меню........................................63
Добавление диалогового блока...................................64
Добавление поля объекта........................................66
Шаг 5: Добавление диалогового блока............................68
Создание ресурсов диалогового блока............................69
Идентификаторы управляющих элементов...........................69

B.Pascal 7 & Objects/OW - 2 -

Построение объекта диалогового блока...........................70
Выполнение диалогового блока...................................70
Режимные и безрежимные диалоговые блоки........................72
Глава 4. Работа с диалоговым блоком............................73
Шаг 6: Изменение атрибутов пера................................73
Создание объекта пера..........................................74
Создание сложного диалогового блока............................76
Управляющие объекты............................................77
Использование интерфейсных объектов............................78
Конструктор InitResource.......................................79
Создание буфера передачи.......................................79
Передача данных................................................81
Чтение возвращаемых значений...................................81
Вызов диалогового блока пера...................................82
Глава 5. Повторное отображение графики.........................83
Шаг 7: Вывод на экран графики..................................83
Изображение и рисование........................................83
Сохранение графики в объектах..................................84
Добавление поля объекта........................................85
Определение объекта линии......................................85
Изменение методов работы с "мышью".............................87
Вывод сохраненной графики......................................88
Шаг 8: Сохранение рисунка в файле..............................89
Отслеживание состояния.........................................89
Сохранение и загрузка файлов...................................91
Шаг 9: Печать графического образа..............................94
Построение объекта принтера....................................94
Создание объекта распечатки....................................95
Запись в контекст устройства...................................95
Создание распечатки окна.......................................95
Вывод распечатки...............................................96
Выбор другого принтера.........................................96
Глава 6. Вывод всплывающего окна...............................98
Шаг 10: Добавление всплывающего окна...........................98
Добавление к окну дочернего окна...............................99
Построение окна палитры.......................................100
Назначение порождающего окна..................................100
Создание элементов экрана.....................................102
Вывод и сокрытие палитры......................................103
Шаг 11: добавление специализированных управляющих элементов...103
Добавление к палитре командных кнопок.........................104
Объекты управляющих элементов как поля........................105
Работа с управляющими элементами..............................105
Сокрытие вместо закрытия......................................106
Разрешение специализированных управляющих элементов...........107
Создание для командных кнопок графических изображений.........109
Нумерация ресурсов графических изображений....................109
Шаг 12: Создание специализированного управляющего элемента
окна.........................................................111
Динамическое изменение размеров палитры.......................111
Реакция на события управляющих элементов......................112
Имена методов реакции на сообщения управляющих элементов......112
Добавление "кнопок" палитры...................................114

B.Pascal 7 & Objects/OW - 3 -

Определение объекта палитры...................................114
Создание и уничтожение палитры................................116
Размещение в порождающем окне.................................117
Добавление и удаление перьев..................................118
Отображение содержимого палитры...............................120
Выбор перьев с помощью "мыши".................................121
Что дальше?...................................................121
Многодокументальный интерфейс.................................122
Сглаживание линий.............................................122
Отмена........................................................122
Поведение палитры.............................................123
Прокрутка.....................................................123
Часть 2. Использование ObjectWindows..........................124
Глава 7. Иерархия ObjectWindows...............................124
Соглашения Windows............................................124
Имена объектов................................................124
Имена методов.................................................124
Обзор объектов................................................125
Иерархия объектов.............................................125
Файлы ObjectWindows...........................................130
Файлы ресурсов................................................131
Файлы Windows 3.1.............................................131
Взаимодействие с Windows......................................132
Функции API Windows...........................................132
Вызов в ObjectWindows функций API.............................132
Доступ к функциям API.........................................133
Константы Windows.............................................133
Записи данных Windows.........................................133
Комбинирование констант стилей................................134
Типы функций Windows..........................................134
Функции системного вызова.....................................135
Глава 8. Объекты приложения...................................136
Минимальные требования........................................136
Поиск объекта приложения......................................136
Минимальное приложение........................................137
Методы Init, Run и Done.......................................137
Конструктор Init..............................................137
Метод Run.....................................................138
Деструктор Done...............................................138
Инициализация приложения......................................138
Инициализация основного окна..................................139
Специальный вывод основного окна..............................140
Инициализация первого экземпляра..............................140
Инициализация каждого экземпляра..............................142
Выполнение приложений.........................................143
Закрытие приложений...........................................143
Модификация поведения при закрытии............................143
Глава 9. Интерфейсные объекты.................................145
Для чего нужны интерфейсные объекты?..........................145
Что делают интерфейсные объекты?..............................145
Общий интерфейсный объект.....................................146
Создание интерфейсных объектов................................146
Допустимость описателя окна...................................147

B.Pascal 7 & Objects/OW - 4 -

Видимость на экране...........................................148
Уничтожение интерфейсных объектов.............................148
Связь порождающего и дочернего объектов.......................149
Список дочерних окон..........................................149
Построение дочерних окон......................................150
Создание дочерних элементов экрана............................150
Уничтожение дочерних окон.....................................150
Запрещение автоматического создания...........................151
Итерация дочерних окон........................................151
Поиск определенного дочернего окна............................151
Глава 10. Объекты окон........................................153
Что такое объекты окон?.......................................153
Окна, которые не являются окнами..............................153
Где найти объекты окон........................................154
Инициализация объектов окон...................................154
Установка атрибутов создания..................................155
Используемые по умолчанию атрибуты окна.......................156
Переопределение используемых по умолчанию атрибутов...........157
Атрибуты порожденного окна....................................157
Создание элементов окна.......................................158
Задание атрибутов регистрации.................................159
Классы окон...................................................160
Используемые по умолчанию атрибуты регистрации................162
Регистрация нового класса.....................................162
Изменение имени класса........................................163
Определение новых атрибутов регистрации.......................163
Использование специализированных окон.........................165
Использование окон редактирования.............................165
Использование файловых окон...................................167
Прокрутка содержимого окон....................................168
Что такое объект прокрутки?...................................169
Задание для окна объекта прокрутки............................171
Пример прокрутки..............................................171
Запрещение автоматической прокрутки...........................173
Отслеживание полос прокрутки..................................173
Модификация единиц прокрутки и диапазона......................174
Изменение позиции прокрутки...................................174
Установка размеров страницы...................................175
Оптимизация методов Paint для прокрутки.......................175
Глава 11. Объекты диалоговых блоков...........................177
Использование объектов диалоговых блоков......................177
Построение объекта............................................178
Вызов конструктора............................................178
Выполнение диалоговых блоков..................................178
Режимные и безрежимные диалоговые блоки.......................179
Выполнения режимных диалоговых блоков.........................179
Выполнение безрежимных диалоговых блоков......................180
Работа с безрежимными диалоговыми блоками.....................180
Завершение диалогов...........................................181
Работа с управляющими элементами..............................182
Взаимодействие с управляющим элементом........................182
Реакция на сообщения управляющих элементов....................183
Пример связи..................................................183

B.Pascal 7 & Objects/OW - 5 -

Ассоциирование объектов управляющих элементов.................184
Использование диалоговых окон.................................185
Использование предопределенных диалоговых окон................186
Использование диалоговых блоков ввода.........................186
Файловые диалоговые блоки.....................................188
Инициализация файлового диалогового блока.....................189
Выполнение файловых диалоговых блоков.........................189
Глава 12. Объекты управляющих элементов.......................191
Где можно использовать объекты управляющих элементов?.........191
Что такое объекты управляющих элементов?......................194
Построение и уничтожение объектов управляющих элементов.......194
Построение объекта управляющего элемента......................195
Вызов конструкторов объектов управляющих элементов............195
Присваивание полям объекта....................................195
Изменение атрибутов объекта управляющего элемента.............197
Инициализация управляющего элемента...........................197
Сохранение управляющих элементов..............................198
Уничтожение управляющих элементов.............................198
Связь с управляющими элементами...............................198
Работа с управляющими элементами окна.........................198
Реакция на управляющие элементы...............................199
Действие, аналогичное диалоговому блоку.......................199
Использование конкретных управляющих элементов................199
Использование блока списка....................................199
Построение объектов блока списка..............................200
Модификация блоков списка.....................................200
Запрос в блоках списка........................................201
Реакция на блок списка........................................201
Пример программы: LBoxTest....................................202
Использование статических управляющих элементов...............203
Построение статических управляющих элементов..................204
Пример программы StatTest.....................................205
Использование командных кнопок................................206
Построение командных кнопок...................................207
Реакция на командные кнопки...................................207
Использование блоков выбора...................................208
Построение кнопок с зависимой и независимой фиксацией.........208
Модификация блоков выбора.....................................210
Опрос блоков выбора...........................................210
Использование групповых блоков................................210
Построение групповых блоков...................................211
Группирование управляющих элементов...........................211
Реакция на групповые блоки....................................213
Пример программы: BtnTest.....................................213
Использование полос прокрутки.................................214
Построение полос прокрутки....................................214
Управление диапазоном полосы прокрутки........................215
Управление параметрами полосы прокрутки.......................216
Опрос полосы прокрутки........................................216
Модификация полос прокрутки...................................216
Реакция на полосы прокрутки...................................217
Пример программы: SBarTest....................................218
Использование управляющих элементов редактирования............218

B.Pascal 7 & Objects/OW - 6 -

Построение управляющих элементов редактирования...............220
Использование буфера вырезанного изображения и меню Edit......220
Опрос управляющих элементов редактирования....................222
Модификация управляющих элементов редактирования..............223
Пример программы: EditTest....................................224
Использование комбинированных блоков..........................224
Три типа комбинированных блоков...............................225
Выбор типа комбинированного блока.............................226
Построение комбинированных блоков.............................226
Модификация комбинированных блоков............................227
Пример программы: CBoxTest....................................227
Установка значений управляющих элементов......................227
Для чего используется буфер передачи?.........................228
Определение буфера передачи...................................228
Определение окна..............................................231
Использование буфера передачи с диалоговым блоком.............231
Использование буфера передачи с окном.........................233
Передача данных...............................................233
Передача данных в окно........................................233
Передача данных из диалогового окна...........................233
Передача данных из окна.......................................234
Поддержка передачи для специализированных управляющих
элементов....................................................234
Пример программы: TranTest....................................234
Использование специализированных управляющих элементов........236
Специализированные управляющие элементы Borland для Windows...236
Использование стандартных BWCC................................237
Средства BWCC.................................................237
Расширение BWCC...............................................238
Создание ваших собственных специализированных управляющих
элементов....................................................240
Глава 13. Проверка допустимости данных........................241
Три вида проверки допустимости данных.........................241
Фильтрация ввода..............................................242
Проверка допустимости каждого поля............................242
Проверка допустимости полных экранов..........................242
Использование механизма проверки допустимости данных..........243
Построение объектов проверки допустимости.....................244
Добавление к управляющим элементам............................244
Как работает проверка допустимости............................244
Методы объекта проверки допустимости..........................245
Проверка допустимости данных..................................245
Проверка полной строки........................................246
Проверка допустимости нажатий клавиш..........................246
Сообщение о недопустимых данных...............................246
Стандартные средства проверки допустимости....................248
Абстрактный объект проверки допустимости......................248
Фильтрация....................................................248
Проверка диапазона............................................249
Проверка допустимости с просмотром............................249
Просмотр строк................................................249
Проверка допустимости по шаблону..............................250
Глава 14. Объекты MDI.........................................251

B.Pascal 7 & Objects/OW - 7 -

Меню дочернего окна...........................................252
Дочерние окна MDI.............................................252
Окна MDI в ObjectWindows......................................252
Построение приложения MDI.....................................252
Построение рамки MDI..........................................253
Создание меню дочерних окон...................................253
Создание дочерних окон MDI....................................254
Автоматические дочерние окна..................................254
Управление дочерним окном MDI.................................255
Настройка активизации дочернего окна..........................256
Обработка сообщений в приложении MDI..........................256
Пример приложения MDI.........................................256
Глава 15. Объекты печати......................................257
Почему печать представляет трудности?.........................257
Печать в ObjectWindows........................................257
Построение объекта принтера...................................258
Создание распечатки...........................................259
Печать документа..............................................259
Задание параметров печати.....................................260
Подсчет страниц...............................................260
Печать каждой страницы........................................261
Указание оставшихся страниц...................................263
Другие соглашения по печати...................................263
Печать содержимое окна........................................264
Вывод распечатки на принтер...................................265
Выбор другого принтера........................................265
Выбор принтера пользователем..................................266
Назначение конкретного принтера...............................266
Часть 3. Продвинутое программирование с использование
ObjectWindows................................................267
Глава 16. Сообщения Windows...................................267
Что такое сообщение?..........................................267
Именующие сообщения...........................................268
Откуда поступают сообщения....................................268
Обычная диспетчеризация сообщений.............................269
Способ, предлагаемый ObjectWindows............................269
Динамические виртуальные методы...............................270
Написание методов реакции на сообщение........................270
Что такое сообщение?..........................................271
Поля параметров...............................................271
Поле Result...................................................272
Объектно-ориентированная обработка сообщения..................272
Отмена поведения по умолчанию.................................272
Замена поведения по умолчанию.................................273
Дополнение поведения по умолчанию.............................273
Вызов наследуемых методов.....................................273
Вызов процедур, используемых по умолчанию.....................274
Командные, уведомляющие и управляющие идентификаторы..........275
Командные сообщения...........................................275
Уведомляющие сообщения........................................276
Уведомления управляющих элементов.............................276
Уведомление порождающего объекта..............................277
Уведомления управляющих элементов и порождающих объектов......278

B.Pascal 7 & Objects/OW - 8 -

Определение ваших собственных сообщений.......................278
Передача сообщений............................................279
Передача и отправление сообщений..............................279
Передача сообщения............................................280
Отправление сообщения.........................................280
Передача сообщения управляющему элементу......................280
Диапазоны сообщений...........................................282
Глава 17. Интерфейс с графическими устройствами...............284
Запись на устройство вывода...................................284
Чем отличаются контексты устройства?..........................285
Управление контекстом дисплея.................................285
Работа с контекстом дисплея...................................286
Что содержится в контексте устройства?........................286
Побитовая графика.............................................287
Изобразительные средства......................................287
Цвет..........................................................289
Режимы отображения............................................289
Обрезание областей............................................289
Инструментальные средства рисования...........................290
Основные инструментальные средства............................290
Логические инструментальные средства..........................291
Логические перья..............................................291
Логические кисти..............................................293
Логические шрифты.............................................294
Использование изобразительных инструментальных средств........298
Отображение графики в окнах...................................300
Изображение окон..............................................300
Стратегия графики.............................................301
Рисование в окнах.............................................301
Графические функции GDI.......................................302
Функции изображения текста....................................302
Функции рисования линий.......................................303
Изображение фигур.............................................305
Использование палитр..........................................307
Установка палитры.............................................307
Рисование с палитрами.........................................308
Запрос палитры................................................308
Модификация палитры...........................................309
Реакция на изменения палитры..................................309
Глава 18. Более подробно о ресурсах...........................311
Создание ресурсов.............................................311
Добавление ресурсов к выполняемой программе...................312
Загрузка ресурсов в приложение................................312
Загрузка меню.................................................312
Загрузка оперативных клавиш...................................313
Загрузка блоков диалога.......................................314
Загрузка курсоров и пиктограмм................................315
Загрузка строковых ресурсов...................................315
Загрузка графических изображений..............................317
Использование побитовых отображений для создания кистей.......319
Отображение графических изображений в меню....................320
Глава 19. Наборы..............................................322
Объекты наборов...............................................322

B.Pascal 7 & Objects/OW - 9 -

Динамическая установка размеров наборов.......................322
Полиморфизм наборов...........................................323
Проверка типа и наборы........................................323
Объединение в набор элементов, не являющихся объектами........324
Создание набора...............................................324
Методы итератора..............................................326
Итератор ForEach..............................................326
Итераторы FirstThat и LastThat................................327
Отсортированные наборы........................................328
Наборы строк..................................................329
Пересмотренные итераторы......................................331
Полиморфические наборы........................................331
Наборы и управление памятью...................................335
Глава 20. Потоки..............................................336
Вопрос: объектный ввод-вывод..................................336
Ответ: потоки.................................................337
Полиморфизм потоков...........................................337
Потоки обрабатывают объекты...................................337
Смысл использования потоков...................................338
Чтение из потока и запись в поток.............................339
Закрытие потока...............................................340
Как сделать объекты потоковыми................................340
Методы загрузки и хранения....................................340
Регистрация потока............................................341
Номера идентификаторов объектов...............................342
Автоматические поля...........................................342
Регистрация на месте..........................................343
Регистрация стандартных объектов..............................343
Механизм потока...............................................343
Процесс Put...................................................343
Процесс Get...................................................344
Обработка указателей объектов со значением nil................344
Наборы в потоке: пример.......................................344
Добавление методов Store......................................345
Регистрация записей...........................................346
Регистрация...................................................347
Запись в поток................................................347
Как все хранится?.............................................348
Поля в потоке.................................................348
Родство экземпляров окон......................................349
Копирование потока............................................350
Потоки произвольного доступа..................................350
Необъектные элементы потоков..................................351
Разработка пользователем собственных потоков..................351
Обработка ошибок потока.......................................352
Часть 4. Справочник по ObjectWindows..........................353
Глава 21. Объектные типы ObjectWindows........................353
TSample модуль
TSample......................................................354
Поля..........................................................354
Методы........................................................354
Init..........................................................355
Zilch (иногда переопределяется)...............................355

B.Pascal 7 & Objects/OW - 10 -

Процедура Sample (модуль
Sample)......................................................355
Процедура Abstract модуль
Objects......................................................355
Функция AllocMultiSel модуль
ODialogs.....................................................355
Переменная Application модуль
OWindows.....................................................356
Константы bf_XXXX модуль
ODialogs.....................................................356
Стили кнопок bs_XXXX модуль
WinTypes.....................................................357
Переменная BWCCClassNames модуль
OWindows.....................................................358
Стили комбинированного блока cbs_XXXX модуль
WinTypes.....................................................359
Константы cm_XXXX модуль
OWindows.....................................................361
Константы coXXXX модуль
Objects......................................................363
Стили класса cs_XXXX модуль
WinTypes.....................................................364
Константа cw_UseDefault модуль
WinTypes.....................................................365
Процедура DoneMemory модуль
OMemory......................................................365
Константы em_XXXX модуль
OWindows.....................................................365
Переменная EmsCurHandle модуль
Objects......................................................365
Переменная EmsCurPage модуль
Objects......................................................366
Стили управляющих элементов es_XXXX модуль
WinTypes.....................................................366
Процедура FreeMultiSel модуль
ODialogs.....................................................368
Константа tsFileSpec модуль
OStdDlgs.....................................................368
Константы id_XXXX модуль
OWindows.....................................................369
Процедура InitMemory модуль
OMemory......................................................370
Стили блока списка lbs_XXXX модуль
WinTypes.....................................................370
Функция LongDiv модуль
OWindows.....................................................372
Функция LongMul модуль
OWindows.....................................................373
Тип LongRec модуль
Objects......................................................373
Функция LoMemory модуль
OMemory......................................................373
Тип MakeIntResource модуль

B.Pascal 7 & Objects/OW - 11 -

WinTypes.....................................................373
Переменная MaxCollectionSize модуль
Objects......................................................374
Флаги блоков mb_XXXX модуль
WinTypes.....................................................375
Функция MemAlloc модуль
OMemory......................................................376
Функция MemAllocSeg модуль
OMemory......................................................376
Константы nf_XXXX модуль
OWindows.....................................................377
Константы pf_XXX модуль
OPrinter.....................................................378
Тип PString модуль
Objects......................................................379
Тип PtrRec модуль
Objects......................................................379
Процедура RegisterODialogs модуль
ODialogs.....................................................379
Процедура RegisterOStdWnds модуль
OSrdWnds.....................................................379
Процедура RegisterOWindows модуль
OWindows.....................................................380
Процедура RegisterType модуль
Objects......................................................380
Процедура RegisterValidate модуль
Validate.....................................................380
Процедура RestoreMemory модуль
OMemory......................................................380
Переменная SafetyPoolSize модуль
OMemory......................................................381
Стили полосы прокрутки sbs_XXXX модуль
WinTypes.....................................................382
Константы sd_XXXX модуль
OStdDlgs.....................................................384
Стили управляющего элемента ss_XXXX модуль
WinTypes.....................................................385
Пpедопpеделенные логические объекты модуль
WinTypes.....................................................386
Переменная StreamError модуль
Objects......................................................387
Константы stXXX модуль
Objects......................................................388
Константы отображения окна sw_XXX модуль
WinTypes.....................................................389
TApplication модуль
OWindows.....................................................391
Поля..........................................................391
Методы........................................................392
Init (иногда переопределяется)................................392
Done (иногда переопределяется)................................392
CanClose (переопределяется редко).............................393
Error (часто переопределяется)................................393

B.Pascal 7 & Objects/OW - 12 -

ExecDialog (никогда не переопределяется)......................393
ExecDialog (никогда не переопределяется)......................393
IdleAction....................................................394
InitApplication (иногда переопределяется).....................394
InitInstance (иногда переопределяется)........................394
InitMainWindow (всегда переопределяется)......................395
MakeWindow (никогда не переопределяется)......................395
MessageLooр (никогда не переопределяется).....................395
рrocessAccels (иногда переопределяется).......................396
рrocessAppMsg (иногда переопределяется).......................396
рrocessDlgMsg (иногда переопределяется).......................396
рrocessDMIAccels (иногда переопределяется)....................396
Функция Run (переопределяется редко)..........................398
SetKBHandler (никогда не переопределяется)....................398
TBufStream модуль
Objects......................................................399
Поля..........................................................399
Методы........................................................400
Init..........................................................400
Done (никогда не переопределяется)............................400
Flush (никогда не переопределяется)...........................400
Getрos (никогда не переопределяется)..........................401
GetSize (никогда не переопределяется).........................401
Read (никогда не переопределяется)............................401
Seek (никогда не переопределяется)............................401
Truncate (никогда не переопределяется)........................401
Write (никогда не переопределяется)...........................402
TButton модуль
ODialogs.....................................................403
Методы........................................................405
Init..........................................................405
InitResource..................................................405
GetClassName (никогда не переопределяется)....................405
Тип TByteArray модуль
Objects......................................................405
TCheckBox модуль
ODialogs.....................................................407
Поля..........................................................408
Методы........................................................409
Init (иногда переопределяется)................................409
InitResource..................................................409
Load..........................................................409
BNClicked (иногда переопределяется)...........................410
Check (переопределяется редко)................................410
GetCheck (переопределяется редко).............................410
GetClassName..................................................410
SetCheck (переопределяется редко).............................410
Store.........................................................411
Toggle (переопределяется редко)...............................411
Transfer (иногда переопределяется)............................411
UnСheck (переопределяется редко)..............................411
TCollection модуль
Objects......................................................413

B.Pascal 7 & Objects/OW - 13 -

Поля..........................................................413
Методы........................................................414
Init..........................................................414
Load..........................................................414
Done (часто переопределяется).................................414
At............................................................415
AtDelete......................................................415
AtFree........................................................415
AtInsert......................................................415
Atрut.........................................................416
Delete........................................................416
DeleteAll.....................................................416
Error (иногда переопределяется)...............................416
FirstThat.....................................................416
ForEach.......................................................417
Free..........................................................417
FreeAll.......................................................418
FreeItem (иногда переопределяется)............................418
GetItem (иногда переопределяется).............................418
IndexOf (никогда не переопределяется).........................418
Insert (никогда не переопределяется)..........................419
Insert (никогда не переопределяется)..........................419
рutItem (иногда переопределяется).............................419
SetLimit (переопределяется редко).............................420
Store.........................................................420
TComboBox модуль
ODialogs.....................................................421
Поля..........................................................423
Методы........................................................423
Init (иногда переопределяется)................................423
InitResource..................................................423
Load..........................................................424
Clear.........................................................424
GetClassName (никогда не переопределяется)....................424
GetEditSel....................................................424
GetText.......................................................424
GetTextLen....................................................425
HideList......................................................425
SetEditSel....................................................425
SetText.......................................................425
SetuрWindow...................................................425
ShowList......................................................425
Store.........................................................426
Transfer......................................................426
TControl модуль
ODialogs.....................................................427
Методы........................................................428
Init..........................................................428
InitResource..................................................429
GetGlassName (всегда переопределяется)........................429
Register (никогда не переопределяется)........................429
WMрaint (переопределяется редко)..............................429
TDialog модуль

B.Pascal 7 & Objects/OW - 14 -

ODialog......................................................430
Поля..........................................................431
IsModal.......................................................431
Методы........................................................432
Init (иногда переопеределяется)...............................432
Load..........................................................432
Done (иногда переопределяется)................................432
Cancel (иногда переопределяется)..............................432
Create (никогда не переопределяется)..........................433
DefWndрroc (никогда не переопределяется)......................433
EndDlg (никогда не переопределяется)..........................433
Execute (никогда не переопределяется).........................433
GetItemHandle (никогда не переопределяется)...................434
Ok (иногда переопределяется)..................................434
SendDlgItemMsg (никогда не переопределяется)..................434
Store.........................................................434
WMClose.......................................................434
WMInitDialog (никогда не переопределяется)....................435
WMрostInvalid.................................................435
WMQueryEndSession.............................................435
Тип TDialogAttr модуль
ODialogs.....................................................435
TDlgWindow модуль
ODialogs.....................................................437
Методы........................................................438
Init..........................................................438
Create (никогда не переопределяется)..........................439
GetWindowClass (часто переопределяется).......................439
TDosStream модуль
Objects......................................................440
Поля..........................................................440
Методы........................................................440
Init..........................................................440
Done (никогда не переопределяется)............................441
Getрos (никогда не переопределяется)..........................441
GetSize (никогда не переопределяется).........................441
Read (никогда не переопределяется)............................441
Seek (никогда не переопределяется)............................441
Truncate (никогда не переопределяется)........................442
Write (никогда не переопределяется)...........................442
TEdit модуль
ODialogs.....................................................443
Поля..........................................................445
Методы........................................................445
Init..........................................................445
InitResource..................................................446
Load..........................................................446
Done..........................................................446
CanClose......................................................447
CanUndo (переопределяется редко)..............................447
ClearModify (переопределяется редко)..........................447
CMEditClear (никогда не переопределяется).....................447
CMEditCoрy (никогда не переопределяется)......................447

B.Pascal 7 & Objects/OW - 15 -

CMEditCut (никогда не переопределяется).......................448
CMEditDelete (никогда не переопределяется)....................448
CMEditрaste (никогда не переопределяется).....................448
CMEditUndo (никогда не переопределяется)......................448
Coрy (переопределяется редко).................................449
Cut (переопределяется редко)..................................449
DeleteLine (переопределяется редко)...........................449
DeleteSelection (переопределяется редко)......................449
DeleteSubText (переопределяется редко)........................449
GetClassName (никогда не переопределяется)....................449
GetLine (переопределяется редко)..............................450
GetLineFromрos (переопределяется редко).......................450
GetLineIndex (переопределяется редко).........................450
GetLineLength (переопределяется редко)........................450
GetNumLines (переопределяется редко)..........................451
GetSelection (переопределяется редко).........................451
GetSubText (переопределяется редко)...........................451
Insert (переопределяется редко)...............................451
IsModified (переопределяется редко)...........................452
IsValid.......................................................452
рaste (переопределяется редко)................................452
Scroll (переопределяется редко)...............................452
Search........................................................452
SetSelection (переопределяется редко).........................453
SetuрWindow...................................................453
SetValidator..................................................453
Store.........................................................453
Transfer (иногда переопределяется)............................454
Undo (переопределяется редко).................................454
WMChar........................................................454
WMGetDlgCode..................................................454
WMKeyDown.....................................................455
WMKillFocus...................................................455
TEditPrintout
OPrinter.....................................................456
Поля..........................................................456
Методы........................................................457
Init..........................................................457
BeginDocument.................................................458
GetDialogInfo.................................................458
HasHextPage...................................................458
PrintPage.....................................................458
SetPrintParams................................................459
TEditWindow модуль
OStdWnds.....................................................460
TEmsStream модуль
Objects......................................................462
Поля..........................................................462
Методы........................................................463
Init..........................................................463
Done (никогда не переопределяется)............................463
GetPos (никогда не переопределяется)..........................463
GetSize (никогда не переопределяется).........................463

B.Pascal 7 & Objects/OW - 16 -

Read (никогда не переопределяется)............................463
Seek (никогда не переопределяется)............................464
Truncate (никогда не переопределяется)........................464
Write (никогда не переопределяется)...........................464
Константы tf_XXXX модуль
OWindows.....................................................464
TFileDialog модуль
OStdDlgs.....................................................466
Поля..........................................................467
Методы........................................................468
Init..........................................................468
CanClose......................................................468
SetupWindow...................................................468
HandleFName...................................................469
HandleFList...................................................469
HandleDList...................................................469
TFileWindow
OStdWnds.....................................................470
TFilterValidator модуль
Validate.....................................................472
Поля..........................................................472
Методы........................................................472
Init..........................................................472
Load..........................................................472
Error.........................................................473
IsValid.......................................................473
IsValidInput..................................................473
Store.........................................................473
TGroupBox
ODialogs.....................................................474
Поля..........................................................475
Методы........................................................476
Init (иногда переопределяется)................................476
InitResource..................................................476
Load..........................................................476
GetClassName (иногда переопределяется)........................476
SelectionChanged (иногда переопределяется)....................477
Store.........................................................477
TInputDialog модуль
OStdDlgs.....................................................478
Поля..........................................................479
Методы........................................................480
Init..........................................................480
CanClose......................................................480
SetupWindow...................................................480
Тип TItemList модуль
Objects......................................................480
TListBox модуль
ODialogs.....................................................482
Методы........................................................483
Init..........................................................483
AddString (иногда переопределяется)...........................484
ClearList (иногда переопределяется)...........................484

B.Pascal 7 & Objects/OW - 17 -

DeleteString (иногда переопределяется)........................484
GetClassName (переопределяется редко).........................484
GetCount (никогда не переопределяется)........................484
GetMsgID......................................................485
GetSelIndex (переопределяется редко)..........................485
GetSelString (переопределяется редко).........................485
GetString (переопределяется редко)............................485
GetStringLen (переопределяется редко).........................485
InsertString (иногда переопределяется)........................486
SetSelIndex (переопределяется редко)..........................486
SetSelString (переопределяется редко).........................486
Transfer (иногда переопределяется)............................486
TLookupValidator модуль
Validate.....................................................488
Методы........................................................488
IsValid (переопределяется редко)..............................488
Lookup (часто переопределяется)...............................488
TMDIClient модуль
OWindows.....................................................490
Поля..........................................................491
Методы........................................................492
Init (переопределяется редко).................................492
Load..........................................................492
ArrangeIcons (переопределяется редко).........................492
CascadeChildren (переопределяется редко)......................492
GetClassName (никогда не переопределяется)....................493
Register......................................................493
Store.........................................................493
TileChildren (переопределяется редко).........................493
WMPaint (никогда не переопределяется).........................493
TMDIWindow модуль
OWindows.....................................................494
Поля..........................................................495
Методы........................................................496
Init (часто переопределяется).................................496
Load..........................................................496
Done (иногда переопределяется)................................496
ArrangeIcons (переопределяется редко).........................497
CascadeChildren (переопределяется редко)......................497
CloseChildren (переопределяется редко)........................497
CMArrangeIcons (переопределяется редко).......................497
CMCascadeChildren (переопределяется редко)....................497
CMCreateChild (никогда не переопределяется)...................498
CMTileChildren (переопределяется редко).......................498
CreateChild...................................................498
DefWndProc....................................................498
GetClassName (иногда переопределяется)........................498
GetClient (никогда не переопределяется).......................499
GetWindowClass (иногда переопределяется)......................499
InitChild (часто переопределяется)............................499
InitClientWindow (иногда переопределяется)....................499
SetupWindow (часто переопределяется)..........................499
Store.........................................................500

B.Pascal 7 & Objects/OW - 18 -

TileChildren (переопределяется редко).........................500
Тип TMessage модуль
OWindows.....................................................501
Тип TMultiSelRec модуль
ODialogs.....................................................501
TObject модуль
Objects......................................................502
Методы........................................................502
Init..........................................................502
Free..........................................................502
Done..........................................................502
Тип TPaintStruct модуль
WinTypes.....................................................502
Тип TPicResult модуль
Validate.....................................................503
TPrintDialog модуль
OPrinter.....................................................504
Поля..........................................................505
Методы........................................................507
Init..........................................................507
Тип TPrintDialogRec модуль
OPrinter.....................................................508
TPrinter модуль
OPrinter.....................................................510
Поля..........................................................510
Методы........................................................512
Init..........................................................512
Done (переопределяется редко).................................512
ClearDevice...................................................512
Configure.....................................................512
GetDC (переопределяется редко)................................512
InitAbortDialog (переопределяется редко)......................513
InitPrintDialog (переопределяется редко)......................513
InitSetupDialog (переопределяется редко)......................513
Print.........................................................513
ReportError (иногда переопределяется).........................514
SetDevice.....................................................514
Setup.........................................................514
TPrinterAbortDlg модуль
OPrinter.....................................................515
Методы........................................................516
Init..........................................................516
SetupWindow (переопределяется редко)..........................516
WMCommand (переопределяется редко)............................517
TPrinterSetupDlg модуль
OPrinter.....................................................518
Поля..........................................................519
Методы........................................................519
Init..........................................................519
Done (переопределяется редко).................................520
Cancel (никогда не переопределяется)..........................520
IDSetup (никогда не переопределяется).........................520
TransferData (никогда не переопределяется)....................520

B.Pascal 7 & Objects/OW - 19 -

TPrintout модуль
OPrinter.....................................................521
Поля..........................................................521
Методы........................................................522
Init..........................................................522
Done..........................................................522
BeginPrinting.................................................523
EndDocument...................................................523
EndPrinting...................................................523
GetDialogInfo.................................................523
GetSelection..................................................524
HasNextPage...................................................524
PrintPage.....................................................524
SetPrintParams................................................524
TPXPictureValidator модуль
Validate.....................................................526
Поля..........................................................526
Методы........................................................526
Init..........................................................526
Load..........................................................527
Done..........................................................527
Error.........................................................527
ISValidInput..................................................527
IsInvalid.....................................................527
Picture.......................................................528
Store.........................................................529
TRadioButton модуль
ODialogs.....................................................530
Методы........................................................531
Init (иногда переопределяется)................................531
GetGlassName..................................................532
TRangeValidator модуль
Validate.....................................................533
Поля..........................................................533
Методы........................................................533
Init..........................................................534
Load..........................................................534
Error.........................................................534
IsValid.......................................................534
Store.........................................................535
Transfer......................................................535
TScrollBar модуль
ODialogs.....................................................536
Поля..........................................................538
Методы........................................................538
Init..........................................................538
InitResource..................................................538
Load..........................................................539
DeltaPos (переопределяется редко).............................539
GetClassName (никогда не переопределяется)....................539
GetPosition (переопределяется редко)..........................539
GetRange (переопределяется редко).............................539
SBBottom (переопределяется редко).............................540

B.Pascal 7 & Objects/OW - 20 -

SBLineDown (переопределяется редко)...........................540
SBLineUp (переопределяется редко).............................540
SBPageDown (переопределяется редко)...........................540
SBPageUp (переопределяется редко).............................540
SBThumbPosition (переопределяется редко)......................541
SBThumbTrack (иногда переопределяется)........................541
SBTop (переопределяется редко)................................541
SetPosition (переопределяется редко)..........................541
SetRange (переопределяется редко).............................541
SetupWindow (иногда переопределяется).........................542
Store.........................................................542
Transfer (иногда переопределяется)............................542
TScroller модуль
OWindow......................................................543
Поля..........................................................543
Методы........................................................546
Init..........................................................546
Load..........................................................546
Done..........................................................546
AutoScroll (иногда переопределяется)..........................547
BeginView.....................................................547
EndView (иногда переопределяется).............................547
HScroll (никогда не переопределяется).........................547
IsVisibleRect (переопределяется редко)........................547
ScrollBy (переопределяется редко).............................547
ScrollTo (иногда переопределяется)............................548
SetPageSize (иногда переопределяется).........................548
SetRange (никогда не переопределяется)........................548
SetBarRange (никогда не переопределяется).....................548
SetUnits......................................................548
Store.........................................................548
VScroll (никогда не переопределяется).........................549
TSortedCollection модуль
Objects......................................................550
Поля..........................................................550
Методы........................................................551
Load..........................................................551
Compare (всегда переопределяется).............................551
IndexOf (никогда не переопределяется).........................551
Insert (никогда не переопределяется)..........................552
KeyOf (иногда переопределяется)...............................552
Search (переопределяется редко)...............................552
Store.........................................................553
TStatic модуль
ODialogs.....................................................554
Поля..........................................................555
Методы........................................................555
Init..........................................................556
InitResource..................................................556
Load..........................................................556
Clear (переопределяется редко)................................556
GetClassName (переопределяется редко).........................556
GetText (переопределяется редко)..............................557

B.Pascal 7 & Objects/OW - 21 -

SetText (переопределяется редко)..............................557
Store.........................................................557
Transfer (иногда переопределяется)............................557
TStrCollection модуль
Objects......................................................558
Методы........................................................558
Compare (иногда переопределяется).............................558
FreeItem (переопределяется редко).............................559
GetItem (переопределяется редко)..............................559
PutItem (переопределяется редко)..............................559
TStream метод
Objects......................................................560
Поля..........................................................560
ErrorInfo (чтение/запись).....................................560
Методы........................................................561
CopyFrom......................................................561
Error (иногда переопределяется)...............................561
Flush (иногда переопределяется)...............................561
Get...........................................................562
GetPos (всегда переопределяется)..............................562
GetSize (всегда переопределяется).............................562
Put...........................................................562
Read (всегда переопределяется)................................563
ReadStr.......................................................563
Reset.........................................................563
Seek (всегда переопределяется)................................563
StrRead.......................................................564
Truncate (всегда переопределяется)............................564
Write (всегда переопределяется)...............................564
WriteStr......................................................564
Тип TStreamRec модуль
Objects......................................................565
TStringLookupValidator модуль
Validate.....................................................567
Поля..........................................................567
Методы........................................................567
Init..........................................................567
Load..........................................................568
Done..........................................................568
Error.........................................................568
Lookup........................................................568
NewStringList.................................................568
Store.........................................................569
TValidator модуль
Validate.....................................................570
Поля..........................................................570
Status........................................................570
Методы........................................................570
Init..........................................................570
Load..........................................................571
Error.........................................................571
IsValid.......................................................571
IsValidInput..................................................571

B.Pascal 7 & Objects/OW - 22 -

Store.........................................................572
Transfer......................................................572
Valid.........................................................573
Тип TVTransfer модуль
Validate.....................................................574
Тип TWndClass модуль
WinTypes.....................................................574
TWindow модуль
OWindows.....................................................576
Поля..........................................................577
Методы........................................................578
Init (часто переопределяется).................................578
InitResource..................................................579
Load..........................................................579
Done (часто переопределяется).................................579
Create........................................................579
DefWndProc (никогда не переопределяется)......................580
FocusChild....................................................580
GetID (переопределяется редко)................................580
GetWindowClass (часто переопределяется).......................580
Paint (часто переопределяется)................................580
SetCaption....................................................581
SetupWindow (часто переопределяется)..........................581
Store.........................................................581
UpdateFocusChild..............................................581
WMActivate (иногда переопределяется)..........................582
WMCreate......................................................582
WMHScroll (иногда переопределяется)...........................582
WMLButtonDown (иногда переопределяется).......................582
WMMDIActivate.................................................583
WMMove........................................................583
WMPaint (переопределяется редко)..............................583
WMSize (иногда переопределяется)..............................583
WMSysCommand..................................................583
WMVScroll (иногда переопределяется)...........................584
Тип TWindowAttr модуль
OWindows.....................................................585
TWindowPrintout модуль
OPrinter.....................................................586
Поля..........................................................586
Методы........................................................586
Init..........................................................586
GetDialogInfo.................................................587
PrintPage.....................................................587
TWindowsObject модуль
OWindows.....................................................588
Поля..........................................................588
Методы........................................................590
Init (часто переопределяется).................................590
Load..........................................................590
Done (часто переопределяется).................................590
AddChild......................................................591
At............................................................591

B.Pascal 7 & Objects/OW - 23 -

CanClose (иногда переопределяется)............................591
ChildWithID (никогда не переопределяется).....................591
CloseWindow...................................................591
CMExit........................................................591
Create (никогда не переопределяется)..........................592
CreateChildren................................................592
DefChildProc (иногда переопределяется)........................592
DefCommandProc (иногда переопределяется)......................592
DefNotificationProc (иногда переопределяется).................593
DefWndProc....................................................593
Destroy (никогда не переопределяется).........................593
Disable.......................................................593
DisableAutoCreate.............................................594
DisableTransfer...............................................594
DispatchScroll (никогда не переопределяется)..................594
Enable........................................................594
EnableAutoCreate..............................................594
EnableKBHandler...............................................595
EnableTransfer................................................595
FirstThat.....................................................595
Focus.........................................................596
ForEach.......................................................596
GetChildPtr...................................................596
GetChildren...................................................596
GetClassName (иногда переопределяется)........................597
GetClient (никогда не переопределяется).......................597
GetId (переопределяется редко)................................597
GetSiblingPtr.................................................597
GetWindowClass (иногда переопределяется)......................598
IndexOf.......................................................598
IsFlagSet.....................................................598
Next..........................................................598
Previous......................................................598
PutChildPtr...................................................599
PutChildren...................................................599
PutSiblingPtr.................................................599
Register (никогда не переопределяется)........................599
RemoveChild...................................................600
SetFlags......................................................600
SetupWindow (часто переопределяется)..........................600
Show (никогда не переопределяется)............................600
Store.........................................................601
Transfer (иногда переопределяется)............................601
TransferData (иногда переопределяется)........................601
WMActivate (иногда переопределяется)..........................601
WMClose (иногда переопределяется).............................602
WMCommand (переопределяется редко)............................602
WMDestroy (переопределяется редко)............................602
WMHScroll (переопределяется редко)............................602
WMNCDestroy (никогда не переопределяется).....................602
WMQueryEndSession.............................................603
WMVScroll (переопределяется редко)............................603
Тип TWordArray модуль

B.Pascal 7 & Objects/OW - 24 -

Objects......................................................603
Константы voXXXX модуль
Validate.....................................................604
Константы vsXXXX модуль
Validate.....................................................605
Константы wb_XXXX модуль
OWindows.....................................................606
Константы wm_XXXX модуль
OWindows.....................................................606
Тип WordRec модуль
Objects......................................................606
Стили окна ws_XXXX модуль
WinTypes.....................................................608

B.Pascal 7 & Objects/OW - 25 -

------------------------------------------------------------------
Введение
-----------------------------------------------------------------

В данном руководстве вы найдете полную документацию по
ObjectWindows - объектно-ориентированной прикладной среде для
Microsoft Windows. Здесь описываются не только то, что может де-
лать ObjectWindows и как, но и почему. Вы поймете, что
ObjectWindows - это наиболее быстрый путь построения развитых и
многофункциональных приложений Windows.

Хотя в данном руководстве поясняется, как работает Windows,
и как с ней взаимодействуют ваши прикладные программы, оно не ох-
ватывает все аспекты программирования с использованием приклад-
ного программного интерфейса Windows (API). Эти подробности вы
можете узнать в других книгах о программировании в Windows.

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

Что такое ObjectWindows?
-----------------------------------------------------------------

В иерархию данной версии ObjectWindows включены новые объек-
ты, а также добавлены средства к существующим объектам. Изменения
существующих объектов обладают обратной совместимостью, так что
существующий код ObjectWindows следует компилировать с минималь-
ными изменениями.

В данной версии ObjectWindows вы найдете следующие новые
средства:

* поддержку проверки допустимости данных (Глава 13);

* объекты для печати документов и содержимого окон (Глава
15);

* специализированные управляющие элементы фирмы Borland в
стиле Windows;

* множество модулей.

Кроме того, данное руководство содержит следующие новые ма-
териалы:

* расширенное учебное руководство;

* новую главу по сообщениям Windows (Глава 16);

* реорганизованные главы, посвященные иерархии и объектам;

B.Pascal 7 & Objects/OW - 26 -


* более полную информацию о наследовании в справочной части.

Для чего предназначена ObjectWindows?
-----------------------------------------------------------------

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

Чтобы прикладную программу можно было признать приложением
Windows, она должна делать очень многое. Например, она не может
выводить информацию прямо на экран и записывать данные непосредс-
твенно в видеопамять. Кроме того, приложение Windows должно отве-
чать на уведомляющие сообщения, которые посылает своим приложени-
ям Windows в ответ на действия пользователя (события) тип выбора
пункта меню.

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

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

Что нужно знать
-----------------------------------------------------------------

Перед началом программирования для Windows вы должны быть
знакомы с его основами. Во-первых, нужно знать, как использовать
Паскаль и Windows. О программировании на Паскале рассказывается в
"Руководстве пользователя" и "Руководстве по языку", а о работе с
Windows вы можете прочитать в документации, поставляемой с прог-
раммным обеспечением Windows.

Кроме того, для работы с ObjectWindows вы должны владеть
объектно-ориентированным программированием. Приложения, написан-
ные с использованием ObjectWindows, интенсивно используют объект-
но-ориентированные методы, включая наследование и полиморфизм.
Эти темы освещаются в главе по объектно-ориентированному програм-
мированию в "Руководстве пользователя". Кроме объектно-ориентиро-
ванных методов вы должны знать о работе с указателями и динами-
ческими переменными, поскольку почти все экземпляры объектов
ObjectWindows динамически распределяются в динамической области
памяти. Об указателях также рассказывается в "Руководстве пользо-

B.Pascal 7 & Objects/OW - 27 -

вателя".

Как работать с данным руководством
-----------------------------------------------------------------

"Руководство по программированию с использованием
ObjectWindows" расширено, что сделало его более полным и простым
в использовании. Если вы уже знакомы с ObjectWindows, то можете
пропустить главы 7, 13, 15 и 16 и прочитать о новых средствах.
Если вы только начинаете работать с ObjectWindows, то прочитайте
сначала первую часть ("Изучение ObjectWindows"). Эту часть можно
использовать в качестве учебного руководства, в котором описыва-
ется построение полного приложения ObjectWindows и объясняются
принципы ObjectWindows.

О чем рассказывается в данном руководстве
-----------------------------------------------------------------

Так как ObjectWindows представляет собой новый подход в
программировании для Windows и использует некоторые новые методы,
с которыми вы, вероятно, не знакомы, в этом руководстве вы можете
найти поясняющий материал. Полные справочные материалы по
ObjectWindows вы можете найти в Главе 21 "Справочник по
ObjectWindows".

Это руководство разбито на 4 части:

* Часть 1, "Изучение ObjectWindows", знакомит вас с принци-
пами разработки прикладной программы Windows с помощью
ObjectWindows, включая учебные материалы, описывающие про-
цесс написания и дополнения приложения ObjectWindows.

* В Части 2, "Использование ObjectWindows", дается более де-
тальная информация об элементах ObjectWindows, включая об-
зор иерархии и ее взаимодействие с операционной средой
Windows, а также подробно поясняются части иерархии и их
использование.

* В Части 3, "Продвинутое программирование с использование
ObjectWindows" обсуждаются важные темы продвинутого прог-
раммирования в Windows, особенно в части непосредственного
взаимодействия с операционной средой Windows, включая со-
общения, графику и использование ресурсов. Здесь вы найде-
те также главы о наборах и потоковых объектах.

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



B.Pascal 7 & Objects/OW - 28 -

------------------------------------------------------------------
Часть 1. Изучение ObjectWindows
-----------------------------------------------------------------


Глава 1. Знакомство с Windows
-----------------------------------------------------------------

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

Этот процесс разбит на следующие шаги:

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

Исходный код приложения для различных этапов вы можете найти
на дистрибутивных дисках. Описываемым в руководстве шагам соот-
ветствуют файлы STEP01.PAS, STEP02.PAS и так далее (можно найти
также промежуточные программы).

Шаг 1: Создание базового приложения
-----------------------------------------------------------------

------------------------¬
¦-Step-1:-Basic-App-----¦ Базовая программа
¦ Step 2: Text ¦ Текст
¦ Step 3: Lines ¦ Строки
¦ Step 4: Menu ¦ Меню
¦ Step 5: About Box ¦ Об окне
¦ Step 6: Pens ¦ Перья
¦ Step 7: Painting ¦ Рисование
¦ Step 8: Streams ¦ Потоки
¦ Step 9: Printing ¦ Печать
¦ Step 10: Palette ¦ Палитра
¦ Step 11: BWCC ¦ Управляющие элементы окна
¦ Step 12: Custom ctrls ¦ Специализированные элементы
L------------------------


B.Pascal 7 & Objects/OW - 29 -

Отправным пунктом для всех программ, которые вы пишете с
применением ObjectWindows, является программа STEP01A.PAS. Эта
программа, которая называется Steps, создает основное окно прило-
жения.

Все программы ObjectWindows должны использовать модуль
OWindows, которые содержит стандартные объекты, используемые
ObjectWindows для приложений и окон. Большинство приложений вклю-
чают в себя также диалоговые блоки и соответствующие управляющие
элементы. ObjectWindows предусматривает для них объекты в модуле
ODialogs. Объекты, относящиеся к печати, находятся в модуле
OPrinter. Программам, применяющим наборы и потоки, необходим мо-
дуль Objects.

Кроме модулей ObjectWindows большинству программ необходимы
также модули WinTypes и WinProcs. Эти два модуля определяют типы
и константы (WinTypes) и процедуры и функции (WinProcs), образую-
щие прикладной программный интерфейс Windows (API). Приложениям,
использующим продвинутые средства Windows (версий старше 3.0),
кроме данных двух нужны также другие модули.

Примечание: Обзор модулей ObjectWindows вы можете най-
ти в Главе 7 "Иерархия ObjectWindows".

Требования к приложению
-----------------------------------------------------------------

Все приложения Windows имеют основное окно, которое выводит-
ся при запуске программы пользователем. Пользователь выходит из
приложения, закрывая основное окно. В приложении ObjectWindows
основное окно представляет собой объект окна. Этот объект принад-
лежит объекту приложения, который отвечает за создание и вывод на
экран основного окна, обработку сообщений Windows и завершение
программы. Объект приложения действует как объектно-ориентирован-
ная замена самого приложения. Аналогично, чтобы сделать скрытыми
детали программирования в Windows, ObjectWindows предусматривает
окно, диалоговый блок и другие объектные типы.

Каждая программа ObjectWindows должна определять новый тип
приложения, являющегося наследником предоставляемого типа
TApplication. В программе Steps этот тип называется
TMyApplication. Приведем основной блок программы Steps:

var
MyApp: TMyApplication;
begin
MyApp.Init('Steps');
MyApp.Run;
MyApp.Done;
end.

Init - это конструктор TMyApplication, создающий новый объ-
ект MyApp. Он позволяет также задать имя приложения (поле объек-

B.Pascal 7 & Objects/OW - 30 -

та) 'Steps' и создает (и выводит) основное окно приложения. Run
запускает последовательность вызовов методов, составляющих ход
выполнения приложения Windows. Done - это деструктор
TMyApplication.

Определение типа приложения
-----------------------------------------------------------------

Ваша прикладная программа должна создавать новый тип из
стандартного типа ObjectWindows TApplication (или некоторых ти-
пов, производных от TApplication). Этот новый тип должен переоп-
ределять по крайней мере один метод - InitMainWindow.
TApplication.InitMainWindow вызывается ObjectWindows автоматичес-
ки для установки основного окна программы. Каждое приложение
ObjectWindows должно строить свое основное окно.

Примечание: Объекты приложения подробно описываются в
Главе 8.

Определение TMyApplication имеет следующий вид:

type
TMyApplication = object(TApplication)
procedure InitMainWindow; virtual;
end;

Инициализация основного окна
-----------------------------------------------------------------

InitMainWindow отвечает за построение объекта окна, исполь-
зуемого в качестве основного окна программы. Этот объект основно-
го окна хранится в поле объекта приложения MainWindow. Объекту
приложения принадлежит объект основного окна, но эти два объекта
не являются родственными в иерархии наследования.

precedure TMyApplication.InitMainWindow;
begin
MainWindow := New(PWindow, Init(nil, 'Steps'));
end;

Обычно метод InitMainWindow модифицируется для создания но-
вого типа основного окна. Указанный метод использует экземпляр
объекта TWindow - предоставляемый ObjectWindows тип окна, который
определяет наиболее общее окно. На шаге 2 мы заменим его более
интересным оконным типом.

Пока программа Steps просто выводит на экран пустое окно,
которое можно перемещать по экрану, изменять его размер, миними-
зировать, максимизировать и закрывать. Приведем полный листинг
программы Steps, которую мы получили к данному моменту:

program Steps;


B.Pascal 7 & Objects/OW - 31 -

uses OWindows;

type
TMyApplication = object(TApplication)
procedure InitMainWindow; virtual;
end;

procedure TMyApplication.InitMainWindow;
begin
MainWindows := New(PWindow, Init(nil, 'Steps'));
end;

var MyApp: TMyApplication;
begin
MyApp.Init('Steps');
MyApp.Run;
MyApp.Done;
end.



B.Pascal 7 & Objects/OW - 32 -

Объект основного окна
-----------------------------------------------------------------

Пока программа Steps состоит из двух объектов - объекта при-
ложения и объекта окна. Объект приложения (MyApp) является эк-
земпляром TMyApplication - типом, производным от TApplication.
Оконный объект, который содержится в поле MainWindow объекта
MyApp, является экземпляром TWindow (общее окно ObjectWindows).
Во всех программах, кроме простейших, вам нужно определить тип
своего основного окна, соответствующий поведению приложения. В
данном разделе мы выведем на экран основное окно, тип которого
является производным от TWindow.

Приложения: Более подробно об основном окне рассказы-
вается в Главе 8 "Объекты приложения".

Что такое объект окна?
-----------------------------------------------------------------

Объект приложения инкапсулирует стандартное поведение прило-
жения Windows, включая построение основного окна. Тип
TApplication обеспечивает фундаментальное поведение для каждого
создаваемого вами приложения.

Аналогично, объект окна инкапсулирует поведение, реализуемое
приложениями ObjectWindows, включая их основные окна. Это поведе-
ние включает в себя вывод на экран, изменение размера и закрытие;
ответ на пользовательские события, такие как щелчок кнопкой "мы-
ши", буксировку и выбор пунктов меню; вывод управляющих элемен-
тов, таких как блоки списка и командные кнопки. Тип TWindow и его
предок TWindowsObject предусматривают для данного базового пове-
дения методы и поля.

Примечание: Объекты окна подробно описываются в Главе
10 "Объекты окна".

Чтобы сделать ваши программы полезными и интересными, вам
нужно создать новый тип, производный от TWindow. Новый тип насле-
дует поля и методы TWindow и добавляет часть своих. В общем слу-
чае объектно-ориентированный подход позволяет вам не "изобретать"
каждый раз окно.



B.Pascal 7 & Objects/OW - 33 -

Описатели
-----------------------------------------------------------------

Объект окна имеет по крайней мере три поля: HWindow. Parent
и ChildList. HWindow содержит описатель окна. Описатель окна -
это уникальное число, которое связывает интерфейсный объект (та-
кой как окно, диалоговый блок или объект управляющего элемента) с
соответствующим элементом экрана.

Примечание: Подробно об описателях окна их использо-
вании рассказывается в Главе 10 "Объекты окна".

Таким образом, HWindow содержит целое значение, идентифици-
рующее соответствующий элемент экрана. Это напоминает бирку на
связке ключей. Аналогично тому как вы выбираете ключ, чтобы дос-
тать из шкафа пальто, вы выбираете описатель для получения окна.
В большинстве случаев вы работаете с объектами окна, и у вас нет
необходимости манипулировать описателем окна непосредственно, но
они используются при вызове функций Windows. Например, на данном
шаге вы вызываете функцию MessageBox. Эта функция требует указа-
ния параметра, идентифицирующего порождающее окно сообщений. Вы
указываете основное окно, описатель которого записан в его поле
HWindow:

MessageBox(MainWindow^.HWindow, 'Хотите сохранить?',
'Файл не изменен', mb_YesNo or mb_IconQuestion);

Порождающие и дочерние окна
-----------------------------------------------------------------

Большинство приложений используют несколько окон, и, чтобы
они взаимодействовали, их требуется связать. Например, когда вы
завершаете приложение, оно должно иметь способ очистки всех окон,
за которые отвечает. В общем случае Windows справляется с этим,
связывая окна как дочернее и порождающее. Порождающее окно отве-
чает за свое дочернее окно. ObjectWindows предусматривает для
каждого объекта окна поля для отслеживания порождающего и дочер-
них окон.

Примечание: Взаимодействие этих окон подробнее описы-
вается в Главе 9.

Поле Parent содержит указатель на порождающий оконный объ-
ект. Это не порождающее окно в смысле предка, а скорее окно-вла-
делец. Взаимосвязь этих окон описывается в шаге 10.

Третье поле оконного объекта - это поле ChildList, содержа-
щее связанный список дочерних окон.

Создание нового типа окна
-----------------------------------------------------------------

Теперь у вас есть некоторое представление о том, что содер-

B.Pascal 7 & Objects/OW - 34 -

жит оконный объект, и вы можете создать новый оконный тип, произ-
водный от TWindow, используя его как основное окно программы
Step. Сначала измените определения и задайте новый тип
TStepWindow. Не забудьте также определить новый указатель на тип
TStepWindow - PStepWindow, который будет полезен при создании эк-
земпляров объектов TStepWindow.

type
PStepWindow = ^TStepWindow;
TStepWindow = object(TWindow)
end;

Затем измените TMyApplication.InitMainWindow, чтобы создать
в качестве основного окна вместо TWindow TStepWindow.

procedure TMyApplication.InitMainWindow;
begin
Main := New(PStepWindow, Init(nil, 'Step'));
end;

Определение нового типа и создание его экземпляра в
InitMainWindow - это все, что требуется для определения нового
типа основного окна для TMyProgram. Объект приложения вызывает
методы для создания интерфейсного элемента окна (Create) и вывода
его на экран (Show). Вам почти никогда не потребуется использо-
вать эти методы непосредственно. Обычно они вызываются при вызове
метода MakeWindow объекта приложения.

Примечание: MAkeWindow поясняется в Главе 9 "Интер-
фейсные объекты".

Однако TStepWindow не определяет новых видов поведения, от-
личных от тех, которые наследуются от TWindow и TWindowObject.
Другими словами, программа Step не становится более интересной.
Такие виды поведения будут добавлены в следующем разделе.

Реакция на сообщения
-----------------------------------------------------------------

Скорейший способ сделать оконный объект полезным - это зас-
тавить его отвечать на некоторые сообщения Windows. Например,
когда вы щелкаете "мышью" в основном окне программы Step, Windows
посылает окну сообщение wm_LButtonDown, которое перехватывается
ObjectWindows и посылается затем соответствующему оконному объек-
ту. Это указывает оконному объекту, что пользователь щелкнул в
нем кнопкой "мыши". При этом передаются также координаты точки,
где пользователь нажал кнопку. (Эту информацию мы используем в
шаге 2.)

Примечание: Сообщения Windows определены в модуле
WinTypes.

Аналогично, когда пользователь щелкает правой кнопкой "мы-

B.Pascal 7 & Objects/OW - 35 -

ши", основной оконный объект получает сообщение wm_RButtonDown,
переданное Windows. На следующем шаге мы узнаем, как сделать так,
чтобы основное окно (экземпляр TStepWindow) отвечало на эти сооб-
щения и делало что-нибудь полезное.

Чтобы перехватывать сообщения Windows и отвечать на них, для
каждого типа поступающего сообщения, на которое вы хотите реаги-
ровать, вам нужно определить метод оконного объекта. Такие методы
называются методами реакции на сообщение. Чтобы определить заго-
ловок определения метода как метод реакции, нужно добавить к вир-
туальному методу расширение, представляющее собой идентификатор
сообщения, на которое нужно реагировать. Например, определенный
ниже метод реагирует на все сообщения wm_LButtonDown.

type
TStepWindow = object(TWindow)
procedure WMLButtonDown(var Msg: TMessage); virtual
vm_First + wm_LButtonDown;
end;

Примечание: Все программы и модули, переопределяющие
методы ответа на сообщение, должны использовать WinTypes.

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

Чтобы облегчить для вас эту задачу, ObjectWindows определяет
для каждого вида сообщений константы: wm_First для сообщений
окон, cm_First для командных сообщений и nf_First для уведомляю-
щих сообщений. Подробнее об этих константах рассказывается в Гла-
ве 7, но сейчас нужно только помнить, что когда вы пишете метод
реакции на сообщение, начинающееся с wm_, к нему добавляется
wm_First.

Msg - это запись типа TMessage, содержащая такую информацию,
как координаты точки, где была нажата кнопка "мыши". Все методы
реакции на сообщение должны воспринимать один параметр-переменную
типа TMessage. Аргумент Msg мы рассмотрим в программе Step позд-
нее.

В данный момент вы можете просто определить методы реакции,
которые выводят на экран окно сообщения о нажатии кнопки "мыши".
Позднее вы сможете добавить более полезную реакцию. Приведем оп-
ределение метода реакции на нажатие левой кнопки "мыши":

procedure TStepWindow.WMLButtonDown(var Msg: TMessage);
begin
MessageBox(HWindow, 'Вы нажали левую кнопку мыши',
'Диспетчеризуемое сообщение', mb_OK);
end;

B.Pascal 7 & Objects/OW - 36 -


Примечание: Программы, которые вызывают MessageBox или
другие функции API Windows, должны использовать модуль
WinProcs.

------------------------------------------------------------T-T-¬
¦-=---------------------Steps-------------------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ ¦
¦ -----------------------------------------------¬ ¦
¦ ¦-=----------Диспетчеризуемое сообщение--------¦ ¦
¦ +----------------------------------------------+ ¦
¦ ¦ ¦ ¦
¦ ¦ Вы нажали левую кнопку мыши ¦ ¦
¦ ¦ ------------¬ ¦ ¦
¦ ¦ ¦----OK-----¦ ¦ ¦
¦ ¦ L------------ ¦ ¦
¦ L----------------------------------------------- ¦
¦ ¦
L----------------------------------------------------------------

Рис. 1.2 Программа Steps реагирует на пользовательское собы-
тие.

Завершение прикладной программы
-----------------------------------------------------------------

Программа Steps завершает выполнение, когда пользователь
дважды щелкает "мышью" в блоке управляющего меню основного окна -
маленьком квадрате в левом верхнем углу. Окно и приложение немед-
ленно закрываются. Такое поведение годится для простых программ,
но может вызвать затруднения в более сложных случаях.

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

Когда пользователь пытается закрыть приложение
ObjectWindows, Windows посылает основному окну сообщение
wm_Close, которое вызывает метод CanClose приложения. CanClose -
это булевская функция, указывающая, можно ли завершить (OK) при-
ложение (True). По умолчанию метод CanClose наследуется из вызова
TApplication метода CanClose основного оконного объекта. В боль-
шинстве случаев решение о закрытии (OK) принимается объектом ос-
новного окна.



B.Pascal 7 & Objects/OW - 37 -

Переопределение CanClose
-----------------------------------------------------------------

Тип основного окна TStepWindow наследует метод CanClose от
TWindowObject, которые вызывает методы CanClose каждого из своих
дочерних окон (если они имеются). Если дочерних окон нет (как в
данном случае), CanClose просто возвращает значение True. Чтобы
модифицировать поведение приложения при закрытии, вы можете пере-
определить метод CanClose для объектного типа своего основного
окна:

function TStepWindow.CanClose: Boolean;
var Reply: Integer;
begin
CanClose := True;
Reply := MessageBox(HWindow, 'Хотите сохранить?',
'Графическое изображение изменено',
mb_YesNo or mb_IconQuestion);
if Reply = id_Yes then CanClose := False;
end;


B.Pascal 7 & Objects/OW - 38 -


Теперь когда пользователи попытаются закрыть Step, они полу-
чат окно сообщений с запросом "Хотите сохранить". Щелчок "мышью"
на командной кнопке Yes (Да) приводит к тому, что CanClose возв-
ращает значение False и предотвращает закрытие основного окна и
приложения. Щелчок "мышью" на No (Нет) возвращает True, и прило-
жение завершает работу. На шаге 8 это окно сообщений получит не-
который смысл. Модифицированная программа Steps показана на Рис.
1.3.

------------------------------------------------------------T-T-¬
¦-=---------------------Steps-------------------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ ¦
¦ ¦
¦ -----------------------------------------------¬ ¦
¦ ¦-=----------Изображение изменилось------------¦ ¦
¦ +----------------------------------------------+ ¦
¦ ¦ --- ¦ ¦
¦ ¦ -?- Хотите сохранить? ¦ ¦
¦ ¦ --- ------------¬ ------------¬ ¦ ¦
¦ ¦ ¦---Yes-----¦ ¦----No-----¦ ¦ ¦
¦ ¦ L------------ L------------ ¦ ¦
¦ L----------------------------------------------- ¦
¦ ¦
L----------------------------------------------------------------

Рис. 1.3 Программа Steps с переопределенным поведением окна.

Дальнейшее изменение закрытия
-----------------------------------------------------------------

Естественно, сообщение о том, что изображение изменилось,
полезно только в том случае, если программа действительно обнару-
живается изменение изображения. Добавив в TStepWindow поле типа
Boolean, вы можете задать флаг, указывающий на изменение изобра-
жения, и выводить окно сообщения только тогда, когда этот флаг
установлен.

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

type
PStepWindow = ^TStepWindow;
TStepWindow = object(TWindow)
HasGhanged: Boolean;
constructor Init(AParent: PWindowsObject: ATitle:
PChar);
.
.
.
end;

B.Pascal 7 & Objects/OW - 39 -


constructor TStepWindow.Init(AParent: PWindowsObject:
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
HasChanged := False;
end;

Далее измените метод CanClose для проверки перед выводом ок-
на сообщения HasChanged:

function TStepWindow.CanClose: Boolean;
var Reply: Integer;
begin
CanClose := True;
if HasChanged then
begin
Reply := MessageBox(HWindow, 'Хотите сохранить?',
'Изображение изменилось',
mb_YesNo or mb_IconQuestion);
if Reply = id_Yes then CanClose := False;
end;
end;

Позднее, когда вы фактически изменяете изображение,
HasChanged нужно установить в True. Следующий листинг показывает
полный исходный под программы Steps на данном шаге:

program Steps;

uses WinTypes, WinProcs, OWindows;

type
TMyApplication = object(TApplication)
procedure InitMainWindow; virtual;
end;

type
PStepWindow = ^TStepWindow;
TStepWindow = object(TWindow)
Haschanged: Boolean;
constructio Init(AParent: PWindowsObject; ATitle:
PChar);
function CanClose: Boolean; virtual;
procedure CanClose: Boolean; virtual;
procedure WMLButtonDown(var Msg: TMessage);
virtual wm_First + wm_LButtonDown;
procedure WMRButtonDown(var Msg: TMessage);
virtual sm_First +? wm_RButtonDown;
end;

constructor TStepWindow.Init(AParent: PWindowsObject;
ATitle: PChar);

B.Pascal 7 & Objects/OW - 40 -

begin
inherited Init(AParent, ATitle);
HasChanged := False;
end;

function TStepWindow.CanClose: Boolean;
var Reply: Integer;
begin
if HasChanged then
begin
CanClose := True;
Reply := MessageBox(HWindow, 'Хотите сохранить?',
'Изображение изменилось',
mb_YesNo or mb_IconQuestion);
if Reply = id_Yes then CanClose := False;
end;
end;

procedure TStepWindow.WMLButtonDown(var Msg: TMessage);
begin
MessageBox(HWindow, 'Вы нажали левую кнопку мыши',
'Диспетчеризуемое сообщение', mb_OK);
end;

procedure TStepWindow.WMRButtonDown(var Msg: TMessage);
begin
MessageBox(HWindow, 'Вы нажали правую кнопку мыши',
'Диспетчеризуемое сообщение', mb_OK);
end;

procedure TMyApplication.InitMainWindow;
begin
MainWindows := New(PStepWindow, Init(nil, 'Steps'));
end;

var MyApp: TMyApplication;
begin
MyApp.Init('Steps');
MyApp.Run;
MyApp.Done;
end.



B.Pascal 7 & Objects/OW - 41 -

------------------------------------------------------------------
Глава 2. Заполнение окна
-----------------------------------------------------------------

Пока ваша программа не делает ничего интересного. В данной
главе мы возьмем программу Step, которая пока представляет собой
просто оболочку программы, и преобразуем ее в полезное интерак-
тивное графическое приложение. Сначала мы выведем в основном окне
текст. Затем преобразуем Step в полное графическое приложение,
позволяющее вам отображать в основном окне линии различной толщи-
ны.

Шаг 2: Отображение текста в окне
-----------------------------------------------------------------

------------------------¬
¦ Step 1: Basic App ¦
¦-Step-2:-Text----------¦
¦ Step 3: Lines ¦
¦ Step 4: Menu ¦
¦ Step 5: About Box ¦
¦ Step 6: Pens ¦
¦ Step 7: Painting ¦
¦ Step 8: Streams ¦
¦ Step 9: Printing ¦
¦ Step 10: Palette ¦
¦ Step 11: BWCC ¦
¦ Step 12: Custom ctrls ¦
L------------------------

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

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

Вывод в контексте дисплея
-----------------------------------------------------------------

Чтобы вывести текст в основном окне программы Step, вам нуж-
на некоторая отображаемая информация. В Windows имеются специаль-
ные средства, управляющие ее графикой, которые называются кон-
текстом дисплея. Контекст дисплея можно рассматривать как эле-
мент, представляющий поверхность окна, где выводится изображение.
Контекст экрана необходим Windows для отображения в окне любого

B.Pascal 7 & Objects/OW - 42 -

текста или графики.

Примечание: Подробно о контексте дисплея рассказывает-
ся в Главе 17 "Интерфейс с графическими устройствами".

Что такое контекст дисплея?
-----------------------------------------------------------------

Контекст дисплея имеет три основных функции отображения:

* Он обеспечивает, что текст и графика не выводятся вне по-
верхности окна.

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

* Он обеспечивает независимость от устройства. Для вывода в
контексте дисплея ваша программа использует стандартные
функции API Windows. В шаге 9 мы покажем как можно исполь-
зовать одни и те же команды для отображения в окне и на
принтере.

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

Поскольку, чтобы рисовать в окне при буксировке "мыши", вам
необходим контекст дисплея, создайте в объекте основного окна но-
вое поле с именем DragDC, которое будет содержать описатель кон-
текста дисплея. DragDC имеет тип HDC, который эквивалентен типу
Word.

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

* получить контекст дисплея;

* нарисовать в нем;

* освободить контекст дисплея.

Получение контекста дисплея
-----------------------------------------------------------------

Чтобы отобразить что-то в окне, вы должны сначала получить
контекст дисплея. Это можно сделать, вызвав в одном из методов
типа непосредственно перед отображением на экране функцию Windows
GetDC:

DragDC := GetDC(HWindow);

B.Pascal 7 & Objects/OW - 43 -

Использование контекста дисплея
-----------------------------------------------------------------

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

TextOut(DragDC, 20, 20, 'Пример текста', 11);
LineTo(DragDC, 30, 45);

Освобождение контекста дисплея
-----------------------------------------------------------------

После отображения текста или графики вы должны освободить
контекст дисплея (как только закончите отображение).

ReleaseDC(HWindow, DragDC);

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

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

Примечание: GDI и вопросы использования памяти освеща-
ются в Главе 17 "Интерфейс с графическим устройством".



B.Pascal 7 & Objects/OW - 44 -

Координаты Windows
-----------------------------------------------------------------

Если вы работали с графикой раньше, то вам уже знакомо поня-
тие системы координат. В Windows координаты потребуются вам для
вывода текста.

При отображении вас касаются только координаты в контексте
дисплея. Windows обеспечивает, чтобы контекст дисплея попадал в
область клиента окна.

Примечание: Область клиента - это часть окна внутри
рамки.

На этом шаге Step отобразит текст, показывающий координаты
той точки в окне, где вы щелкнули кнопкой "мыши". Например, '(20,
30)' - это точка, отстоящая на 20 элементов изображения вправо и
на 30 элементов изображения вниз от верхнего левого угла поверх-
ности отображения. Вы можете отображать прямо в той точке, где
щелкнули "мышью". Это показано на Рис. 2.1.

------------------------------------------------------------T-T-¬
¦-=---------------------Steps-------------------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦(3,7) (483,7) ¦
¦ (385,31) ¦
¦ ¦
¦ (60,42) ¦
¦ (217,52) ¦
¦ ¦
¦ (302,110) (444,110) ¦
¦ ¦
¦ ¦
¦ (109,141) ¦
¦ ¦
¦ (52,182) ¦
¦ (239,187) (385,181) ¦
¦ ¦
¦(4,288) (474,220)¦
L----------------------------------------------------------------

Рис. 2.1 Отображение текста в точке нажатия кнопки "мыши".

Параметры сообщений
-----------------------------------------------------------------

Щелчок левой кнопкой "мыши" генерирует сообщение
wm_LButtonDown, который вы перехватываете с помощью метода реак-
ции на сообщение WMLButtonDown.

Параметр Msg метода реакции на сообщение несет информацию о
породившем сообщение событии (такую как координаты точки, где
пользователь щелкнул кнопкой "мыши"). Msg - это запись TMessage,

B.Pascal 7 & Objects/OW - 45 -

поля которой содержат параметр lParam типа Longint и параметр
wParam типа Word. Идентификаторы lParam и wParam соответствуют
полям в структуре сообщения Windows TMsg.

TMessage определяют также вариантные поля, содержащие подпо-
ля lParam и wParam. Например, Msg.lParamLo содержит младшее слово
lParam, а Msg.lParamHi - старшее слово. Чаще всего используются
поля wParam, lParamLo и lParamHi.

В случае WMLButtonDown Msg.lParamLo содержит x-координату
точки нажатия кнопки "мыши", а Msg.lParamHi - y-координату этой
точки. Таким образом, чтобы переписать WMLButtonDown для отобра-
жения координат точки нажатия кнопки, нужно преобразовать
Msg.lParamLo и Msg.lParamHi в строки и, чтобы они приняли вид
'(25,21)', конкатенировать их с запятой. В примере для форматиро-
вания строки используется функция Windows WVSPrintF.

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

После получения итоговой строки ее можно вывести в точке на-
жатия кнопки "мыши" с помощью функции Windows TextOut. Перед
отображением нужно получить контекст дисплея, а после отображения
- освободить его.

procedure TStepWindow.WMLButtonDown(var Msg: TMessage);

var S: array[0..9] of Char;
begin
WVSPrint(S, '(%d,%d)', Msg.LParam);
DragDC := GetDC(HWindow);
TextOut(DragDc, Msg.LParamLo, Msg.LParamHi, S, StrLen(S));
ReleaseDC(HWindow, DragDC);
end;

Примечание: Windows ожидает получения строк с заверша-
ющим нулем (конечным нулевым байтом). Подробнее эти строки
описываются в Главе 18 "Руководства по языку".

Очистка окна
-----------------------------------------------------------------

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

Чтобы очистить окно в ответ на щелчок правой кнопкой "мыши",
переопределите метод WMRButtonDown и вызовите в нем процедуру
InvalidateRect, которая приводит к повторному отображению всего

B.Pascal 7 & Objects/OW - 46 -

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

Procedure TStepWindow.WMRButtonDown(var Msg: TMessage);
begin
InvelidateRect(HWindow, nil, Trut);
end;

Текущий исходный код вы можете найти в файле STEP02.PAS.



B.Pascal 7 & Objects/OW - 47 -

------------------------------------------------------------------
Шаг 3: Изображение линий в окне
-----------------------------------------------------------------

------------------------¬
¦ Step 1: Basic App ¦
¦ Step 2: Tex ¦
¦-Step-3:-Lines---------¦
¦ Step 4: Menu ¦
¦ Step 5: About Box ¦
¦ Step 6: Pens ¦
¦ Step 7: Painting ¦
¦ Step 8: Streams ¦
¦ Step 9: Printing ¦
¦ Step 10: Palette ¦
¦ Step 11: BWCC ¦
¦ Step 12: Custom ctrls ¦
L------------------------

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

На шаге 3 мы добавим следующее поведение:

* Щелчок левой кнопкой "мыши" и буксировка соединяют началь-
ную и конечную точки отображая в результате линию.

* Щелчок правой кнопкой "мыши" выводит диалоговое окно вво-
да, позволяющее пользователю изменить толщину линии.

Чтобы выполнить эти шаги, изучим сначала схему буксировки
Windows, а затем реализуем простую графическую программу.



B.Pascal 7 & Objects/OW - 48 -

Буксировка линии
-----------------------------------------------------------------

Мы уже видели, что щелчок левой кнопкой "мыши" дает в ре-
зультате сообщение wm_LButtonDown и вызывает метод WMLButtonDown.
В шаге 1 ваша программа отвечала на щелчки левой кнопкой "мыши",
выводя окна сообщений. Вы могли также видеть, что щелчок правой
кнопкой "мыши" давал в результате сообщение wm_RButtonDown и вы-
зывал метод WMRButtonDown. На нажатие правой кнопки "мыши" прог-
рамма отвечала очисткой окна.

Но это предусматривает реакцию только на щелчки кнопкой "мы-
ши". Многие программы Windows требуют от пользователя нажатия
кнопки "мыши" и перемещения ее указателя по экрану (буксировка).
При этом рисуются линии или прямоугольники, либо графическое
изображение помещается в точку с конкретными координатами. Для
программ графического отображения желателен перехват событий бук-
сировки и реакция на них путем изображения линий.

Сообщения wm_MouseMove
-----------------------------------------------------------------

Сделать это можно путем реакции еще на несколько сообщений.
Когда пользователь буксирует "мышь" в новую точку окна, Windows
посылает сообщение wm_MouseMove, а когда пользователь отпускает
левую кнопку "мыши" - сообщение wm_LButtonUp. Обычно окно получа-
ет одно сообщение wm_LButtonDown, за которым следует последова-
тельность сообщений wm_MouseMove (по одному на каждую промежуточ-
ную точку буксировки) и одно сообщение wm_LButtonUp.

Типичная графическая программа Windows реагирует на сообще-
ние wm_LButtonDown инициализацией процесса рисования (получая,
кроме всего прочего, контекст дисплея). На сообщение wm_LButtonUp
она реагирует завершением процесса рисования (освобождая контекст
дисплея).



B.Pascal 7 & Objects/OW - 49 -

Реакция на сообщения буксировки
-----------------------------------------------------------------

Нужно помнить о том, что после wm_LButtonDown всегда следует
сообщение wm_LButtonUp (с промежуточными сообщениями
wm_MouseMove или без них). Таким образом, каждый раз, когда вы
получаете контекст дисплея, вы можете позднее освободить его.

Для правильного функционирования программы Windows очень
важным является освобождение каждого получаемого вами контекста
дисплея. Однако вы можете добавить еще одно более надежное средс-
тво. Определите в TStepWindow новое булевское поле - тип основно-
го окна с именем ButtonDown и обеспечьте его инициализацию в
TStepWindow.Unit значением False. Затем вы можете проверять перед
получением и освобождением контекста дисплея значение ButtonDown.

Приведем три метода обработки буксировки "мыши":

procedure TStepWindow.WMLButtonDown(var Msg: TMessage);
begin
InvalidateRect(HWindow, nil, True);
if not ButtonDown then
begin
ButtonDown := True;
SetCapture(HWindow);
DragDC := GetDC(HWindow);
MoveTo(DragDC, Msg.lParamLo, Msg.lParamHi);
end;
end;

procedure TStepWindow.WMMouseMove(var Msg: TMessage);
begin
if ButtonDown then
LineTo(DragDC, Msg.lParamLo, MsglParamHi);
end;

procedure TStepWindow.WMLButtonUp(var Msg: TMessage);
begin
if ButtonDown then
begin
ButtonDown := False;
ReleaseCapture;
ReleaseDC(HWindow, DragDC);
end;
end;



B.Pascal 7 & Objects/OW - 50 -

Изображение точек и линий
-----------------------------------------------------------------

В API Windows имеются графические функции MoveTo и LineTo,
которые, соответственно, перемещают текущую позицию рисования и
рисуют линию до текущей позиции. Для правильной работы функций
требуется указание описателя контекста дисплея DragDC. Нужно пом-
нить о том, что вы рисуете не непосредственно в окне, а в его
контексте дисплея.

Перехват "мыши"
-----------------------------------------------------------------

Передачу Windows соответствующих сообщений wm_MouseMove
обеспечивают функции SetCapture и ReleaseCapture. Например, если
вы буксируете "мышь" за пределы окна, Windows все равно будет по-
сылать сообщения основному, а не смежному с ним окну, в которое
она попала. Перехват "мыши" обеспечивает также поступление в ваше
окно сообщения от "мыши", так что оно будет знать о прекращении
рисования даже если "мышь" перемещается в другом окне.

Нужно изменить определение объекта для TStepWindow с заго-
ловками метода для WMMouseMove и WMLButtonUp:

procedure WMLButtonUp(var Msg: TMessage); virtual wm_First +
wm_LButtonUp;
procedure WMLMouseMove(var Msg: TMessage); virtual wm_First +
wm_LMouseMove;

Пример полученного исходного кода вы найдете в файле
STEP03A.PAS.



B.Pascal 7 & Objects/OW - 51 -

Изменение размера пера
-----------------------------------------------------------------

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

Для реализации механизма выбора пользователем размера пера
мы используем диалоговое окно (типа TInputDialog). Это окно вида:

------------------------------------------------------------T-T-¬
¦-=---------------------Steps-------------------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ ¦
¦ Введите новую толщину линии: ¦
¦ -----------------------------------------------¬ ¦
¦ ¦-1- ¦ ¦
¦ L----------------------------------------------- ¦
¦ ------------¬ ------------¬ ¦
¦ ¦----OK-----¦ ¦--Cancel---¦ ¦
¦ L------------ L------------ ¦
¦ ¦
L----------------------------------------------------------------

Рис. 2.2 Задание новой толщины линии с помощью диалогового
окна ввода.

Отслеживание размера пера
-----------------------------------------------------------------

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

Изобразительные средства

Для получения графики и текста в окне Windows использует
несколько изобразительных средств: перья, кисти и шрифты. Эти
изобразительные средства представляют собой элементы, хранимые в
памяти Windows и не отличающиеся от видимых элементов экрана, та-
ких как окна и управляющие элементы. Ваша программа может обра-
щаться к изобразительным средствам с помощью описателей (как это
имеет место в случае окон). Так как ObjectWindows не использует
для представления изобразительных средств объекты, вашим програм-
мам не нужно создавать их и удалять из памяти Windows при завер-
шении работы с ними.


B.Pascal 7 & Objects/OW - 52 -

Примечание: В шаге 6 мы создадим объект, инкапсулирую-
щий одно инструментальное средство - перо.

Изобразительное средство можно рассматривать как кисть ху-
дожника, а контекст дисплея - как холст. Художник сначала создает
изобразительные средства (кисти) и получает контекст дисплея
(холст). Затем художник выбирает соответствующее изобразительное
средство, используя в каждый момент одну из кистей. Аналогично,
программа Windows должна выбирать изобразительные средства в кон-
тексте дисплея.

Используемые по умолчанию изобразительные средства

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

Получение пера нового размера
-----------------------------------------------------------------

Сначала нужно обеспечить способ выбора нового размера пера.
В простейшем случае это можно сделать с помощью диалогового окна
ввода модуля OStdDlgs. Добавьте модуль OStdDlgs в оператор uses
программы. Чтобы использовать совместимые с Windows функции рабо-
ты со строками, укажите также модуль Strings. Начало программного
файла должно выглядеть таким образом:

program Steps;

uses Strings, WinTypes, WinProcs, OWindow, OStdDlgs;
.
.
.

Выполнение диалогового окна ввода

Диалоговое окно ввода - это простое диалоговое окно, которое
выводит подсказку и возвращает одну введенную строку текста. Вы
можете использовать его без модификации TInputDialog или других
методов.

Щелчок правой кнопкой "мыши" дает удобный способ вывода па-
раметра для изменения толщины пера. Давайте переопределим метод
WMRButtonDown для вывода нового диалогового окна ввода.

Так как диалоговое окно ввода появляется только на короткое
время, а вся обработка выполняется одним методом, вам нет необхо-
димости определять его как поле TStepWindows. Оно может существо-
вать в виде локальной переменной метода WMRButtonDown. Все пост-
роение и отмену объекта диалогового окна вы можете выполнять в

B.Pascal 7 & Objects/OW - 53 -

рамках метода WMRButtonDowm.

Когда Init построит объект диалогового окна ввода, вы можете
выполнить его как режимное диалоговое окно, вызвав ExecDialog.
ExecDialog проверяет успешность выполнения конструктора Init и
создает объект диалогового окна, соответствующий элементу экрана,
выполняя затем диалоговое окно. Обработка для ExecDialog заверша-
ется только после того как пользователь закрыл диалог, щелкнув
"мышью" на командной кнопке OK (Подтверждение) или Cancel (Отме-
на).

Если пользователь щелкнул "мышью" на командной кнопке OK,
InputText заполняется полученным от пользователя текстом, вызывая
метод GetText из TInputDialog. Так как вы запрашиваете номер тол-
щины, возвращаемый текст нужно преобразовать в число и передать
его в вызове SetPenSize. Таким образом, каждый раз, когда пользо-
ватель выбирает новую толщину линии, старое перо удаляется и соз-
дается новое.

procedure TStepWindow.WMLButtonDown(var Msg: TMessage);
var
InputText: array[0..9] of Char;
NewSize, ErrorPos: Integer;
begin
if not ButtonDown then
begin
Str(PenSize, InputText);
if Application^.ExecDialog(New(PInputDialog,
Init(@Self, 'Толщина линии',
'Введите новую толщину:', InputText,
SizeOf(InputText))) = id_Ok then
begin
Val(InputText, NewSize, ErrorPos);
if ErrorPos = 0 then SetPenSize(NewSize);
end;
end;
end.

Добавление полей объекта

Далее добавим в TStepWindow новое поле для хранения описате-
ля пера, которое вы будете использовать для рисования графики. В
данной программе в каждый момент времени вы можете рисовать и вы-
водить на экран линии только одной толщины. Соответствующее этой
толщине перо хранится в новом поле TStepWindow с именем ThePen.
Вы напишете также метод SetPenSize, создающий новое перо и удаля-
ющий старое. Теперь описание объекта TStepWindow должно принять
следующий вид:

type
PStepWindow = ^TStepWindow;
TStepWindow = object(TWindow)
DragDC: HDC;

B.Pascal 7 & Objects/OW - 54 -

ButtonDown, HasChanged: Boolean;
ThePen: HPen;
PenSize: Integer;
constructor Init(AParent: PWindowsObject;
ATitle: PChar);
destructor Done; virtual;
function CanClopse: Boolean: virtual;
procedure WMLButtonDown(var Msg: TMessage); virtual
wm_First + wm_LButtonDown;
procedure WMLButtonUp(var Msg: TMessage); virtual
wm_First + wm_LButtonUp;
procedure WMMouseMove(var Msg: TMessage); virtual
wm_First + wm_LMouseMove;
procedure WMRButtonDown(var Msg: TMessage); virtual
wm_First + wm_RButtonDown;
procedure SetPenSize(NewSize: Integer); virtual;
end;

Инициализация полей

Чтобы инициализировать новые поля, вам нужно модифицировать
конструктор Init для установки пера и переопределить деструктор
Done для его отмены. Не забудьте вызвать в новых методах наследу-
емые методы:

constructor TStepWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
Inherited Init(AParent, ATitle);
ButtonDown := False;
HasChanged := False;
PenSize := 1;
ThePen := CreatePen(ps_Solid, Pensize, 0);
end;

destructor TStepWindow.Done;
begin
DeleteObject(ThePen);
inherited Done;
end;

Изображение линий

Теперь изменим метод WMLButtonDown для выбора текущего пера
(ThePen) во вновь полученном контексте дисплея. Аналогично MoveTo
и MessageBox, SelectObject является функцией API Windows.

procedure TStepWindow.WMLButtonDown(var Msg: TMessage);
begin
if not ButtonDown then
begin
ButtonDown := True;
SetCapture"(HWindow);

B.Pascal 7 & Objects/OW - 55 -

DragDC := GetDC(HWindow);
SelectObject(DragDC, ThePen);
MoveTo(DragDC, Msg.lParamLo, Msg.lParamHi);
end;
end;

Указанные методы выбирают в контексте дисплея уже созданное
перо. Однако для создания пера нужно написать следующий вызывае-
мый WMRButtonDown метод SetPenSize:

procedure TStepWindow.SetPenSize(NewSize: Integer);
begin
DeleteObject(ThePen);
ThePen := Create(ps_Solid, NewSize, 0);
PenSize := NewSize;
end;

Вызов функции Windows CreatePen - это один из способов соз-
дания пера Windows заданной толщины. Описатель пера записывается
в ThePen. Очень важным шагом является удаление старого пера. От-
сутствие такого шага приведет к неверному использованию памяти
Windows.

На шаге 5 и 6 вы создадите собственное диалоговое окно и
объект пера и используете их для более эффективного графического
отображения.



B.Pascal 7 & Objects/OW - 56 -

------------------------------------------------------------------
Глава 3. Меню и диалоговые ресурсы
-----------------------------------------------------------------

Большинство приложений Windows имеют в своих основных окнах
меню, которые предоставляют пользователю возможность выбора -
например, команды File¦Save, File¦Open и Help. В шаге 4 мы доба-
вим в программу Steps строку меню. Ввод пользователем данных и
выбор параметров в программах Windows часто происходит в диалого-
вых блоках. В шаге 5 в программу Steps будет добавлен диалоговый
блок.

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

Ресурсы для программы проще всего создавать с помощью редак-
торов ресурсов, таких как Resource Workshop (пакет разработчика
ресурсов) фирмы Borland. Подробно о создании и редактировании ре-
сурсов рассказывается в "Руководстве пользователя по пакету раз-
работчика ресурсов".

Шаг 4: Добавление строки меню
-----------------------------------------------------------------

------------------------¬
¦ Step 1: Basic App ¦
¦ Step 2: Text ¦
¦ Step 3: Lines ¦
¦-Step-4:-Menu----------¦
¦ Step 5: About Box ¦
¦ Step 6: Pens ¦
¦ Step 7: Painting ¦
¦ Step 8: Streams ¦
¦ Step 9: Printing ¦
¦ Step 10: Palette ¦
¦ Step 11: BWCC ¦
¦ Step 12: Custom ctrls ¦
L------------------------

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

* Проектирование меню как ресурса меню.

* Определение констант меню во включаемом файле.

* Загрузка файла ресурса из программы.

B.Pascal 7 & Objects/OW - 57 -


* Загрузка ресурса меню в объект основного окна.

* Определение реакции на выбор в меню.

Меню прикладной программы - это не отдельный объект, а атри-
бут основного окна. Все оконные объекты имеют набор атрибутов,
записанных в поле записи Attr объекта. В поле Menu записи Attr
хранится не описатель меню, а меню. Чтобы установить атрибут ме-
ню, вы должны переопределить конструктор своего типа окна
TStepWindow.

Ресурсы меню
-----------------------------------------------------------------

Определение ресурсов меню не является частью исходного кода
программы. Вместо этого существует ресурс, содержит текст пунктов
меню и структуру элементов верхнего уровня и их подсистем. Для
проектирования меню и других ресурсов, таких как диалоговые бло-
ки, пиктограммы и битовые массивы, вы можете использовать пакет
разработчика ресурсов Resource Workshop.

Определение идентификаторов ресурса

Приложение обращается к присоединенным к нему ресурсам по
идентификатору ресурса. Этот идентификатор представляет собой це-
лое значение, например, 100, или целочисленную константу, такую
как MyMenu. Кроме того, приложение отличает один выбор меню от
другого по идентификатору, связанному с элементом меню.

Определение констант меню

Чтобы сделать программу более читаемой, замените идентифика-
торы меню константами, определяемыми во включаемом файле. При
создании своего ресурса меню с помощью Resource Workshop или ком-
пилятора ресурсов вы можете включить те же константы и использо-
вать те же идентификаторы, которые вы используете для доступа к
ресурсу к своей программе. Константы меню для программы Steps оп-
ределены в файле STEPS.INC:

const
cm_FilePrint = 105;
cm_FileSetup = 107;
cm_Pen = 200;
cm_About = 201;
cm_PalShow = 301;
cm_PalHide = 302;

Заметим, что число элементов меню в файле STEPS.INC не опре-
делено. Это связано с тем, что ObjectWindows в файле IWINDOWS.INC
определяет для вас некоторые общие команды меню, включая
cm_FileOpen, cm_FileNew, cm_FileSave и cm_FileSaveAs.


B.Pascal 7 & Objects/OW - 58 -

Включение файлов ресурсов

Чтобы продолжить работу с программой Steps, используйте па-
кет разработчика ресурсов или компилятор ресурсов для создания
ресурса меню и сохраните его в файле с расширением .RES -
STEPS.RES. Формат файла ресурса в исходном виде вы можете посмот-
реть в файле STEPS.RC. Вы можете также использовать файл
STEPS.RES, который можно найти на дистрибутивных дисках. Имея
файл STEPS.RES, вы можете включить его с помощью директивы компи-
лятора $R:

{$R STEPS.RES}

Директива компилятора $R в конце компиляции и компоновки ав-
томатически добавляет заданный файл ресурса к выполняемому файлу.
Ресурсы можно добавить или удалить из выполняемых файлов, а су-
ществующие ресурсы можно модифицировать.

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


B.Pascal 7 & Objects/OW - 59 -


На Рис. 3.1 показан внешний вид этого меню (идентификатор
ресурса 100). Оно включает в себя пункты File (Файл), Options
(Параметры) и Palette (Палитра), а меню File содержит элементы
New (Новый), Open (Открытие), Save (Сохранение), Save As (Сохра-
нение под именем), Print (Печать), Printer Setup (Установка прин-
тера) и Exit (Выход). Элементы верхнего уровня, у которых есть
подэлементы, не имеют идентификаторов меню, а их вывод не вызыва-
ет никаких действий кроме вывода подэлементов.

Примечание: Не путайте идентификатор ресурса меню с
идентификаторами меню отдельных элементов (пунктов) меню.

------------------------------------------------------------T-T-¬
¦-=---------------------Steps-------------------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦-File- Options Palette ¦
+------------------T--------------------------------------------+
¦-New--------------¦ ¦
¦ Open... ¦ ¦
¦ Save ¦ ¦
¦ Save as... ¦ ¦
+------------------+ ¦
¦ Print... ¦ ¦
¦ Printer Setup... ¦ ¦
+------------------+ ¦
¦ Exit ¦ ¦
+------------------- ¦
¦ ¦
¦ ¦
¦ ¦
¦ ¦
¦ ¦
L----------------------------------------------------------------

Рис. 3.1 Программа Steps с ресурсом меню.



B.Pascal 7 & Objects/OW - 60 -

Загрузка ресурса меню
-----------------------------------------------------------------

Получить ресурс меню можно с помощью вызова функции Windows
LoadMenu:

LoadMenu(HInstance, MakeIntResource(100));

MakeIntResource(100) приводит число 100 к ссылочному типу
PChar, представляющему собой указатель на массив символов. Функ-
ции Windows, воспринимающие в качестве аргументов строки, требу-
ют, чтобы они имели тип PChar. Имея дело с ресурсами, Windows
ожидает, что целые числа должны быть представлены в виде PChar,
поэтому если вы хотите обратиться к ресурсу, имеющему числовой
идентификатор, нужно преобразовать его тип с помощью
MakeIntResource.

Примечание: Для использования типа PChar требуется ус-
тановка $X+ (по умолчанию).

В качестве альтернативы идентификатор меню может иметь сим-
вольный идентификатор, например, 'SAMPLE_MENU'. В этом случае
загрузить ресурс меню можно следующим образом:

LoadMenu(HInstance, 'SAMPLE_MENU');

Вот как это делает TStepWindow.Init (заметим, что первое,
что он делает - это вызов конструктора Init, наследуемого из
TWindow, для выполнения инициализации, необходимой для всех окон-
ных объектов):

constructor TStepWindow(AParent: PWindowObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
Attr.Menu := LoadMenu(HInstance, MakeIntResource(100));
BottomDown := False;
HasChanged := False;
end;

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



B.Pascal 7 & Objects/OW - 61 -

Перехват сообщений меню
-----------------------------------------------------------------

Когда пользователь выбирает элемент меню, окно, к которому
присоединено меню, получает командное сообщение Windows.
ObjectWindows обрабатывает и диспетчеризует эти сообщения
wm_Command аналогично другим сообщениям, но облегчает для вас ра-
боту со специальными командами.

Одним из параметров сообщения wm_Command является сама ко-
манда (номер, соответствующий идентификатору меню выбранного эле-
мента). Вместо вызова метода WMCommand и возложения на вас реше-
ния, что делать с каждой возможной командой, ObjectWindows вызы-
вает основанные на конкретных командах методы. Чтобы обработать
эти сообщения, вы можете определить методы для объектного типа
TStepWindow, используя специальное расширение:

procedure CMFileNew(var Msg: TMessage);
virtual cm_First + cm_FileNew;

где cm_First - это константа ObjectWindows, определяющая начало
диапазона констант для команд, а cm_FileNew - это желаемая коман-
да меню. Это означает, что все элементы меню должны иметь уни-
кальные идентификаторы (если только не предполагается реагировать
на них одинаковым образом).

Примечание: О диапазонах сообщений и смещениях расска-
зывается в Главе 16.

Не путайте основанный на cm_First динамический индекс метода
с индексом, соответствующим поступающему сообщению Windows (осно-
ванному на wm_First). cm_First - это специальное смещение, ис-
пользуемое только для определения методов реакции для команд меню
и командных клавиш.



B.Pascal 7 & Objects/OW - 62 -

Определение методов реакции на команду
-----------------------------------------------------------------

Теперь вы можете определить все методы реакции на команды:

procedure CMFileNew(var Msg: TMessage);
virtual cm_First + cm_FileNew;
procedure CMFileOpen(var Msg: TMessage);
virtual cm_First + cm_FileOpen;
procedure CMFileSave(var Msg: TMessage);
virtual cm_First + cm_FileSave;
procedure CMFileSaveAs(var Msg: TMessage);
virtual cm_First + cm_FileSaveAs;
procedure CMFilePrint(var Msg: TMessage);
virtual cm_First + cm_FilePrint;
procedure CMFileSetup(var Msg: TMessage);
virtual cm_First + cm_FileSetup;

Определять процедуру CMExit не требуется, поскольку
TWindowsObject уже определяет завершающую программу процедуру,
которая вызывается при поступлении в основное окно сообщения
cm_Exit.

Связывание клавиш с командами
-----------------------------------------------------------------

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

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

Каждая прикладная программа может иметь только один набор
командных клавиш. Чтобы загрузить в программу ресурс командных
клавиш, переопределите метод InitInstance:

procedure TMyApplication.InitInstance;
begin
inherited InitInstance;
HaccTable := LoadAccelerators(HInstance, 'ShortCuts');
end;

Командные клавиши 'ShortCuts' в STEPS.RES связывают знакомые
вам по IDE функциональные клавиши с аналогичными функциями прог-
раммы Steps. Например, клавиша F3 генерирует команду cm_FileOpen.


B.Pascal 7 & Objects/OW - 63 -

Реакция на команды меню
-----------------------------------------------------------------

Теперь для каждого выбора в меню у вас есть метод, который
будет вызываться в ответ на соответствующую команду. Выбор коман-
ды File¦Print вызывает ваш метод CMFilePrint. Пока вызовем просто
окно сообщения:

procedure TStepWindow.CMFilePrint(var sg: TMessage);
begin
Message(HWindow, 'Средство не реализовано',
'Печать файла', mb_Ok);
end;

На Рис. 3.2 показана реакция программы Steps на выбор коман-
ды File¦Print.

------------------------------------------------------------T-T-¬
¦-=---------------------Steps-------------------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ File Options Palette ¦
+---------------------------------------------------------------+
¦ ¦
¦ ¦
¦ -----------------------------------------------¬ ¦
¦ ¦-=---------------Печать файла-----------------¦ ¦
¦ +----------------------------------------------+ ¦
¦ ¦ ¦ ¦
¦ ¦ Средство не реализовано ¦ ¦
¦ ¦ ¦ ¦
¦ ¦ ------------¬ ¦ ¦
¦ ¦ ¦----OK-----¦ ¦ ¦
¦ ¦ L------------ ¦ ¦
¦ L----------------------------------------------- ¦
¦ ¦
¦ ¦
¦ ¦
¦ ¦
L----------------------------------------------------------------

Рис. 3.2 Программа Steps реагирует на команду File¦Print.

Для CMFileOpen, CMFileSave, CMFileSaveAs и CMFileSetup напи-
шите фиктивные методы, аналогичные CMFilePrint. Позднее вы пере-
пишете данные методы для выполнения осмысленных действий.

Теперь, очистив окно, вы можете реагировать на выбор команды
меню File¦New более интересным образом. Добавьте следующий метод
CMFileNew:

procedure TStepWindow.CMFileNew(var Msg: TMessage);
begin
InvalidateRect(HWindow, nil, True);

B.Pascal 7 & Objects/OW - 64 -

end;

InvalidateRect выполняет принудительное повторное отображе-
ние окна. Полный исходный код программы Steps для данного этапа
содержится в файле STEP04A.PAS.

Добавление диалогового блока
-----------------------------------------------------------------

Диалоговый блок аналогичен всплывающему окну, но обычно оно
сохраняется на экране в течении короткого периода и выполняет од-
ну конкретную задачу, связанную с вводом-выводом, такую как выбор
принтера или настройка страницы документа. Здесь мы добавим в
программу Steps диалоговое окно для открытия и сохранения файлов.

Файловое диалоговое окно, как одно из диалоговых окон
ObjectWindows, определено с типом TFileDialog. Файловое диалого-
вое окно полезно использовать в любой ситуации, когда вы запраши-
ваете у пользователя для сохранения и загрузки выбор файла на
диске. Например, редактор текстов может использовать диалоговое
окно для открытия и сохранения документов.


B.Pascal 7 & Objects/OW - 65 -


Вы будете выводить файловое диалоговое окно в ответ на выбор
пользователем команды File¦Open или File¦Save As. Файловое диало-
говое окно заменяет окно сообщения "Средство не реализовано". В
шаге 8 оно будет приспособлено для некоторых реальных файлов, а
также сохранения и открытия их для записи и считывания реальных
данных. Пока просто выведем диалоговые окна. Вид файлового диало-
гового окна показан на Рис. 3.3.

------------------------------------------------------------T-T-¬
¦-=---------------------Steps-------------------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ File Options Palette ¦
+---------------------------------------------------------------+
¦ -----------------------------------------------¬ ¦
¦ ¦-=---------------Открытие файла---------------¦ ¦
¦ +----------------------------------------------+ ¦
¦ ¦ -------------------¬ -----------¬¦ ¦
¦ ¦ Имя файла: ¦ *.pts ¦ ¦----OK----¦¦ ¦
¦ ¦ L------------------- L-----------¦ ¦
¦ ¦ -----------¬¦ ¦
¦ ¦ Каталог: a:\ ¦--Cancel--¦¦ ¦
¦ ¦ L-----------¦ ¦
¦ ¦ Файлы: Каталоги: ¦ ¦
¦ ¦ -----------------¬ --------------T-¬ ¦ ¦
¦ ¦ ¦ ¦ ¦[-a] ¦^¦ ¦ ¦
¦ ¦ ¦ ¦ ¦[-b] +-+ ¦ ¦
¦ ¦ ¦ ¦ ¦[-c] ¦-¦ ¦ ¦
¦ ¦ ¦ ¦ ¦[-d] ¦-¦ ¦ ¦
¦ ¦ ¦ ¦ ¦[-e] ¦-¦ ¦ ¦
¦ ¦ ¦ ¦ ¦[-f] ¦-¦ ¦ ¦
¦ ¦ ¦ ¦ ¦[-g] ¦-¦ ¦ ¦
¦ ¦ ¦ ¦ ¦[-h] +-+ ¦ ¦
¦ ¦ ¦ ¦ ¦[-i] ¦v¦ ¦ ¦
¦ ¦ L----------------- L-------------+-- ¦ ¦
¦ L----------------------------------------------- ¦
L----------------------------------------------------------------

Рис. 3.3 Программа Steps с диалоговым блоком File Open.

Добавление к программе Steps файлового диалогового блока
требует трех шагов:

* Добавление поля объекта, содержащего имя файла.
* Модификация конструктора объекта для инициализации файла.
* Выполнение диалогового блока.



B.Pascal 7 & Objects/OW - 66 -

Добавление поля объекта
-----------------------------------------------------------------

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

Построение файлового диалогового блока требует трех парамет-
ров: порождающего окна, шаблона ресурса и имя или маску файла (в
зависимости от того, используется файловое окно для открытия или
закрытия файла). Шаблон ресурса определяет, какое из стандартных
файловых диалоговых окон вы хотите использовать. Стандартные фай-
ловые диалоговые ресурсы определяются идентификаторами ресурсов
sd_FileOpen и sd_FileSave. Параметр имени файла используется для
передачи используемой по умолчанию маски файла диалогу открытия
файла (а также для возврата выбранного имени файла) и для переда-
чи используемого по умолчанию имени для сохранения файла.

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

Определение типа TStepsWindow должно теперь выглядеть следу-
ющим образом:

TStepWindow = object(TWindow)
.
.
.
FileName: array[0...fsPathName] of Char;
.
.
.

Примечание: Для работы с константой fsPathName нужно
использовать модуль WinDos.

Модификация конструктора

Для создания экземпляра объекта справочного окна вы можете
использовать конструктор Init типа TStepWindow. Теперь вам потре-
буется добавить к нему код для инициализации FileName:

StrCopy(FileName, '*.PTS');


B.Pascal 7 & Objects/OW - 67 -

Расширение .PTS используется для файлов, содержащих точки
вашего графического изображения.

Выполнение диалогового блока

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

CMFileOpen и CMFileSaveAs следует переписать следующим обра-
зом:

procedure TStepWindow.CMFileOpen(var Msg: TMessage);
begin
if Application^.ExecDialog(New(PFileDialog,
Init(@Self, PChar(sd_FileOpen), FileName))) = id_Ok
then MessageBox(HWindow, FileName, 'Открыть файл:',
mb_Ok);
end;

procedure TStepWindow.CMFileSaveAs(var Msg: TMessage);
begin
if Application^.ExecDialog(New(PFileDialog,
Init(@Self, PChar(sd_FileSave), FileName))) = id_Ok
then MessageBox(HWindow, FileName, 'Сохранить файл:',
mb_Ok);
end;

Заметим, что при выполнении файлового диалогового окна ис-
пользуется тот же метод ExecDialog, который вы вызывали для вы-
полнения диалогового окна ввода в шаге 3. С помощью метода
ExecDialog выполняются все режимные диалоговые окна в приложении.

Полный исходный код программы Steps для данного шага вы мо-
жете найти в файле STEP04B.PAS.



B.Pascal 7 & Objects/OW - 68 -

------------------------------------------------------------------
Шаг 5: Добавление диалогового блока
-----------------------------------------------------------------

------------------------¬
¦ Step 1: Basic App ¦
¦ Step 2: Text ¦
¦ Step 3: Lines ¦
¦ Step 4: Menu ¦
¦-Step-5:-About-Box-----¦
¦ Step 6: Pens ¦
¦ Step 7: Painting ¦
¦ Step 8: Streams ¦
¦ Step 9: Printing ¦
¦ Step 10: Palette ¦
¦ Step 11: BWCC ¦
¦ Step 12: Custom ctrls ¦
L------------------------

До сих пор в программе Steps использовались два очень прос-
тых диалоговых блока: окно сообщений (в методе CanClose) и диало-
говый блок ввода для изменения размера пера. Эти диалоговые блоки
удобно применять для простых задач, но в программах обычно требу-
ются более сложные и ориентированные на задачу взаимодействия с
пользователем. В таких случаях вы можете разработать собственные
диалоговые блоки.

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

Создание диалогового блока из ресурса требует следующих ша-
гов:

* Создание ресурса диалогового блока.
* Построение объекта диалогового блока.
* Выполнение диалогового блока.



B.Pascal 7 & Objects/OW - 69 -

Создание ресурсов диалогового блока
-----------------------------------------------------------------

Проектировать ресурсы диалогового блока можно несколькими
способами, используя пакет разработчика ресурса Resource Workshop
или компилятор ресурсов. Диалоговый блок (блок диалога) - это
специализированное окно с рамкой, содержащее один или более уп-
равляющих элементов (командные кнопки, блоки списка и пиктограм-
мы). Ваша прикладная программа не знает о том, как выглядят уп-
равляющие элементы и как они позиционированы; она знает только о
типе управляющих элементах и их идентификаторах.

Примечание: Не забывайте, что ресурс - это просто не-
кое описание того, что будет создавать ваша программа.

Идентификаторы управляющих элементов
-----------------------------------------------------------------

Аналогично элементам в ресурсе меню, каждый управляющий эле-
мент в ресурсе диалогового блока имеет идентификатор, который
прикладная программа использует для определения того, с каким уп-
равляющим элементом нужно взаимодействовать. Для статических эле-
ментов, с которыми ваша прикладная программа не взаимодействует
(статический текст или битовые массивы) уникальные идентификаторы
не требуются, поэтому они обычно имеют идентификатор -1.

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



B.Pascal 7 & Objects/OW - 70 -

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

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

Конструктор объекта диалогового блока выглядит как конструк-
тор оконного объекта, воспринимающий два параметра. В обоих слу-
чаях первый параметр - это указатель на объект порождающего окна.
Второй параметр (PChar) определяет заголовок объекта окна. Однако
для объекта диалогового блока в качестве шаблона диалогового бло-
ка используется имя диалогового ресурса.

Файл ресурса для программы Steps определяет диалоговый блок
с именем 'ABOUTBOX', которое вы можете использовать в качестве
окна About box, показанного на Рис. 3.4. Построение объекта диа-
логового блока из данного ресурса выглядит следующим образом:

New(PDialog, Init(@Self, 'ABOUTBOX'));

--------------------------------------------------¬
¦-=------------------About Steps------------------¦
+-------------------------------------------------+
¦ ¦
¦ -----------------------------------------¬ ¦
¦ ¦ ¦ ¦
¦ ¦ ---- ObjectWindows tutorial program ¦ ¦
¦ ¦ ---- ¦ ¦
¦ ¦ Copiright (C) 1992 ¦ ¦
¦ ¦ Borland International Inc. ¦ ¦
¦ ¦ All Rights Reserved ¦ ¦
¦ L----------------------------------------- ¦
¦ ¦
¦ ------------¬ ¦
¦ ¦----OK-----¦ ¦
¦ L------------ ¦
L--------------------------------------------------

Рис. 3.4 Окно About Box для программы Steps.

Выполнение диалогового блока
-----------------------------------------------------------------

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

Application^.ExecDialog(New(PDialog,Init(@Self,'ABOUTBOX')));

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

B.Pascal 7 & Objects/OW - 71 -

блока About box; Steps использует сообщение cm_About, генерируе-
мое выбором меню Optrions¦About. Теперь такой вид реакции на ко-
манду должен быть вам достаточно знаком (см. файл STEP05.PAS):

type
TStepWindow = object(TWindow)
.
.
.
procedure CMAbout(var Msg: TMessage);
virtual cm_First + cm_About;
end;

procedure TStepWindow.CMAbout(var Msg: TMessage);
begin
Application^.ExecDialog(New(PDialog, Init(@Self,
'ABOUTBOX')));
end;

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



B.Pascal 7 & Objects/OW - 72 -

Режимные и безрежимные диалоговые блоки
-----------------------------------------------------------------

После выполнения окна с помощью ExecDialog диалоговый блок
становится режимным. Это означает, что программа работает с этим
блоком до его закрытия. Пока активно это окно, все получаемые
программой сообщения поступают в него. Такой диалоговый блок на-
зывается режимным окном приложения, поскольку оно режимное только
по отношению к выполняющему его приложению. Существуют также сис-
темные режимные диалоговые блоки, которые приостанавливают всю
работу приложения, пока блок не будет закрыт. Такие блоки и окна
используются редко, и применять их следует только в том случае,
если при работе других приложений могут возникнуть проблемы.

Иногда желательно получить диалоговый блок, сохраняющийся
при работе других частей программы. Такой диалоговый блок работа-
ет почти как обычное окно, но не является режимным, и потому но-
сит название безрежимного. О создании безрежимных диалоговых бло-
ков рассказывается в Главе 11 "Объекты диалоговых блоков".



B.Pascal 7 & Objects/OW - 73 -

------------------------------------------------------------------
Глава 4. Работа с диалоговым блоком
-----------------------------------------------------------------

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

В данной главе описаны следующие шаги:

* Определение объекта пера.

* Создание сложного диалогового блока.

* Добавление управляющих объектов.

* Создание буфера передачи.

* Выполнение диалогового блока.

* Чтение результатов.

Шаг 6: Изменение атрибутов пера
-----------------------------------------------------------------

------------------------¬
¦ Step 1: Basic App ¦
¦ Step 2: Text ¦
¦ Step 3: Lines ¦
¦ Step 4: Menu ¦
¦ Step 5: About Box ¦
¦-Step-6:-Pens----------¦
¦ Step 7: Painting ¦
¦ Step 8: Streams ¦
¦ Step 9: Printing ¦
¦ Step 10: Palette ¦
¦ Step 11: BWCC ¦
¦ Step 12: Custom ctrls ¦
L------------------------

Данный шаг охватывает ряд тем, касающихся изобразительных
средств Windows, особенно перьевых средств, применяемых для изоб-
ражения линий. Перья Windows имеют три отдельных атрибута: стиль,
ширину и цвет.

Первая часть данного шага - создание объекта для представле-
ния пера не является абсолютно необходимой, но позволяет вашему
окну работать с пером как единой сущностью, а не отслеживать от-
дельно все атрибуты перьев. Инкапсулируя перо, вы можете также
избежать необходимости иметь дело с некоторыми повторяющимися де-
талями использования инструментальных средств GDI, аналогично то-
му, как объекты окон ObjectWindows предохраняют вас от мелких де-

B.Pascal 7 & Objects/OW - 74 -

талей, связанных с созданием окна.

Создание объекта пера
-----------------------------------------------------------------

Хотя Windows ссылается на свои изобразительные средства как
на "объекты" (отсюда и имена типа SelectObject и DeleteObject),
они не являются объектами в истинном объектно-ориентированном
смысле, так как не используют наследование и полиморфизм. Перо на
самом деле представляет собой просто группу из трех характеристик
отображения, на которые Windows ссылается при изображении линии.
Эти характеристики являются просто свойствами контекста дисплея,
но полезно рассматривать их, как встроенные в перо.

Характеристики пера

Три характеристики пера - это его стиль, размер и цвет. В
шаге 3 вы изменяли размер пера и отслеживали текущий размер пера
в поле объекта окна. Вместо реализации трех отдельных полей для
отслеживания характеристик пера вы можете инкапсулировать их в
единый объект TPen. Описание TPen имеет следующий вид:

type
PPen = ^TPen;
TPen = object(TObject)
Width, Style: Integer;
Color: Longint;
constructor Init(AStyle, AWidth: Integer;
AColor: Longint);
constructor Load(var S: TStream);
procedure ChangePen;
procedure Delete;
procedure Select(ADC: HDC);
procedure SetAttributes(AStyle, AWidth: Integer;
AColor: Longint);
procedure Store(var S: TStream);
private
PenHandle, OldPen: HPen;
TheDC: HDC;
PenData: TPenData;
end;

Примечание: Большую часть исходного кода из данной
главы вы можете найти в файле PEN.PAS. Для использования
модуля Pen в STEP06A.PAS и STEP06B.PAS нужно внести мини-
мальные изменения.

Примечание: Тип TPen определен в модуле Pen.

Конструктор Init создает новый объект пера с заданным сти-
лем, размером и цветом. SetAttributes изменяет атрибуты уже соз-
данного объекта пера. ChangePen выводит диалоговое окно, позволя-
ющее пользователю задать атрибуты пера. Load и Store позволяют

B.Pascal 7 & Objects/OW - 75 -

сохранять объекты пера в потоке.

Выбор и удаление объектов пера

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

Метод Delete отменяет описатель пера, освобождая ресурс для
Windows. Select проверяет, имеется ли уже выделенное перо, и пе-
ред созданием и выбором нового отменяет существующее перо. Это
полезно использовать, если это же перо предполагается применять
повторно, так что вам не понадобиться вызывать Delete при каждом
использовании пера. С другой стороны, в шаге 7 вы увидите, как
можно сохранять нарисованные линии, и каждая линия будет иметь
свой собственный объект пера. Если бы каждый объект пера созда-
вался и сохранялся в пере Windows, Windows скоро исчерпала бы ре-
сурсы. Поэтому важно непосредственно после использования пера вы-
зывать для его отмены метод Delete.

Основное достоинство TPen в том, что вам не нужно больше
беспокоиться о получении, сохранении и удалении объекта пера.
TPen имеет два частных поля, в одном их которых записывается опи-
сатель пера. Объект пера отслеживает описатель и взаимодействия с
Windows, а ваша программа просто имеет дело с объектом. Другое
частное поле, PenData, содержит используемый на этом шаге буфер
передачи.

Файл STEP06A.PAS содержит код программы Steps, модифициро-
ванный для использования объекта TPen в модуле Pen. В основном
изменения невелики (например, поле ThePen изменяет тип с HPen на
PPen, а метод SetPenSize заменяется вызовом метода
SetPenAttributes объекта пера, поскольку объект пера может управ-
лять цветом и стилем наряду с размером).



B.Pascal 7 & Objects/OW - 76 -

Создание сложного диалогового блока
-----------------------------------------------------------------

До сих пор вы использовали достаточно простой диалоговый
блок (см. блок About Box в шаге 5). Особенно полезными становятся
диалоговые блоки, когда вы можете устанавливать и считывать зна-
чения их управляющих элементов.

В модуле Pen определяется более сложный ресурс диалогового
блока с именем 'PenDlg', который дает вам возможность изменения
атрибутов только что определенного объекта пера. Этот диалоговый
блок показан на Рис. 4.1.

----------------------------------------------------¬
¦-=-----------Set Pen Attributes--------------------¦
+---------------------------------------------------+
¦ --Color----------¬ --Style-----------¬ ¦
¦ ¦ (*) Black ¦ ¦ (*) Solid ¦ ¦
¦ ¦ ( ) Purple ¦ ¦ ( ) Dash ¦ ¦
¦ ¦ ( ) Blue ¦ ¦ ( ) Dot ¦ ¦
¦ ¦ ( ) Cyan ¦ ¦ ( ) DashDot ¦ ¦
¦ ¦ ( ) Green ¦ ¦ ( ) DasDotDot ¦ ¦
¦ ¦ ( ) Yellow ¦ ¦ ( ) Null ¦ ¦
¦ ¦ ( ) Red ¦ +-----------------+ ¦
¦ ¦ ( ) White ¦ ¦ Width: -1- ¦ ¦
¦ L----------------- L------------------ ¦
+---------------------------------------------------+
¦ ¦
¦ -------------¬ -------------¬ ¦
¦ ¦----OK------¦ ¦--Cancel----¦ ¦
¦ L------------- L------------- ¦
¦ ¦
L----------------------------------------------------

Рис. 4.1 Диалоговый блок с изменением атрибутов пера.

Set Pen Attributes - установка атрибутов пера; Color - цвет;
Black - черный; Purple - фиолетовый; Blue - голубой; Cyan - бирю-
зовый; Green - зеленый; Yellow - желтый; Red - красный; White -
белый; Style - стиль; Solid - непрерывная линия; Dash - пунктир;
Dot - точки; DashDot - точки и тире; DasDotDot - тире и две точ-
ки; Null - пусто; Width - ширина; OK - подтверждение; Cancel -
отмена.

Построение объекта из ресурса 'PenDlg' выполняется также,
как это делается для окна About Box (за исключением порождающего
окна). Поскольку диалоговый блок атрибута пера выполняется из
объекта TPen, а не из оконного объекта, вы не можете в качестве
порождающего окна использовать @Self. Вместо этого TPen присоеди-
няет диалоговый блок к одному из окон, о присутствии которых из-
вестно заранее - основному окну приложения:

procedure TPent.ChangePen;

B.Pascal 7 & Objects/OW - 77 -

var PenDlg: PPenDialog;
begin
.
.
.
PenDlg := New(PPenDialog, Init(Application^.MainWindow,
'PenDlg'));
.
.
.
end;

Другим важным отличием является то, что на этот раз вы имее-
те новый производный объектный тип TPenDialog. Так как окно About
box не использует ничего, кроме назначенного по умолчанию поведе-
ния диалогового окна, инкапсулированного в TDialog, вам не требу-
ется создавать для него новый объектный тип. Однако диалог атри-
бутов пера отличается более сложным поведением и требует настрой-
ки объекта.

Приведем определение TPenDialog из модуля Pen:

type
PPenDialog = ^TPenDialog;
TPenDialog = object(TDialog);
constructor Init(AParent: PWindowsObject; AName;
PChar);
end;

constructor TPenDialog.Init(AParent: PWindowsObject;
AName: PChar;
var
AControl: PRadioButton;
i: Integer;
begin
inherited Init(AParent, AName);
AControl := New(PRadioButton, InitResource(@Self,
1100 + i));
for i := 0 to 5 do
AControl := New(PRadioButton, InitResource(@Self,
1200 + i));
end;

Построенные в TPenDialog управляющие объекты поясняются в
следующем разделе.

Управляющие объекты
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 78 -

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

Использование интерфейсных объектов
-----------------------------------------------------------------

При "обычном" программировании в Windows (то есть без
ObjectWindows), ваша прикладная программа должна взаимодейство-
вать с каждым элементом экрана через функции API Windows. Как вы
уже видели, ObjectWindows облегчает создание и управление диало-
говыми блоками, изолируя вас от Windows путем максимально возмож-
ного использования для представления элементов экрана объектов.
Эти интерфейсные объекты также значительно облегчают взаимодейс-
твие с управляющими элементами в диалоговых блоках.

Примечание: Интерфейсные объекты описываются в Главе
9, а управляющие объекты описываются, в частности, в Главе
12.

Если вам не требуются управляющие объекты, вы все равно смо-
жете взаимодействовать с управляющими элементами, но это приведет
к необходимости частого вызова функций API Windows, передачи уп-
равляющим элементам сообщений и интерпретации результатов.
ObjectWindows значительно облегчает эту задачу, инкапсулируя по-
ведение каждого управляющего элемента в объекте. Передаются и об-
рабатываются те же сообщения, но ObjectWindows заботится обо всех
деталях.

Связь объекта с созданными из ресурса управляющим элементом
достаточно проста: внутри конструктора объекта диалогового блока
вы строите объекты для любых управляющих элементов, которыми хо-
тите манипулировать. Однако вместо использования для построения
управляющих объектов конструктора Init применяется InitResource.



B.Pascal 7 & Objects/OW - 79 -

Конструктор InitResource
-----------------------------------------------------------------

Когда вы на этапе выполнения создаете управляющий объект (в
противоположность созданию его из ресурса), вам нужно задать рас-
положение, размер и начальное значение (или состояние) управляю-
щего элемента, а также указать, какой объект является порождаю-
щим. Все эти элементы передаются в качестве параметров конструк-
тору Init объекта.

Связь объекта с управляющим элементом из ресурса намного
проще, так как такая информация как расположение и размер, опре-
деляется ресурсом. Требуется передать конструктору InitResource
только порождающий объект и идентификатор управляющего элемента.
Так как управляющие объекты обычно строятся внутри конструктора
их порождающих диалоговых блоков, указатель порождающего объекта
почти всегда равен @Self.

Как показано в приведенном выше примере, диалог пера модуля
Pen связывает объекты с их управляющими элементами редактирования
(для задания размера пера) и обоими наборами кнопок с зависимой
фиксацией (для задания цвета и стиля).

Заметим, что все управляющие объекты строятся и присваивают-
ся одной и той же локальной переменной AControl. Вашей программе
не придется взаимодействовать ни с одним из этих управляющих эле-
ментов непосредственно, так как пока выполняется режимный диало-
говый блок, остальная часть программы не активна. InitResource
к списку дочерних окон диалогового блока, чтобы обеспечить очист-
ку и уничтожение элементов экрана вместе с диалоговым окном.

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

Создание буфера передачи
-----------------------------------------------------------------

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

Например, диалоговый блок, созданный в шаге 6, имеет поле
редактирования и четырнадцать кнопок с зависимой фиксацией. В уп-
равляющий элемент редактирования требуется передавать строку, а
каждая кнопка с зависимой фиксацией получает значение Word, ука-
зывающее на его выбор. Модуль Pen определяет тип записи, переда-
ваемый TPenDialogs и из него:


B.Pascal 7 & Objects/OW - 80 -

type
TPenData = record
XWidth: array[0..6] of Char;
ColorArray: arra[0..7] of Word;
StyleArray: array[0..5] of Word;
end;

Вы можете также управлять кнопками с независимой фиксацией,
используя 14 отдельных полей или один массив из 14 значений типа
Word; передаваемые данные будут теми же. Однако, так как ваша
прикладная программа будет интерпретировать их как две группы из
8 и 6 кнопок соответственно, удобно задать поле для каждой груп-
пы.

Присваивание буфера

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

PenDlg := New(PPenDialog, Init(Application^.MainWindow,
'PenDlg'));
PenDlg^.TransferBuffer := @PenData;

Если ваши программы создают объекты диалогового окна динами-
чески, убедитесь, что они каждый раз назначают буфер передачи.
TransferBuffer по умолчанию имеет значение nil. Это означает, что
данные не переданы.

Заполнение буфера

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

procedure TPen.ChangePen;
var
PenDlg: PPenDialog;
TempWidth, ErrorPos: Integer;
begin
SetColorAttr(PenDate, Color);
SetStyle(PenDate, Style);
wvsprintf(PenDialog, Init(Application^.MainWindows,
'PenDlg'));
PenDlg^.TransferBuffer := @PenData;
if Application^.ExecDialog(PenDlg) <> id_Cancel then
begin
Val(PenData.XWidth, TempWidth, ErrorPos);
if ErrorPos = 0 then
SetAttributes(SetStyle(PenData), TempWidth,
GetColorAttr(PenData));
end;

B.Pascal 7 & Objects/OW - 81 -

end;

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

procedure SetStyle(var ARec: TPenData; AStyle: Integer);
var i: Integer;
begin
for i := 0 to 5 do
if = AStyle then ARec.StyleArray[i] := bf_Checked
else ARec.StyleArray[i] := bf_Unchecked;
end;

Примечание: SetColorAttr выполняет то же назначение,
что и ColorArray. bf_Checked и bf_Unchecled - это константы
ObjectWindows.

Передача данных
-----------------------------------------------------------------

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

Когда вы завершите диалоговое окно, щелкнув "мышью" на ко-
мандной кнопке OK, ExecDialog перед уничтожением диалогового бло-
ка и его управляющих элементов передает значения из управляющего
элемента обратно в буфер передачи. Отмена диалогового блока или
его закрытие с помощью управляющего меню обходит механизм переда-
чи данных обратно в буфер передачи.

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

Чтение возвращаемых значений
-----------------------------------------------------------------

Считывание значений обратно в буфер передачи - это обратный
процесс по отношению к заполнению буфера перед заполнением диало-
гового окна. В модуле Pen определены некоторые функции, способс-
твующие интерпретации выбора кнопки с зависимой фиксацией в каж-
дой группе.

function GetStyle(ARec: TPenDate): Longint;

B.Pascal 7 & Objects/OW - 82 -

var i: Integer;
begin
for i := 0 to 5 do
if ARec.StyleArray[i] = bf_Cheched then GetStyle := i;
end;

Если пользователь отменяет диалоговый блок, то вас, конечно,
не должно беспокоить считывание значений: они совпадают с пере-
данными значениями. Обычно когда вы выполняете диалоговый блок с
помощью ExecDialog, то чтобы определить, возвратил ли диалоговый
блок какие-либо полезные данные, проверяется возвращаемое значе-
ние (id_Ok, если пользователь щелкнул "мышью" на командной кнопке
OK, в противном случае id_Cancel).

if Application^.ExecDialog(PenDlg) <> id_Cancel then
begin
Val(PenDate.XWith, TempWith, ErrorPos);
SetAttributes(GetStyle(PenData), TempWidth,
GetColorAttr(PenData));
end;

Вызов диалогового блока пера
-----------------------------------------------------------------

Чтобы вывести диалоговый блок пера, вызовите его метод
ChangePen. Программа STEP06B.PAS делает это в ответ на команду
cm_Pen, генерируемую выбором пункта меню Options¦Pen и щелчком
правой кнопкой "мыши".

procedure TStepWindow.CMPen(var Msg: TMessage);
begin
CurrentPen^.ChangePen; { CurrentPen - это объект
блока пера }
end;

procedure TStepWindow.WMRButtonDown(var Msg: TMessage);
begin
if not ButtonDown then CurrentPen^.ChangePen;
end;

Примечание: Данные методы можно найти в файле
STEP06B.PAS.



B.Pascal 7 & Objects/OW - 83 -

------------------------------------------------------------------
Глава 5. Повторное отображение графики
-----------------------------------------------------------------

В следующих трех шагах вы узнаете как

* Отображать по запросу графический образ.

* Сохранять образ файла и загружать его.

* Печатать образ.

Шаг 7: Вывод на экран графики
-----------------------------------------------------------------

------------------------¬
¦ Step 1: Basic App ¦
¦ Step 2: Text ¦
¦ Step 3: Lines ¦
¦ Step 4: Menu ¦
¦ Step 5: About Box ¦
¦ Step 6: Pens ¦
¦-Step-7:-Painting------¦
¦ Step 8: Streams ¦
¦ Step 9: Printing ¦
¦ Step 10: Palette ¦
¦ Step 11: BWCC ¦
¦ Step 12: Custom ctrls ¦
L------------------------

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

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

Изображение и рисование
-----------------------------------------------------------------

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

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

B.Pascal 7 & Objects/OW - 84 -

да они требуют изображения или обновления. При этом окно должно
каким-то образом генерировать образ экрана. В ответ на необходи-
мость изображения. ObjectWindows автоматически вызывает метод
Paint вашего окна. Наследуемый и TWindow метод Paint не выполняет
никаких функций. В Paint вы должны поместить код для передачи со-
держимого окна. Фактически Paint вызывается при первом выводе ок-
на. Paint отвечает за обновление (при необходимости) изображения
текущим содержимым.

Существует еще одно важное отличие между отображением графи-
ки в методе Paint и другим ее отображением (например, в ответ на
действия "мышью"). Содержимое экрана, которое должно использо-
ваться для отображения, передается в параметре PaintDC, так что
вашей программе не требуется получать или освобождать его. Однако
вам потребуется вновь выбрать для PaintDC изобразительные средс-
тва.

Чтобы отобразить содержимое окна, вместо повторения тех
действий, которые привели к первоначальному изображению (DragDC),
вы используете PaintDC. Визуальный эффект будет тот же, что и при
первоначальном рисовании пользователем (аналогично проигрыванию
аудиозаписи концерта). Но чтобы "проигрывать" ее в методе Paint,
сначала вам нужно сохранить графику в виде объектов.

Сохранение графики в объектах
-----------------------------------------------------------------

Созданные программой Steps изображения на самом деле просто
представляют наборы различного числа линий. При каждой буксировке
"мыши" вы добавляете другую линию. А каждая линия - это на самом
деле определенный набор точек, соединенных линейными сегментами.
Чтобы сохранить и воспроизвести такие изображения, вам необходим
гибкий и расширяемый тип данных

Для размещения неизвестного числа линий или точек прекрасно
подходит определенный в модуле Objects тип TCollection. Это набор
объектов, который может динамически расширяться, когда вы добав-
ляете другие элементы. Этим наборам не важно, что они включают,
поэтому вы можете использовать один и тот же механизм и для ри-
сунка (набора линий), и для линии (набора точек).

Примечание: О наборах рассказывается в Главе 19 "Набо-
ры".

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

* Передать окну объект или поле, содержащее набор линий.

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


B.Pascal 7 & Objects/OW - 85 -

* В ответ на сообщения "мыши" добавлять к сохраненным линиям
точки.

Добавление поля объекта
-----------------------------------------------------------------

Чтобы сохранить рисунок в виде набора линий, добавьте в
TStepWindow поле с именем Drawing. В любой момент Drawing содер-
жит текущий рисунок в виде набора объектов линий. Когда требуется
отобразить окно, оно использует для изображения линии данные, за-
писанные в Drawing.

Определение объекта линии
-----------------------------------------------------------------

Далее нужно ответить на вопрос, что такое линия. В шаге 4 вы
видели, что изображаемая линия представляет собой просто набор
точек, передаваемых из Windows в программу через сообщение
wm_MouseMove. Для представления линий и точек вам необходимы объ-
ектные типы. Поскольку эффективный объект изображения линии дол-
жен быть повторно используемой частью, создайте отдельный модуль,
определяющий объекты линий и точек.

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

type
PLine = ^TLine;
TLine = object(TObject)
Points: PCollection;
LinePen: PPen;
constructor Init(APen: PPen);
constructor Load(var S: TStream);
destructor Done; virtual;
procedure AddPoint(AX, AY: Word);
procedure Draw(ADC: HDC);
procedure Store(var S: TStream);
end;

LinePen просто указывает на объект TPen, а Point - это набор
объектов точек. TLine и TLinePoint содержат методы Load и Store,
преимущества использования которых для записи картинок на диск вы
увидите в шаге 8. В отличие от них объект TLine весьма прост:
конструктор и деструктор создают и уничтожают LinePen, AddPoint
включает объект точки в Points, а Draw рисует линии между точками
Points.

Объект TLinePoint еще проще:

type
PLinePoint = ^TLinePoint;
TLinePoint = object(TObject)
X, Y: Integer;

B.Pascal 7 & Objects/OW - 86 -

constructor Init(AX, AY: Integer);
constructor Load(var S: TStream);
procedure Store(var S: TStream);
end;

constructor TLinePoint.Init(AX, AY: Integer);
begin
X := AX;
Y := AY;
end;

TLinePoint не определяет никакого нового поведения - это
просто объект данных, который должен использоваться в TLine. Но
позднее (в шаге 8) он понадобиться как объект для записи в поток.
Не забудьте построить в TStepWindow.Init Drawing и уничтожить его
в TStepWindow.Done:

constructor TStepWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherites Init(AParent, ATitle);
ButtonDown := False;
HasChanged := False;
CommonPen := New(PPen, Init(ps_Solid, 1, 0));
Drawing := New(PCollection, Init(50, 50));
end;

destructor TStepWindow.Done;
begin
Dispose(CommonPen, Done);
Dispose(Drawing, Done);
inherited Done;
end;

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



B.Pascal 7 & Objects/OW - 87 -

Изменение методов работы с "мышью"
-----------------------------------------------------------------

Чтобы сохранять линии в виде объектов, вы должны изменить
EMLButtonDown и WMMouseMove, чтобы не только рисовать линии, но
также сохранять точки в наборе линий. Поскольку текущую линию
придется обновлять не только одному методу, добавьте в
TStepWindow еще одно поле типа PLine с именем CurrentLine:

type
TStepWindow = object(TWindow);
CurrentLine: PLine;
.
.
.
end;

Кроме добавления изображения линии WMLButttonDown создает
при каждом вызове новый объект линии и добавляет его в набор в
Drawing. WMMouseMove просто добавляет новую точку в конец объекта
текущей линии и изображает в окне линейные сегменты. Сохраняя все
точки всех линий, ваше окно будет записывать информацию, необхо-
димую для точного воспроизведения картинки.

procedure TStepWindow.WMLButtonDown(var Msg: TMessage);
begin
if not ButtonDown then
begin
ButtonDown := True;
SetCapture(HWindow);
DragDC := GetDC(HWindow);
CommonPen^.Select(DragDC);
MoveTo(DragDC, Msg.lParamLo, Msg.lParamHi);
CurrentLine := New(PLine, Init(CommonPen));
Drawing^.Insert(CurrentLine);
end;
end.

procedure TStepWindow.WMMouseMove(var Msg: TMessage);
begin
if ButtonDown then
begin
LineTo(DragDC, Msg.lParamLo, Msg.lParamHi);
CurrentLine^.AddPoint(Msg.LParamLo, Msg.LParamHi);
end;
end;

Примечание: Уничтожать устаревшие CurrentLine не тре-
буется, поскольку они записаны в наборе Drawing. Все объек-
ты линий уничтожаются при уничтожении Drawing.

WMLButtonUp модификации не требует. Вам не нужно уничтожать
все объекты линий при очистке отображаемого окна, поэтому добавь-

B.Pascal 7 & Objects/OW - 88 -

те в CMFileNew вызов метода FreeAll:

procedure TStepWindow.CMFileNew(var Msg: TMessage);
begin
Drawing^.FreeAll;
InvalidateRect(HWindow, nil, True);
end;

Вывод сохраненной графики
-----------------------------------------------------------------

Теперь, когда TStepWindow сохраняет свою текущую строку, вы
должны научить его по команде (этой командой является Paint) ри-
совать ее. Давайте напишем для TStepWindow метод Paint, который
повторяет действия WMLButtonDown, WMMouseMove и WMLButtonUp. Пу-
тем итерации по набору линий Paint воссоздает картинку аналогично
тому, как это делаете вы. Метод Paint имеет следующий вид (см.
файл STEP07.PAS):

procedure TStepWindow.Paint(PaintDC: HDC; var PaintInfo:
TPintStruct);

procedure DrawLine(P: PLine); far;
begin
P^.Draw(PaintDC);
end;

begin
Drawing^.ForEach(@DrawLine);
end;

Примечание: Итерация методов описывается в Главе 19
"Наборы".

Метод Draw объекта линии для изображения каждой линии между
точками также использует итератор ForEach:

procedure TLine.Draw(ADC: HDC);
var First: Boolean;

procedure DrawLine(P: PLinePoint); far;
begin
if First then MoveTo(ADC, P^.X, P^.Y)
else LineTo(ADC, P^.X, P^.Y);
First := False;
end;

begin
First := True;
LinePen^.Select(ADC);
Points^.ForEach(@DrawLine);
LinePen^.Delete;
end;

B.Pascal 7 & Objects/OW - 89 -

------------------------------------------------------------------
Шаг 8: Сохранение рисунка в файле
-----------------------------------------------------------------

------------------------¬
¦ Step 1: Basic App ¦
¦ Step 2: Text ¦
¦ Step 3: Lines ¦
¦ Step 4: Menu ¦
¦ Step 5: About Box ¦
¦ Step 6: Pens ¦
¦ Step 7: Painting ¦
¦-Step 8:-Streams-------¦
¦ Step 9: Printing ¦
¦ Step 10: Palette ¦
¦ Step 11: BWCC ¦
¦ Step 12: Custom ctrls ¦
L------------------------

Теперь, когда вы сохранили представление данных в виде ри-
сунка как часть оконного объекта, можно легко записать эти данные
в файл (фактически, в буферизованный поток DOS) и считать его об-
ратно.

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

Отслеживание состояния
-----------------------------------------------------------------

Требуется отслеживать две характеристики рисунка. Изменение
файла мы уже отслеживали (в шаге 1 было добавлено поле
HasChanged), но теперь нужно знать, загружен ли файл в данный мо-
мент. Как и HasChanged, IsNewFile - это атрибут TStepWindow типа
Boolean, поэтому его также следует сделать полем:

TStepWindow = object(TWindow)
ButtonDown, HasChanged, IsNewFile: Boolean;
.
.
.
end.

Поле HasChanged принимает значение True, если текущий рису-
нок модифицирован. Модификация означает, что рисунок был изменен
с момента последнего сохранения или не сохранялся вовсе. Вы уже
устанавливаете поле HasChanged в True, когда пользователь начина-
ет рисовать, и в False, когда окно очищается. Когда пользователь
открывает новый файл или сохраняет существующий, HasChanged сле-
дует установить в False.


B.Pascal 7 & Objects/OW - 90 -

IsNewFile указывает, что рисунок не взят из файла, поэтому
сохранение рисунка потребует от пользователя задать имя файла.
IsNeFile имеет значение True только при первоначальном запуске
приложения и после выбора пользователем команды меню File¦New
(Файл¦Новый). Это поле устанавливается в False, когда файл откры-
вается или сохраняется. Фактически, FileSave использует
IsNewFile, чтобы увидеть, можно ли сохранить файл немедленно, или
пользователю требуется выбрать файл из файлового диалога.

Приведем методы сохранения и загрузки файла. На данный мо-
мент они выполняют только сохранение и загрузку файлов. Сохране-
ние файла сконцентрировано в одном новом методе, который называ-
ется WriteFile, а открытие файла выполняет метод ReadFile.

procedure TStepWindow.CMFileNew(var Msg: TMessage);
begin
if CanClose then
begin
Drawing^.FreeAll;
InvalidateRect(HWindow, nil, True);
HasChanged := False;
IsNewFile := True;
end;
end;

procedure TStepWindow.CMFileOpen(var Msg: TMessage);
begin
if CanClose then
if Application^.ExecDialog(New(PFileDialog, Init(@Self,
PChar(sd_FileOpen), StrCopy(FileName, '*.PTS')))) =
id_Ok then ReadFile;
end;

procedure TStepWindow.CMFileSave(var Msg: TMessage);
begin
if IsNewFile then CMFileSaveAs(Msg) else WriteFile;
end;

procedure TStepWindow.CMFileSaceAs(var Msg: TMessage);
begin
if IsNewFile then StrCopy(FileName, '');
if Application^.ExecDialog(New(PFileDialog,
Init(@Self, PChar(sd_FileSave), FileName))) =
id_Ok then WriteFile;
end;

procedure TStepWindow.ReadFile;
begin
MessageBox(HWindow, @FileName, 'Загрузить файл:',
mb_Ok);
HasChanged := False;
IsNewFile := False;
end;

B.Pascal 7 & Objects/OW - 91 -


procedure TStepWindow.WriteFile;
begin
MessageBox(HWindow, @FileName, 'Сохранить файл:',
mb_Ok);
HasChanged := False;
IsNewFile := False;
end;

Примечание: Данный текст программы можно найти в файле
STEP08A.PAS.

Сохранение и загрузка файлов
-----------------------------------------------------------------

Теперь, когда вы создали основную схему для построения и
загрузки файлов, осталось только выполнить фактическую загрузку и
сохранение в файле наборов точек. Для этого можно использовать
потоковый механизм автоматического сохранения объекта. Сначала вы
научитесь сохранять и загружать сами объекты точек и линий (как
это сделать для наборов вы уже знаете). Затем методы WriteFile и
FileOpen будут модифицированы для использования потоков.

Примечание: Подробнее об использовании потоков с объ-
ектами рассказывается в Главе 20 "Потоки".

Ниже приведен исходный код, показывающий как сохранять и
загружать сами объекты TLine и TLinePoint:

const
RLinePoint: TStreamRec = (
ObjType: 200;
VmtLink: Ofs(TypeOf(TLinePoint)^);
Load: @TLinePoint.Load;
Store: @TLinePoint.Store);

RLine: TStreamRec = (
ObjType: 201;
VmtLink: Ofs(TypeOf(TLine)^);
Load: @TLine.Load;
Store: @TLine.Store);

constructor TLinePoint.Load(var S: TStream);
begin
S.Read(X, SizeOf(X));
S.Read(Y, SizeOf(Y));
end;

procedure TLinePoint.Store(var S: TStream);
begin
S.Write(X, SizeOf(X));
S.Write(Y, SizeOf(Y));
end;

B.Pascal 7 & Objects/OW - 92 -


constructor TLine.Load(var S: TStream);
begin
Points := PCollection(S.Get);
LinePen := PPen(S.Get);
end;

procedure TLine.Store(var S: TStream);
begin
S.Put(Points);
S.Put(LinePen);
end;

procedure StreamRegistration;
begin
RegisterType(RCollection);
end;

Для регистрации TCollection при запуске прикладной программы
вы должны вызывать StreamRegistration (который находится в
Steps). Вы можете поместить это вызов в метод TStepWindow.Init.
Модуль DrawLine регистрирует в своем коде инициализации
TLinePoint и TLine, поэтому линии и точки регистрируются простым
включением DrawLine в оператор uses.

Заключительным шагом изменения методов WriteFile и ReadFile
будет фактическая запись в потоки и чтение из них (см.
STEP08B.PAS):

procedure TStepWindow.ReadFile;
var
TempColl: PCollection;
TheFile: TDosStream;
begin
TheFile.Init(FileName, stOpen);
TempColl: := PCollection(TheFile.Get);
TheFile.Done;
if TempColl <> nil then
begin
Dispose(Drawing, Done);
Drawing := TempColl;
InvalidateRect(HWindow, nil, True);
end;
HasChanged := False;
IsNewFile := False;
end;

procedure TStepWindow.WriteFile;
var
TheFile: TDosStream;
begin
TheFile.Init(FileName, stCreate);
TheFile.Put(Drawng);

B.Pascal 7 & Objects/OW - 93 -

TheFile.Done;
IsNewFile := False;
HasChanged := False;
end;



B.Pascal 7 & Objects/OW - 94 -

------------------------------------------------------------------
Шаг 9: Печать графического образа
-----------------------------------------------------------------

------------------------¬
¦ Step 1: Basic App ¦
¦ Step 2: Text ¦
¦ Step 3: Lines ¦
¦ Step 4: Menu ¦
¦ Step 5: About Box ¦
¦ Step 6: Pens ¦
¦ Step 7: Painting ¦
¦ Step 8: Streams ¦
¦-Step-9:-Printing------¦
¦ Step 10: Palette ¦
¦ Step 11: BWCC ¦
¦ Step 12: Custom ctrls ¦
L------------------------

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

Добавление этих средств предусматривает следующие три шага:

* Построение объекта принтера.

* Создание объекта распечатки.

* Печать объекта распечатки.


Построение объекта принтера
-----------------------------------------------------------------

Любая программа ObjectWindows может получить доступ к прин-
теру с помощью объекта типа TPrinter. В этом случае основное окно
вашего приложения должно построить объект принтера и сохранить
его в объектном поле с именем Printer:

constructor TStepWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
.
.
.
Printer := New(PPrinter, Init);
end;

Примечание: Тип TPrinter определен в модуле OPrinter,
поэтому не забудьте добавить OPrinter в свой оператор uses.

Это все, что обычно приходится делать для инициализации объ-

B.Pascal 7 & Objects/OW - 95 -

екта принтера. По умолчанию TPrinter использует назначенный по
умолчанию принтер, заданный в файле WIN.INI. TPrinter предусмат-
ривает также механизм для выбора альтернативных принтеров.


Создание объекта распечатки
-----------------------------------------------------------------

ObjectWindows управляет выводимыми на печать данными точно
также, как выводом на экран. То есть вместо записи непосредствен-
но на устройство вывода (или даже непосредственно в Windows) вы
направляете свой вывод на объект, который знает, как представлять
информацию на устройстве вывода. Для вывода на печать используйте
объекты, полученные из абстрактного типа TPrintout и метода с
именем PrintPage.

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

Примечание: О печати документов рассказывается в Главе 15.

Запись в контекст устройства
-----------------------------------------------------------------

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

Запись в контекст одного устройства мало отличается от запи-
си в контекст другого, поэтому, например, достаточно просто сооб-
щить, например, оконному объекту, что для записи на принтер нужно
использовать механизм Paint.

Создание распечатки окна
-----------------------------------------------------------------

TWindowPrint - это специальный потомок TPrintout, используе-
мый для печати содержимого окна. Печать содержимого окна не
представляет сложности по двум причинам: вы имеете дело только с
одной страницей, и объект окна уже знает, как отображать свой об-
раз.

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

B.Pascal 7 & Objects/OW - 96 -


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

procedure TWindowPrint.PrintPage(DC: HDC; Page: Word;
Size: TPoint; var Rect: TRect; Flags: Word);
var PS: TPaintStruct;
begin
Window^.Paint(DC, PS);
end;

Поскольку переданный PrintPage параметр DC уже указывает на
подходящий для принтера контекст устройства, в простейшем случае
PrintPage должен только сообщить объекту окна на вывод его содер-
жимого в этот контекст устройства. Теперь ваш объект распечатки
также знает о своем представлении.

Вывод распечатки
-----------------------------------------------------------------

Наличие объекта распечатки, которому известно о своем предс-
тавлении, это все, что нужно для передачи распечатки на принтер.
Программа Steps делает это в ответ на команду cm_FilePrint, гене-
рируемую командой Print меню File:

procedure TStepWindow.CMFilePrint(var Msg: TMessage);
var P: PPrintout;
begin
if IsNewFile then StrCopy(FileName, 'Untitled');
P := New(PWindowPrint, Init(FileName, @Self));
Printer^.Print(@Self, P);
Dispose(P, Done);
end;

CMFilePrint очень просто строит объект распечатки, озаглав-
ленный заданным именем (имя файла точек или 'Untitled') и запол-
няет его своим содержимым (так как это единственное окно в при-
ложении).

При наличии объекта распечатки CMFilePrint сообщает объекту
принтера, что его нужно напечатать, добавив какие-либо сообщения
об ошибках или диалоговые окна (отсюда параметр @Self). Когда пе-
чать закончится, CMFilePrint уничтожает объект распечатки.

Выбор другого принтера
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 97 -


Чтобы вывести диалоговое окно установки принтера, ваша прик-
ладная программа вызывает метод Setup объекта принтера. Steps де-
лает это в ответ на команду cm_FileSetup (см. STEP09.PAS):

procedure TStepWindow.CMFileSetup(var Msg: TMessage);
begin
Printer^.Setup(@Self);
end;

Диалоговое окно установки принтера является экземпляром типа
TPrinterSetupDlg (см. Рис. 5.1).

----------------------------------------------------------------¬
¦-=---------------------Select Printer--------------------------¦
+---------------------------------------------------------------+
¦ ¦
¦ Принтер и порт ¦
¦ ---------------------------------------------T-¬ ¦
¦ ¦PostScript Printer on LPT1:-----------------¦v¦ ¦
¦ L--------------------------------------------+-- ¦
¦ ------------¬ ------------¬ ------------¬ ¦
¦ ¦----OK-----¦ ¦--Setup----¦ ¦--Cancel---¦ ¦
¦ L------------ L------------ L------------ ¦
¦ ¦
L----------------------------------------------------------------

Рис. 5.1 Диалоговое окно установки принтера.

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



B.Pascal 7 & Objects/OW - 98 -

------------------------------------------------------------------
Глава 6. Вывод всплывающего окна
-----------------------------------------------------------------

Итак, вы создали два типа окон - основное окно (объект
TStepWindow) и режимные дочерние окна, которые создаются и унич-
тожаются каждый раз, когда они необходимы (например, блоки сооб-
щений). Однако, в полноценной программе Windows дочерние окна
часто требуется сохранять активными в течении неопределенного пе-
риода времени (в качестве примера можно привести окно оперативной
полосы SpeedBar в работающей под Windows интегрированной среде
IDE).

До сих пор все дочерние окна в Steps имели фиксированный
размер и создавались из шаблонов ресурсов. В шагах 10 - 12 вы бу-
дете делать следующее:

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

* Добавлять в окно специализированные управляющие элементы.

* Создавать собственное интерактивное окно.

Наконец, мы дадим предложения по дальнейшему расширению
программы Steps.

Шаг 10: Добавление всплывающего окна
-----------------------------------------------------------------

------------------------¬
¦ Step 1: Basic App ¦
¦ Step 2: Text ¦
¦ Step 3: Lines ¦
¦ Step 4: Menu ¦
¦ Step 5: About Box ¦
¦ Step 6: Pens ¦
¦ Step 7: Painting ¦
¦ Step 8: Streams ¦
¦ Step 9: Printing ¦
¦-Step-10:-Palette------¦
¦ Step 11: BWCC ¦
¦ Step 12: Custom ctrls ¦
L------------------------

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

В этом шаге вы будете делать следующее:

* Добавите к основному окну поле.


B.Pascal 7 & Objects/OW - 99 -

* Построите плавающую палитру пера.

* Выведете и скроете палитру пера.

Палитра пера, которая выводится при выборе пользователем ко-
манды Palette¦Show (Палитра¦Вывод) показана на Рис. 6.1.

----------------------------------------¬
¦-=--------------PenPalette-------------¦
+------------------T--------------------+
¦ -- Add ¦ Delete ¦
¦ ------ Pen ¦ ------ Pen ¦
¦ -- ¦ ¦
+------------------+--------------------+
¦ ¦
¦ ----------------------------- ¦
¦ ¦
+---------------------------------------+
¦ ¦
¦ ----------------------------- ¦
¦ ¦
+---------------------------------------+
¦ ¦
¦ ----------------------------- ¦
¦ ¦
L----------------------------------------

Рис. 6.1 Палитра пера программы Steps с тремя перьями.

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

Добавление к окну дочернего окна
-----------------------------------------------------------------

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

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

B.Pascal 7 & Objects/OW - 100 -


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

TStepWindow = object(TWindow)
DragDC: DHC;
ButtonDown: Boolean;
FileName: array[0..fsPathName] of Char;
HasChanged, IsNewFile: Boolean;
Drawing: PCollection;
Printer: PPrinter;
PenPalette: PPenPalette; { окно палитры }
.
.
.
end;

Осталось только построить объект дочернего окна и присвоить
его PenPalette. Этому посвящен следующий раздел.

Построение окна палитры
-----------------------------------------------------------------

Объекты дочернего окна строятся обычно в конструкторах своих
порождающих окон. Аналогично тому, как это происходит при инициа-
лизации любого другого поля, вы присваиваете значения любому ука-
зателю дочернего окна. В данном случае:

constructor TStepWindows.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
.
.
.
PenPalette := New(PPenPalette, Init(@Self, 'Pan Palette');
end;

Назначение порождающего окна
-----------------------------------------------------------------

Порождающие окна автоматически управляют своими дочерними
окнами, поэтому при создании дочернего окна ему передается указа-
тель на объект порождающего окна. Поскольку порождающее окно
обычно строит свои дочерние окна, указателем порождающего окна
обычно является @Self.

Важным исключением является основное окно приложения. Так
как оно не имеет порождающего окна, конструктору основного окна
передается nil.

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

B.Pascal 7 & Objects/OW - 101 -

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



B.Pascal 7 & Objects/OW - 102 -

Создание элементов экрана
-----------------------------------------------------------------

При построении объекта дочернего окна, ObjectWindows берет
на себя функции по работе с соответствующими объекту элементами
экрана. Это обратно тому, что вы делали в шаге 6 с помощью
InitResource. Тогда вы имели созданный из ресурса элемент экрана
и связывали с ним объект, благодаря чему могли манипулировать
элементом экрана. Теперь вы создали собственный объект, и вам
нужно сообщить Windows о необходимости создания соответствующего
экранного элемента.

Когда вы в шаге 3 делали это для диалогового окна, то вызы-
вали ExecDialog. Метод TApplication создает элемент экрана и вы-
полняет режимное диалоговое окно. Соответствующим методом для не-
режимных (или безрежимных) диалоговых окон является
TApplication.MakeWindow. Основным отличием является то, что
MakeWindow не выводит автоматически создаваемый элемент экрана и
не переходит в режимное состояние.

Примечание: MakeWindow и создание элементов экрана
подробно описываются в Главе 9 "Интерфейсные объекты".

Тогда процесс построения и вывода окна состоит из следующих
трех этапов:

* Построение оконного объекта с помощью Init.

* Создание элемента экрана с помощью MakeWindow.

* Вывод окна с помощью Show.

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

В следующем разделе мы выведем дочернее окно.



B.Pascal 7 & Objects/OW - 103 -

Вывод и сокрытие палитры
-----------------------------------------------------------------

Дочерние окна, отличные от тех, которые были созданы и выве-
дены по умолчанию их порождающими окнами (этот процесс управляет-
ся с помощью EnableAutoCreate и DisableAutoCreate) в каждом ин-
терфейсном объекте. Но вы можете скрыть или вывести дочернее окно
по команде. Обе функции метода Show наследуются из
TWindowsObject.

В зависимости от передаваемых параметров метод Show выводит
либо скрывает окно. Параметр - это одна из констант sw_, опреде-
ленная в Windows. В ответ на команды меню Palette¦Show (Палит-
ра¦Вывод) или Palette¦Hide (Палитра¦Сокрытие), которые генериру-
ют, соответственно, команды cm_PalShow и cm_PalHide, TStepWindow
вызывает метод Show палитры пера (это дополняет STEP10.PAS):

procedure TStepWindow.CMPalShow(var Msg: TMessage);
begin
PenPalette^.Show(sw_ShowNA);
end;

procedure TStepWindow.CMPalHide(var Msg: TMessage);
begin
PenPalette^.Show(sw_Hide);
end;

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

------------------------------------------------------------------
Шаг 11: добавление специализированных управляющих элементов
-----------------------------------------------------------------

------------------------¬
¦ Step 1: Basic App ¦
¦ Step 2: Text ¦
¦ Step 3: Lines ¦
¦ Step 4: Menu ¦
¦ Step 5: About Box ¦
¦ Step 6: Pens ¦
¦ Step 7: Painting ¦
¦ Step 8: Streams ¦
¦ Step 9: Printing ¦
¦ Step 10: Palette ¦
¦-Step-11:-BWCC---------¦
¦ Step 12: Custom ctrls ¦
L------------------------

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

B.Pascal 7 & Objects/OW - 104 -

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

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

Палитра пера, показанная на Рис. 6.1, использует две специа-
лизированные кнопки кисти и последовательность графических изоб-
ражений, каждое из которых представляет перо, которое можно ис-
пользовать для рисования. Эти перьевые "кнопки" фактически не яв-
ляются управляющими элементами, а скорее представляют собой обра-
зы в единственным дочернем окне, которое может их идентифициро-
вать при щелчке "мышью".

В данном шаге вы добавите графические кнопки с помощью:

* добавления простых управляющих кнопок;

* реализации в программе специализированных управляющих эле-
ментов;

* определения графических изображений для кнопок.

Для всех управляющих элементов, в целом, поведение задается
типом ObjectWindows TControl и его типом-потомком, позволяющим
работать с каждым типом управляющего элемента. Например, TListBox
определяет объекты блока списка, а TEdit определяет каждый управ-
ляющий объект редактирования. Вы должны также понимать, что
TControl - это потомок TWindow.


Добавление к палитре командных кнопок
-----------------------------------------------------------------

Хотя они ведут себя идентично, между управляющими кнопками
диалоговых блоков (таких как файловое диалоговое окно) и управля-
ющими элементами окон (таких как окно палитры) имеется существен-
ное различие. Управляющие элементы диалогового блока вы можете
задать в ресурсе диалогового блока. Они не являются объектами, и
диалоговый блок, которому они принадлежат, полностью отвечает за
управление этими элементами. В Главе 11 показано, как создать из
диалоговых ресурсов свои собственные диалоговые блоки и работать
с их управляющими элементами.

Управляющие элементы окон задаются определением объекта. По-
рождающее окно управляет их поведением через методы, определенные
объектами управляющих элементов ObjectWindows. Например, чтобы

B.Pascal 7 & Objects/OW - 105 -

получить следующий элемент, который пользователь выбрал в блоке
списка, вызовите метод GetSelString объекта блока. Аналогично
оконному объекту или объекту диалогового блока, объект управляю-
щего элемента имеет соответствующий визуальный элемент.

Объект управляющего элемента и его управляющий элемент свя-
заны через поле идентификатора объекта управляющего элемента.
Каждый управляющий элемент имеет уникальный идентификатор, кото-
рый используется его порождающим окном для идентификации управля-
ющего элемента при маршрутизации управляющих событий (таких как
щелчок на элементе "мышью"). Для ясности для каждого идентифика-
тора управляющего элемента следует определить следующие констан-
ты:

const
id_Add = 101;
id_Del = 102;
MaxPens = 9;

MaxPens задает максимальное число перьев, которые будет со-
держать палитра. Значение 9 хорошо подходит для стандартного эк-
рана VGA.

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

Как и в случае других дочерних окон, часто удобно хранить
указатель объекта управляющего элемента в виде поля. Это необхо-
димо только для дочерних окон, с которыми вы позднее сможете ра-
ботать непосредственно, вызывая методы их объектов. TPenPalette
записывает каждый из этих объектов управляющих элементов в от-
дельном поле. Приведем часть описания объекта TPenPalette:

TPenPalette = object(TWindow)
AddBtn, DelBtn: PButton;
.
.
.
end;

После создания экземпляра этих дочерних объектов управляющих
элементов вы можете манипулировать ими с помощью вызовов методов.
Например, в соответствующие моменты можно разрешать или запрещать
командные кнопки, вызывая их методы Enable и Disable. Используя
метод ChildList порождающего окна, можно получить доступ к объек-
там управляющих элементов дочерних окон, не записанных в полях,
но гораздо удобнее делать это с помощью полей.


Работа с управляющими элементами
-----------------------------------------------------------------

Любой тип окна, который имеет объекты управляющих элементов

B.Pascal 7 & Objects/OW - 106 -

(или другое дочернее окно) должен определять для построения своих
объектов управляющих элементов конструктор Init. Кроме того, для
задания управляющих элементов перед выводом вы можете переопреде-
лить SetupWindow. Порождающее окно (TPenPalette) автоматически
создает и выводит все свои дочерние окна.

Приведем в качестве примера метод Init палитры пера. Первое,
что он делает - это установка собственного расположения и атрибу-
тов размера. Так как метод Init окна отвечает за задание его ат-
рибутов создания, и поскольку вместе с ним создаются управляющие
элементы окна, вы должны также в методе Init окна построить уп-
равляющие элементы. В каждом вызове конструктора первый параметр
- это @Self (порождающее окно). За ним следует идентификатор уп-
равляющего элемента.

constructor TPenPalette.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
with Attr do
begin
Style := Style or ws_Tiled or ws_SysMenu or
ws_Visible;
W := 133;
H := GetSystemMetrics(sm_CYCaction) + 42;
AddBtn := New(PButton, Init(@Self, id_Add,
'Добавить перо', 0, 0, 65, 40, True);
DelBtn := New(PButton, Init(@Self, id_Del,
'Удалить перо', 0, 0, 65, 40, False);
end;

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

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

Вызов методов Init и SetupWindow вполне достаточен для пра-
вильного вывода в окне палитры всех управляющих элементов. Коман-
дные кнопки можно будет активизировать ("нажимать"), но без ка-
ких-либо действий. В шаге 12 мы определим реакцию на события уп-
равляющего элемента.


Сокрытие вместо закрытия
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 107 -


Если вы дважды щелкните "мышью" в блоке системного меню па-
литры пера, оно исчезнет. Выбор команды Palette¦Show не может
больше выводить палитру, так как объект и его экранные элементы
уничтожены. Выводить нечего. Вы можете переопределить это, доба-
вив метод CanClose, который скрывает окно, а затем запрещает его
закрытие (см. STEP11A.PAS):

function TPenPalette.CanClose: Boolean;
begin
Show(sw_Hide);
CanClose := False;
end;

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

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


Разрешение специализированных управляющих элементов
-----------------------------------------------------------------

Как вы уже знаете, объекты управляющих элементов создают
стандартные управляющие элементы Windows. Например, только что
созданный вами объект TButton дает в результате в палитре окна
стандартную серую кнопку. Однако IDE и диалоговые блоки, создан-
ные вами из ресурсов, используют кнопки другого типа с располо-
женными на них графическими изображениями. ObjectWindows предос-
тавляет вам простой способ использования в программах командных
кнопок такого вида.

Использовать специализированные управляющие элементы Borland
для Windows (BWCC) также просто, как использование модуля. Для
этого нужно просто добавить BWCC в оператор uses основной прог-
раммы. Это немедленно дает два эффекта. Первый состоит в том, что
все стандартные диалоговые блоки (такое как файловое диалоговое
окно, которое вы уже добавили в программу Steps) используют для
таких общих элементов как кнопки OK или Cancel, а также кнопки с
зависимой и независимой фиксацией, вместо стандартных управляющих
элементов специализированные.

Примечание: Об использовании и проектировании специа-
лизированных управляющих элементов Borland рассказывается в
Главе 12.

Фактически, после добавления в оператор uses программы Steps
BWCC вы можете перекомпилировать программу и получить доступ к
диалоговым блокам. Без каких-либо других усилий вы существенно

B.Pascal 7 & Objects/OW - 108 -

улучшите внешний вид программы и ее интерфейса.

Но как насчет кнопок в палитре пера? Они были созданы из уп-
равляющих объектов с BWCC, используемых в программе, но выглядят
как обычные командные кнопки. Ответ, конечно, состоит в том, что
вы еще не определили для кнопок, графические изображения, так что
по умолчанию они просто используют метки, переданные в конструк-
торе Init. В следующем разделе вы увидите, как добавлять к специ-
ализированным управляющим элементам графические изображения.



B.Pascal 7 & Objects/OW - 109 -

Создание для командных кнопок графических изображений
-----------------------------------------------------------------

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

С этими графическими изображениями вы можете делать что
угодно. Здесь ограничений нет. Вы можете изменять цвет образа в
зависимости от состояния кнопки или перемещать образы (что обычно
используется) при нажатии, а также добавлять вокруг текста кнопки
линию из точек, когда она находится в фокусе (активна). На Рис.
6.2 показано три графических изображения для командной кнопки Add
Pen палитры пера.

-------------------¬ -------------------¬ -------------------¬
¦ ¦- ¦ ..... ¦ ¦ ..... ¦-
¦ -- Add ¦- ¦ -- : Add : ¦ ¦ -- : Add : ¦-
¦ ------ Pen ¦- ¦ ------ : Pen : ¦ ¦ ------ : Pen : ¦-
¦ -- ¦- ¦ -- ..... ¦ ¦ -- ..... ¦-
¦ ¦- ¦ ¦ ¦ ¦-
L-------------------- L------------------- L--------------------
------------------- -------------------

Рис. 6.2 Графические изображения для специализированной
кнопки.

Нумерация ресурсов графических изображений
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 110 -


Единственная сложная часть в определении графических изобра-
жений для командных кнопок - это присваивание идентификаторов ре-
сурсов. Управляющие элементы BWCC знают о том, какое графическое
изображение использовать, основываясь на идентификаторе конкрет-
ного управляющего элемента. Для командных кнопок в системах с VGA
для ресурсов используется 1000 + идентификатор для "верхнего" об-
раза, 3000 + идентификатор для "нижнего" образа и 5000 + иденти-
фикатор для образа в фокусе.

Примечание: В системах с EGA используются, соответс-
твенно, ресурсы 2000 + идентификатор, 4000 + идентификатор
и 6000 + идентификатор.

Так как командная кнопка Add Pen имеет идентификатор 101
(id_Add), разрешение использования BWCC принимает вид ресурсов
1101, 3101 и 5101. В программе STEP11B.PAS, для доступа к специа-
лизированными графическим изображениям, для командных кнопок Add
Pen и Del Pen, используется директива:

{$R PENTAL.RES}



B.Pascal 7 & Objects/OW - 111 -

------------------------------------------------------------------
Шаг 12: Создание специализированного управляющего элемента окна
-----------------------------------------------------------------

------------------------¬
¦ Step 1: Basic App ¦
¦ Step 2: Text ¦
¦ Step 3: Lines ¦
¦ Step 4: Menu ¦
¦ Step 5: About Box ¦
¦ Step 6: Pens ¦
¦ Step 7: Painting ¦
¦ Step 8: Streams ¦
¦ Step 9: Printing ¦
¦ Step 10: Palette ¦
¦ Step 11: BWCC ¦
¦-Step-12:-Custom-ctrls-¦
L------------------------

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

На этом шаге вы сделаете следующее:

* реализуете динамическое изменение размера окна палитры;

* зададите реакцию на уведомляющие сообщения от управляющих
элементов;

* создадите объект палитры с несколькими областями.

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

Так как каждое перо, которое вы сохраняете в палитре, имеет
один и тот же размер (40 элементов изображения высотой и 128 ши-
риной), вам нужно убедиться, что окно палитры может увеличиваться
и сжиматься на этот размер каждый раз, когда вы удаляете перо.
Объект TPenPalette определяет два метода, которые позволяют это
делать: Grow и Shrink.

procedure TPenPalette.Grow
var WindowRect: TRect;
begin
GetWindowRect(HWindow, WindowRect);
with WindowRect do
MoveWindow(HWindow, left, top, right - left,
bottom - top + 40, True);
end;

procedure TPenPalette.Shrink;
var WindowRect: TRect;

B.Pascal 7 & Objects/OW - 112 -

begin
GetWindowRect(HWindow, WindowRect);
with WindowRect do
MoveWindow(HWindow, left, top, right - left,
bottom - top - 40, True);
end;

Оба метода находят координаты границ окна, модифицируют их и
сообщают окну, что нужно использовать новые координаты границ.
Функция API GetWindowRect возвращает структуру TRect, содержащую
верхнюю, нижнюю, левую и правую координату. Grow добавляет в ниж-
нюю область окна 40 элементов изображения, а Shink вычитает тот
же объем.

В следующем разделе вы узнаете, как вызывать методы Grow и
Shrink в ответ на нажатие командных кнопок Add Pen и Del Pen.

Реакция на события управляющих элементов
-----------------------------------------------------------------

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

Пока командные кнопки выводятся в окне палитры, но щелчок
кнопкой "мыши" не дает никакого эффекта. Щелчок и выбор "мышью"
являются событиями управляющего элемента. Они аналогичны событиям
меню, на которые вы отвечали в шаге 4.

Вы отвечали на события меню, определяя методы реакции на ко-
манды. Что-то аналогичное нужно делать с сообщениями управляющих
элементов. События управляющих элементов создают сообщения (на
основе дочернего идентификатора), аналогичные командным сообщени-
ям, но вместо идентификатора меню содержащие идентификатор управ-
ляющего элемента. Для идентификации заголовка метода на основе
дочернего идентификатора используйте сумму идентификаторов уп-
равляющего элемента и констант id_First.

Примечание: Подробнее о командных сообщениях и уведом-
ляющих сообщениях управляющих элементов рассказывается в
Главе 16 "Сообщения окон".

Имена методов реакции на сообщения управляющих элементов
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 113 -

вать, имеют идентификаторы id_Add и id_Del, TPenPalette нужны ме-
тоды с именами IDAdd и IDDel.

TPenPalette = object(TWindow)
AddBtn, DelBtn: PBitButton;
constructor Init(AParent: PWindowsObject; ATitle: PChar);
procedure Grow;
procedure SetupWindow; virtual;
procedure Shrink;
procedure IDAdd(var Msg: TMessage); virtual
id_First + id_Add;
procedure IDDel(var Msg: TMessage); virtual
id_First + id_Del;
end;

Теперь для выполнения соответствующих действий в ответ на
командные кнопки осталось только определить методы IDAdd и IDDel.
Пока что IDAdd должен просто вызывать увеличение окна, а IDDel -
его сжатие

procedure TPenPalette.IDAdd(var Msg: TMessage);
begin
Grow;
end;

procedure TPenPalette.IDDel(var Msg: TMessage);
begin
Shrink;
end;

Примечание: Это дополняет содержимое файла
STEP12A.PAS.



B.Pascal 7 & Objects/OW - 114 -

Добавление "кнопок" палитры
-----------------------------------------------------------------

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

В данном разделе вы сделаете следующее:

* определите объект палитры пера;

* выберете перья по щелчку кнопкой "мыши".


Определение объекта палитры
-----------------------------------------------------------------

Так как окно палитры пера может изменять свой размер, палит-
ра в окне может фактически оставаться фиксированной. Чтобы пока-
зать только часть палитры, в которой отображаются перья, вы може-
те использовать возможности отсечения Windows.

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

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

TPenPic = object(TWindow)
PenSet: PCollection;
CurrentPen: Integer;
constructor Init(AParent: PWindowsObject);
destructor Done: virtual;
procedure Paint(PaintDC: HDC; var PaintInfo:
TPaintStruct); virtual;
procedure AddPen(APen: PPen);
procedure DeletePen;
procedure SetupWindow; virtual;
procedure WMLButtonDown(var Msg: TMessage);
virtual wm_First + wm_LButtonDown;
private
UpPic, DownPic: HBitMap;
end;

Объекту TPenPic не требуется очень много методов. Он имеет
простой конструктор для создания набора перьев и деструктор для
их уничтожения. Метод SetupWindow просто перемещает палитру внут-
ри ее порождающего окна. AddPen и DeletePen включают перо в набор
и удаляют перо из набора, а WMLButtonDown интерпретирует щелчки

B.Pascal 7 & Objects/OW - 115 -

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

Отметим также, что TPenPic является потомком TWindow, а не
TControl. Хотя поведение вашего нового объекта во многом напоми-
нает поведение управляющего элемента окна, он должен быть произ-
водным от TWindow, так как TControl работает только со стандарт-
ными управляющими элементами, такими как "нажимаемые" командные
кнопки и полосы прокрутки. При создании собственных управляющих
элементов нужно начинать с TWindow.



B.Pascal 7 & Objects/OW - 116 -

Создание и уничтожение палитры
-----------------------------------------------------------------

Построение и уничтожение объекта палитры выполняется доста-
точно просто. Конструктор Init вызывает TWindow.Init, затем изме-
няет стиль окна (чтобы оно стало видимым дочерним окном). PenSet
инициализируется как набор фиксированного размера, достаточно
большой, чтобы содержать максимальное число заданных константой
MaxPens перьев, и не возрастающий. Для текущего выбранного пера
CurrentPen устанавливается в -1. Это означает, что выбранного пе-
ра нет.

Наконец, Init загружает в UpPic и DownPic два графических
образа. Они используются в качестве фона для каждого пера палит-
ры. DownPic рисуется за выбранным пером, а UpPic - в качестве фо-
на других перьев.

-------------------
--------------------¬ -------------------¬
-¦ ¦ ¦ ¦-
-¦ ¦ ¦ ¦-
-¦ ¦ ¦ ¦-
L------------------- L--------------------
-------------------

Рис. 6.3 Фоновые образы палитры пера.

Деструктор Done перед вызовом наследуемого деструктора Done
отменяет графические образы. Вызов DeleteObject для уничтожения
графических образов имеет важное значение. Подобно контексту
дисплея, графические образы являются ресурсами Windows, поддержи-
ваемыми в ограниченной памяти Windows. Если размещаете их в памя-
ти Windows и не удаляете, то ваша программа (и другие работающие
параллельно с ней программы) потеряют доступ к этой памяти.

Init и Done объекта палитры выглядят следующим образом:

constructor TPenPic.Init(AParent: PWindowsObject);
begin
inherited Init(AParent, nil);
AttrStyle := ws_Child or ws_Visible;
PenSet := New(PCollection, Init(MaxPens, 0));
CurrentPen := -1;
UpPic := LoadBitMap(HInstance, 'PAL_UP');
DownPic := LoadBitmap(HInstance, 'PAL_DOWN');
end;

destructor TPenPic.Done;
begin
DeleteObject(UpPic);
DeleteObject(DownPic);
Dispose(PenSet, Down);
inherites Done;

B.Pascal 7 & Objects/OW - 117 -

end;

Размещение в порождающем окне
-----------------------------------------------------------------

Как вы могли заметить, TPenPic не задает свою позицию в
конструкторе так, как это делают большинство управляющих элемен-
тов. Причина здесь в том, что вы не можете полагаться на коорди-
наты окна, пока оно не будет реально существовать. TPenPalette
обходит эту проблему, создавая свои объекты кнопок путем вызова
для определения высоты заголовка окна функции API
GetSystemMetrics. Хотя это будет работать, существует и другой
подход.

Вместо позиционирования палитры в конкретное место порождаю-
щего окна вы можете поместить его в определенную позицию в порож-
дающей области клиента. Таким образом, если вы добавляете меню
или изменяете рамку, либо выполняете вне окна какое-либо другое
изменение, ваш объект палитры все равно будет правильно позицио-
нирован.

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

procedure TPenPic.SetupWindow;
var ClientRect: TRect;
begin
inherited SetupWindow;
GetClientRect(Parent^.HWindow, ClientRect);
with ClientRect do
MoveWindow(HWindow, 1, bottom - top + 1, 128,
40 * MaxPens, False;
end;

Для возврата координат области клиента окна палитры метод
TPicPen использует функцию API Windows GwetClientRect. Затем он
перепозиционируется с помощью MoveWindow непосредственно под объ-
екты кнопок, задавая высоту, достаточную для размещения всех
перьев в наборе. Заметим, что последний параметр MoveWindow - это
значение типа Boolean, указывающее, следует ли выполнять повтор-
ное отображение окна после перемещения. Так как палитра на экран
пока не выводилась, то заново отображать ее не имеет смысла, поэ-
тому TPenPic.SetupWindow передает значение False.



B.Pascal 7 & Objects/OW - 118 -

Добавление и удаление перьев
-----------------------------------------------------------------

В последнем разделе вы отвечали на сообщения от Add Pen (До-
бавить перо) и Del Pen (Удалить перо) изменением размера окна па-
литры. Теперь настало время изменить эту реакцию и фактически до-
бавлять или удалять перья из палитры, что в свою очередь указыва-
ет окну палитры на необходимость изменения размера. Вместо вызова
собственных методов Grow и Shrink методы объекта палитры AddPen и
DeletePen должны вызывать соответственно, методы IDAdd и IDDel
в TPenPalette.

procedure TPenPalette.IDAdd(var Msg: TMessage);
begin
Pens^.AddPen(CommonPen);
end;

procedure TPenPalette.IDDel(var Msg: TMessage);
begin
Pens^.DeletePen;
end;

Метод AddPen воспринимает передаваемое перо, копирует его в
набор и отмечает перо, как текущее выбранное. Затем он разрешает
кнопку Del Pen в окне палитры пера, запрещает кнопку Add Pen, ес-
ли набор полон, и сообщает порождающему окну о необходимости уве-
личения размера, чтобы поместить новое перо.

procedure TPenPic.AddPen(APen: PPen);
begin
CurrentPen := PenSet^.Count;
with APen^ do PenSet^.Insert(New(PPen, Init(Style, With,
Color)));
with PPenPalette(Parent)^ do
begin
DelBtn^.Enable;
if PenSet^.Count >= MaxPens tnen
AddBtn^.Disable;
Grow;
end;
end;

Примечание: Чтобы использовать преимущества средств,
специфических для TPenPAlette, TPenPic может выполнять при-
ведение типа поля Parent. Большинство оконных объектов не
связаны так жестко с конкретным порождающим типом, и поэто-
му не должны делать никаких предположений относительно типа
порождающих их окон.

Метод DeletePen по существу изменяет действия AddPen на об-
ратные. При наличии выбранного в палитре пера оно удаляется из
набора, а набор уплотняется таким образом, чтобы перья размеща-
лись непрерывно. Затем он указывает, что в данный момент выбран-

B.Pascal 7 & Objects/OW - 119 -

ных перьев нет (поскольку выбранное перо только что удалено) и
запрещает командную кнопку Del Pen, так как Del Pen работает с
выбранным пером. Далее он разрешает кнопку Add Pen, поскольку
удаление пера автоматически освобождает место для по крайней мере
еще одного пера. Наконец, он сообщает порождающему окну на необ-
ходимость уменьшения его размера (так выводить теперь нужно мень-
ше перьев).

procedure TPenPic.DeletePen;
begin
if CurrentPen > -1 then
begin
PenSet^.AtFree(CurrentPen);
PenSet^.Pack;
CurrentPen := -1;
with PPenPelette(Parent)^ do
begin
AddBtn^.Enable;
DelBtn^.Disable;
Shrink;
end;
end;
end;

Заметим, что AddPen и DeletePen используют преимущества того
факта, что окна палитры пера для упрощения связи с методами имеет
указатели на свои командные кнопки. Если бы TPenPalette не имел
полей AddBtn и DelBtn, то объекту палитры пришлось бы искать их
по идентификаторам и посылать им сообщения, либо нужно было бы
послать сообщение порождающему окну, которое в свою очередь долж-
но каким-то образом связываться с командными кнопками.



B.Pascal 7 & Objects/OW - 120 -

Отображение содержимого палитры
-----------------------------------------------------------------

За все, что мы насоздавали в объекте палитры, приходится
расплачиваться, когда приходит момент отображать ее на экране.
Поскольку перья хранятся в наборе, для отображения каждого пера
вы легко можете выполнять итерацию. В самом деле, метод Paint
состоит только из инициализации локальной переменной-счетчика, а
затем выполняет итерацию по набору с помощью ForEach:

procedure TPenPic.Paint(PaintDC: HDC;
var PaintInfo: TPaintStruct);
var PenCount: Integer;

procedure ShowPen(P: PPen); far;
var
MemDC: HDC;
TBitmap: HBitmap;
begin
MemDC := CreateCompatibleDC(PaintDC);
Inc(PenCount);
if PenCount = CurrentPen then
TheBitmap = DownPic;
else TheBitmap := UpPic;
SelectObject(MemDC, TheBitmap);
BitBlt(PaintDC, 0, PenCount * 40, 128, 40, MemDC, 0,
0, SrcCopy);
P^.Select(PaintDC);
MoveTo(PaintDC, 15, PenCount * 40 + 20);
LineTo(PaintDC, 115, PenCount * 40 + 20);
P^.Delete;
DeleteDC(MemDC);
end;

begin
PenCount := -1;
PenSet^.ForEach(@ShowPen);
end;

Наиболее интересная часть содержится не в Paint, а во вло-
женной процедуре ShowPen, которая вызывается для каждого пера в
палитре. На самом деле ShowPen состоит из двух различных частей.
Первая рисует графическое изображение фона, а вторая (которая уже
должна быть вам достаточно знакома) использует объект пера для
изображения по этому фону образца линии.

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

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

B.Pascal 7 & Objects/OW - 121 -

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

Метод CreateMemoryDC создает пустой контекст устройства па-
мяти, совместимый с текущим PaintDC. Затем, в зависимости от то-
го, является ли данное конкретное перо выбранным, ShowPen выбира-
ет в контексте устройства графические образы UpPic или DownPic.
Заметим, что в контексте устройства памяти графический образ
интерпретируется аналогично любому другому изобразительному
средству. Наконец, функция BitBlt копирует заданную часть кон-
текста устройства памяти в PaintDC. Заметим, что контекст уст-
ройства памяти требуется уничтожать.

После того как фон будет на месте, ShowPen использует ShowTo
и LineTo аналогично тому, как это делается при рисовании непос-
редственно в окне.

Выбор перьев с помощью "мыши"
-----------------------------------------------------------------

Наконец. TPenPic обеспечивает реакцию на щелчок в нарисован-
ной области кнопкой "мыши". Заметим, что хотя размер объекта па-
литры никогда не изменяется, он получает сообщение от щелчков
"мышью" в области, фактически показываемой на экране. Палитра от-
секается рамкой окна палитры. Это означает, что вы можете щелкать
кнопкой "мыши" только непосредственно в палитре.

Поскольку каждый элемент в палитре имеет один и тот же раз-
мер, WMLButton для определения того, в каком графическом образе
была нажата кнопка "мыши", может просто разделить y-координату
щелчка "мыши" (которая поступает в LParamHi) на 40 (размер каждо-
го графического изображения). Затем он делает перо, на котором
была нажата кнопка "мыши" текущим и задает в качестве пера для
рисования копию выбранного пера палитры. Поскольку теперь есть
выбранное перо, он разрешает кнопку Del Pen в окне палитры, затем
запрещает палитру для обеспечения ее повторного отображения для
того, чтобы показать новый выбор.

Код для WMLButtonDown имеет следующий вид (это дополняет
текст STEP12B.PAS):

procedure TPenPic.WMLButtonDwon(var Msg: TMessage);
begin
CurrentPen := Msg.LParamHi div 40;
if CurrentPen <> nil then Dispose(CurrentPen, Done);
with PPen(PenSet^.At(CurrentPen))^ do
CurrentPen := New(PPen, Init(Style, With, Color));
PPenPalette(Parent)^.DelBlt^.Enable;
InvalidateRect(HWindow, nil, False);
end;

Что дальше?

B.Pascal 7 & Objects/OW - 122 -

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

Есть много дополнений и изменений, которые вы можете внести
в программу Steps, чтобы сделать ее более полезной. Версию
программы Steps, которая включает в себя эти изменения, вы можете
найти в файле GRAFFITI.PAS.

Программа Graffiti содержит следующие изменения:

* Многодокументальный интерфейс (MDI).

* Сглаживание линий.

* Отмена.

* Улучшает поведение окна палитры.

* Прокрутка.

Многодокументальный интерфейс
-----------------------------------------------------------------

TStepWindow может очень легко работать в качестве дочернего
окна MDI. Фактически с небольшими изменениями программа Graffiti
использует в качестве своих дочерних окон те же окна, что Steps
использует для основного окна. Так как владельцем окна палитры
пера является объект TStepWindow, каждый отдельный рисунок имеет
свой собственный отличный набор перьев. О многодокументальном ин-
терфейсе рассказывается в Главе 14 "Объекты MDI").

Сглаживание линий
-----------------------------------------------------------------

Для сложных рисунков со многими длинными линиями повторное
отображение рисунка может потребовать много времени. Graffiti ис-
пользует одно из преимуществ графический функций GDI - функцию
PolyLine, которая рисует сегменты каждой линии сразу, а не по од-
ному. Эффектом будет более быстрое и плавное отображение окна.

Отмена
-----------------------------------------------------------------

Поскольку рисунок состоит из наборов линий, для стирания
последней нарисованной линии легко использовать методы наборов.
Graffiti связывает элемент меню Edit¦Undo (Редактирование¦Отмена)
с набором линий метода AtDelete, удаляя последнюю линию в наборе,
которая является также последней нарисованной линией. Повторяя
удаление последней линии в наборе, вы можно эффективно отменять
все изображение.

Хотя программа Graffiti этого не делает, вы можете добавить
также функцию Redo (Возобновление), сохраняя удаленные линии в
другом наборе, и перемещая их по одной в набор отображаемых ли-

B.Pascal 7 & Objects/OW - 123 -

ний, либо даже в другой рисунок.


Поведение палитры
-----------------------------------------------------------------

Вы можете также отметить, что при щелчке "мышью" между па-
литрой и основным окном, окно, где вы нажимаете кнопку, становит-
ся активным (получает активную рамку), а другие окна становятся
неактивными. Если вы часто перемещаетесь между двумя окнами (что
может иметь место при работе с палитрой), это может показаться
весьма раздражающим. Чтобы предотвратить это явление, вам нужно
перехватывать передачу в окна сообщений sm_NCActivate, и когда
параметр WParam сообщений равен 0 (попытка деактивизации рамки),
вы можете изменить его на 1 (активизация рамки):

procedure TPenPalette.WVNCActivate(var Msg: TMessage);
begin
if Msg.WParam = 0 then Msg.WParam := 1;
DefWndProc(Msg);
end;

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

Прокрутка
-----------------------------------------------------------------

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



B.Pascal 7 & Objects/OW - 124 -

------------------------------------------------------------------
Часть 2. Использование ObjectWindows
-----------------------------------------------------------------


Глава 7. Иерархия ObjectWindows
-----------------------------------------------------------------

ObjectWindows представляет собой исчерпывающий набор объек-
тов, облегчающий разработку программ для Microsoft Windows на
Паскале. В данной главе вы найдете обзор иерархии объектов
ObjectWindows. В остальных главах данной части дается детальное
описание различных частей иерархии.

Кроме описания иерархии объектов, в данной главе описываются
основные принципы программирования для операционной среды
Windows, включая вызов API Windows.

Соглашения Windows
-----------------------------------------------------------------

Соглашения по именам ObjectWindows обеспечивают ясность и
содержательность имен.

Имена объектов
-----------------------------------------------------------------

Имена всех объектный типов, предусмотренных в ObjectWindows,
начинаются с буквы T. Например, объекты диалоговых окон имеют тип
TDialog. Для каждого определения объектного типа имеется соот-
ветствующий ссылочный тип, начинающийся с P. Например, указатель
на TDialogh имеет тип PDialog. В примерах данного руководства бу-
дут создаваться динамические экземпляры объектов, например, с по-
мощью PDialog позволяет разместить объекты TDialog в динамически
распределяемой области памяти.

Имена методов
-----------------------------------------------------------------

Методы реакции на сообщения называются по именам сообщений,
на которые они отвечают, но без подчеркиваний. Например, метод,
отвечающий на сообщение wm_KeyDown будет называться WMKeyDown.



B.Pascal 7 & Objects/OW - 125 -

Обзор объектов
-----------------------------------------------------------------

Иерархия объектов
-----------------------------------------------------------------

ObjectWindows - это иерархия объектных типов, которые вы мо-
жете использовать для работы с большинством обычных задач в при-
ложении ObjectWindows. Схема объектов пользовательского интерфей-
са библиотеки показана на Рис. 7.1. На Рис. 7.2 представлены объ-
екты иерархии, используемые для управления данными и проверки их
допустимости.

-----------------¬
¦ TObject ¦
L-------T---------
-----+--------------T----------------------T------------¬
--------+--------¬ ---------+-------¬ --------+--------¬ ¦
¦ TPrintout ¦ ¦ TPrinter ¦ ¦ TWindowsObject ¦ ¦
L-------T--------- L----------------- L-------T--------- ¦
+-------------------¬ ¦ ¦
--------+--------¬ ---------+-------¬ ------------- ¦
¦ TEditPrintout ¦ ¦ TWindowPrintout¦ ¦ -------------+
L----------------- L----------------- ¦ ¦ ¦
¦ --------+--------¬ ¦
---------------------T----------- ¦ TApplication ¦ ¦
¦ ¦ L----------------- ¦
-------+---------¬ ---------+-------¬ --------------
¦ TDialog ¦ ¦ TWindow ¦ ¦
L------T---------- L--------T-------- --------+--------¬
¦ ¦ ¦ TScroller ¦
¦ ¦ L-----------------
¦ L----------------------------¬
+-------------------T-----------¬ ¦
-------+---------¬ --------+--------¬ ¦ ¦
¦ TFileDialog ¦ ¦ TInputDialog ¦ ¦ ¦
L----------------- L----------------- ¦ ¦
-----------------------T--------- ¦
-------+------------¬ ¦ ¦
¦TPrinterAbortDialog¦ +------------¬ ¦
L-------------------- ¦ ¦ ¦
¦ ---------+-------¬ ¦
----------------------+ ¦ TPrintDialog ¦ ¦
--------+--------¬ ¦ L----------------- ¦
¦TPrinterSetupDlg¦ L------------¬ ¦
L----------------- ¦ ¦
---------+-------¬ ¦
¦ TDlgWindow ¦ ¦
L----------------- ¦


B.Pascal 7 & Objects/OW - 126 -


¦
-------------------T------------------T----------+
--------+--------¬ --------+--------¬ --------+--------¬ ¦
¦ TControl ¦ ¦ TMDIClient ¦ ¦ TMDIWindow ¦ ¦
L-------T--------- L----------------- L----------------- ¦
+------------------T-----------¬ --------
--------+--------¬ --------+--------¬ ¦ --------+--------¬
¦ TButton ¦ ¦ TScrollBar ¦ ¦ ¦ TEditWindow ¦
L-------T--------- L----------------- ¦ L-------T---------
--------+--------¬ ¦ --------+--------¬
¦ TCheckBox ¦ ------------+ ¦ TFileWindow ¦
L-------T--------- ¦ ¦ L-----------------
--------+--------¬ --------+--------¬ +----------¬
¦ TRadioButton ¦ ¦ TStatic ¦ ¦ ¦
L----------------- L-------T--------- ¦ ¦
¦ ¦ --------+--------¬
--------+--------¬ ¦ ¦ TListBox ¦
¦ TEdit ¦ ¦ L-------T---------
L----------------- ¦ ¦
¦ --------+--------¬
------------- ¦ TComboBox ¦
¦ L-----------------
--------+--------¬
¦ TGroupBox ¦
L-----------------

Модуль OPRINTER: Модуль OWINDOWS: Модуль OSTDDLGS:

TPrinout TWindow TInputDialog
TPtinter TAppication TInputDialog
TEditPrintout TScroller
TWindowPrintout
TPrinterAbortDlg
TPrintDialog
TPrinterSetup

Модуль ODUIALOGS: Модуль OSTDWNDS:

TDialog TEditWindow
TDlgWindow TFileWindow
TButton
TScrollBar
TCheckBox
TRadioButton
TControl
TStatic
TEdit
TListBox
TComboBox
TGroupBox
Рис. 7.1. Иерархия объектных типов ObjectWindows.


B.Pascal 7 & Objects/OW - 127 -


-----------------¬
¦ TObject ¦
L-------T---------
-----+--------------T--------------------¬
--------+--------¬ --------+--------¬ --------+--------¬
¦ TValidator ¦ ¦ TCollection ¦ ¦ TStream ¦
L-------T--------- L----------------- L---------T-------
+---------------------T------------------¬ L--------¬
--------+-----------¬ --------+--------¬ --------+--------¬ ¦
¦TPXPictureValidator¦ ¦TFilterValidator¦ ¦TLookupValidator¦ ¦
L-------------------- L-------T--------- L-------T--------- ¦
--------+---------¬ ¦ ¦
¦ TRangeValidator ¦ ---- ¦
L------------------ ¦ ¦
-----------+-----------¬ ¦
¦TStringLookupValidator¦ ¦
L----------------------- ¦
--------------------T-------------------T------------
--------+--------¬ --------+--------¬ --------+--------¬
¦ TMemoryStream ¦ ¦ TDosStream ¦ ¦ TEmsStream ¦
L----------------- L-------T--------- L-----------------
--------+--------¬
¦ TBufStream ¦
L-----------------

Рис. 7.2 Иерархия наборов, потоков и проверки допустимости.

Модуль OBJECTS: Модуль VALIDATE:

TObject TValidator
TCollection TPXPictureValidator
TSortedCollection TFilterValidator
TStrCollection TRangeValidator
TStringCollection TLookupValidator
TStream TStrongLookupValidator
TMemoryStream
TEmsStream
TDosStream
TBufStream

Базовый объект

TObject - это базовый объектный тип, общий предок всех объ-
ектов ObjectWindows. Он определяет рудиментарный конструктор и
деструктор. Потоки ObjectWindows требует, чтобы записанные объек-
ты были потомками TObject.

TApplication

Этот тип определяет поведение, необходимое для всех приложе-
ний ObjectWindows. Каждое приложение ObjectWindows, которое вы
пишете, будет определять объектный тип приложения, производный от

B.Pascal 7 & Objects/OW - 128 -

TApplication. Объекты приложения подробно описываются в Главе 8
"Объекты приложения".

Интерфейсные объекты

Остальные объекты в иерархии ObjectWindows классифицируются
в общем случае как интерфейсные объекты. Они являются интерфейс-
ными в том смысле, что представляют элементы и пользовательском
интерфейсе Windows и служат интерфейсом между кодом вашей прик-
ладной программы и операционной средой Windows. Интерфейсные объ-
екты описываются в Главе 9.

Объекты Windows

Объекты Windows представляются не только знакомыми окнами
среды Windows, но и большинством визуальных инструментов операци-
онной среды, такими как управляющие элементы.

Объекты диалоговых блоков

Объекты диалоговых блоков (окон) обеспечивают временные ок-
на для обслуживания специальных функций ввода и вывода. В общем
случае они включат в себя текст и управляющие элемента, такие как
командные кнопки, блоки списка и полосы прокрутки. Об объектах
диалоговых блоков подробно рассказывается в Главе 11.

Объекты управляющих элементов

В диалоговых блоках и некоторых окнах управляющие элементы
позволяют пользователям вводить данные и выбирать параметры. Объ-
екты управляющих элементов обеспечивают согласованные и простые
средства для работы со всеми типами управляющих элементов, опре-
деленных в Windows. Объекты управляющих элементов подробно описы-
ваются в Главе 12.

Объекты MDI

Windows реализует стандарт для работы с несколькими докумен-
тами в рамках одного окна, которое называется множественным доку-
ментальным интерфейсом (MDI). ObjectWindows обеспечивает средства
для установки окон MDI и работы с ними. Объекты MDI подробно опи-
сываются в Главе 14.

Объекты проверки допустимости

ObjectWindows содержит полный набор объектов проверки допус-
тимости данных, которые позволяют проверять допустимость данных,
введенных пользователем, при выходе пользователя из поля или ког-
да пользователь завершает работу с окном. Проверка допустимости
данных описывается в Главе 13.

Объекты принтера


B.Pascal 7 & Objects/OW - 129 -

Для работы с печатью документов или печати содержимого окна
ObjectWindows предусматривает соответствующие объекты. О том, как
использовать эти объекты, рассказывается в Главе 15.

Объекты наборов и потоков

Модуль Object включает в себя многочисленные объекты, реали-
зующие гибкие структуры данных и потоки, позволяющие считывать и
записывать объекты. Наборы описываются в Главе 19, а потоки - в
Главе 20.



B.Pascal 7 & Objects/OW - 130 -

Файлы ObjectWindows
-----------------------------------------------------------------

Перечисленные выше типы ObjectWindows реализует в скомпили-
рованных модулях. В данном разделе кратко описывается содержимое
поставляемых модулей. В каждом приложении ObjectWindows требуется
только модуль OWindows.

В данной версии ObjectWindows различные части иерархии объ-
ектов разбивают различные части иерархии объектов по отдельным
моделям. Чтобы перекомпилировать код ObjectWindows более ранних
версий, в общем случае нужно изменить все ссылки на модуль
WObjects на OWindows и добавить к программам и модулям, использу-
ющим наборы и потоки или диалоговые блоки, соответственно Objects
и ODialogs.

В данную версию ObjectWindows добавлены также новые модули
для печати, проверки данных, специализированных управляющих эле-
ментов Borland и поддержки Windows 3.1.

В Таблице 7.1 перечислены модули, составляющие интерфейс
ObjectWindows и AOPI Windows 3.0. Модули, поддерживающие расшире-
ния Windows 3.1, представлены в Таблице 7.2.

Модули для ObjectWindows и API Windows Таблицы 7.1
-----------------T----------------------------------------------¬
¦ Модуль ¦ Содержимое ¦
+----------------+----------------------------------------------+
¦ Objects ¦ Базовый объект TObject, наборы, потоки. ¦
¦ OWindows ¦ Приложения, окна, полосы прокрутки, окна MDI.¦
¦ ODialogs ¦ Диалоговые блоки, диалоговые окна, управляю-¦
¦ ¦ щие элементы. ¦
¦ OPrinter ¦ Печать, специальные распечатки. ¦
¦ Validate ¦ Проверка допустимости данных. ¦
¦ BWCC ¦ Специализированные управляющие элементы фирмы¦
¦ ¦ Borland. ¦
¦ OStdDlgs ¦ Диалоговые блоки имен файлов, однострочный¦
¦ ¦ ввод. ¦
¦ OStdWnds ¦ Окна текстового редактора, окна редактора¦
¦ ¦ файлов. ¦
¦ WinTypes ¦ Все типы, используемые подпрограммами API¦
¦ ¦ Windows 3.0, включая записи, стили, сообщений¦
¦ ¦ и флаги. ¦
¦ WinProcs ¦ Описания процедур и функций для API Windows¦
¦ ¦ 3.0. ¦
L----------------+-----------------------------------------------



B.Pascal 7 & Objects/OW - 131 -

Файлы ресурсов
-----------------------------------------------------------------

Модули OStdDlgs, OStdWnds и OPrinter имеют связанные с ними
файлы ресурсов. Ресурс модуля находится в файле с именем, эквива-
лентным имени модуля, и расширением .RES. Ресурсы автоматически
включаются при использовании соответствующих модулей, так что
программа, которая использует модуль OstdDlgs, будет автоматичес-
ки иметь доступ к ресурсам в OSTDDLGS.RES.

Файлы Windows 3.1
-----------------------------------------------------------------

Кроме стандартных модулей API Windows 3.0, вы можете писать
программы, использующие преимущества средств, добавленных в вер-
сию 3.1 Windows. Каждая из 11 DLL Windows 3.1 имеет соответствую-
щий модуль:

Модули для доступа к средствам Windows 3.1 Таблица 7.2
-----------------T----------------------------------------------¬
¦ Модуль ¦ Средство ¦
+----------------+----------------------------------------------+
¦ ComDlg ¦ Общие диалоговые блоки. ¦
¦ DDTML ¦ Сообщения динамического обмена данными. ¦
¦ Dlgs ¦ Константы диалогового блока. ¦
¦ LZExpand ¦ Расширения файла LZ. ¦
¦ MMSystem ¦ Расширения мультимедиа. ¦
¦ OLE ¦ Компоновка и встраивание объектов (OLE). ¦
¦ ShellAPI ¦ Оболочка API Windows. ¦
¦ Stress ¦ Строгая проверка типов. ¦
¦ ToolHelp ¦ Отладка и другие инструментальные средства. ¦
¦ Ver ¦ Версии. ¦
¦ Win31 ¦ Расширения Windows 3.1. ¦
L----------------+-----------------------------------------------



B.Pascal 7 & Objects/OW - 132 -

Взаимодействие с Windows
-----------------------------------------------------------------

ObjectWindows избавляет вас от многих утомительных и запу-
танных частей Windows, но иногда возникает необходимость в непос-
редственном взаимодействии с Windows (например, когда вы хотите
переопределить некоторое заданное в Windows поведение или выйти
за рамки того, что инкапсулировано в ObjectWindows).

Существует два способа, с помощью которых вы можете взаимо-
действовать с ObjectWindows: вызов ее функций API и получение со-
общений. В данном разделе описываются функции API. Об обработке
сообщений рассказывается в Главе 16 "Сообщения Windows".

Функции API Windows
-----------------------------------------------------------------

Функциональные возможности Windows заключены в ее около 600
функций. Каждая функция имеет имя. Взаимодействовать с операцион-
ной средой Windows, модифицировать ее отображение или действие в
ответ на ввод пользователя можно с помощью вызова функций API.
Однако с помощью ObjectWindows вы можете создавать окна, выводить
диалоговые блоки и манипулировать управляющими элементами, не вы-
зывая функций Windows. Как все это работает?

Вызов в ObjectWindows функций API
-----------------------------------------------------------------

Методы ObjectWindows вызывают функции API. Но ObjectWindows
- это не дублируемые функциональные возможности; она предоставля-
ет в новом пакете объектно-ориентированной библиотеки функции
Windows, ее прикладной программный интерфейс (API). Кроме того,
ObjectWindows значительно упрощает задачи спецификации многочис-
ленных параметров, требуемых в функциях Windows. Часто ObjectWin-
dows автоматически подставляет параметры, такие как описатели
окон и идентификаторы дочерних окон, которые хранятся в интер-
фейсных объектах в виде полей.

Например, многие функции Windows для задания окна, с которым
они должны работать, используют описатели окна, и эти функции вы-
зываются обычно из методов оконного объекта. Объекты содержат в
поле HWindow описатель соответствующего окна и может передавать
его, освобождая вас от необходимости каждый раз задавать описа-
тель. Таким образом, объектные типы ObjectWindows служат объект-
но-ориентированным слоем, реализованным с помощью вызовов необъ-
ектно-ориентированных функций API.



B.Pascal 7 & Objects/OW - 133 -

Доступ к функциям API
-----------------------------------------------------------------

Чтобы из приложения ObjectWindows обратиться непосредствен-
но к функциям API, вы должны использовать модуль WinProcs.
WinProcs определяет для каждой функции Windows заголовок процеду-
ры или функции Паскаля, что позволяет вам вызывать функции
Windows как любую подпрограмму на Паскале. Перечень заголовков
этих функций вы можете найти в файле WINPROCS.PAS или в оператив-
ном справочнике Help.

Константы Windows
-----------------------------------------------------------------

Функции Windows требуют от вас передачи в качестве аргумен-
тов разнообразных констант типа Word или Longint. Эти константы
представляют стили окна, диалогового блока или управляющего эле-
мента, а также возвращаемые значение и др. Если в программе ис-
пользуются данные константы, она становится более читаемой, обс-
луживаемой и будет более независимой от изменений в последующих
версиях Windows, чем программы, использующие числа. Определенные
в модуле WinTypes константы описываются в Главе 21 "Справочник по
ObjectWindows".

Записи данных Windows
-----------------------------------------------------------------

Некоторые функции Windows требуют более сложных структур
данных, например, шрифтов (TLongFont) или классов окон
(TWndClass). Windows и ObjectWindows определяют эти и другие
структуры данных. Перечень доступных структур вы можете найти в
оперативном справочнике или в файле WINTYPES.PAS. Структуры, не-
посредственно используемые в ObjectWindows, вы можете найти в
Главе 21 "Справочник по ObjectWindows".

При использовании ObjectWindows все функции Windows доступны
также непосредственно и могут вызываться в вашей программе (если
в ее операторе uses указывается модуль WinProcs). Например, сле-
дующий код для получения окна сообщений вызывает функцию Windows
MessageBox:

Reply := MessageBox(HWindow, 'Хотите сохранить?',
'Файл изменен', mb_YesNo or mb_IconQuestion);

MessageBox возвращает целочисленное значение, указывающее,
какое действие выбрал пользователь для закрытия окна сообщения.
Если пользователь щелкнул "мышью" на командной кнопке Yes (Да),
то результат равен определенной в Windows целочисленной константе
id_Yes. Если пользователь щелкнул "мышью" на командной кнопке No
(Нет), то результат равен id_No.



B.Pascal 7 & Objects/OW - 134 -

Комбинирование констант стилей
-----------------------------------------------------------------

Функции Windows, позволяющие получить интерфейсные элементы,
требуют обычно некоторого параметра типа Word или Longint. Иден-
тификаторы констант стилей состоят из двухбуквенного мнемоничес-
кого префикса, за которым следует подчеркивание и описательное
имя. Например, ws_Popup - это константа стиля окна (ws_ означает
стиль окна - window style").

Примечание: В Windows определены сотни констант сти-
лей, которые перечислены в Главе 21 "Справочник по
ObjectWindows".

Часто эти стили комбинируются для получения другого сти-
ля. Например, в случае функции MessageBox вы можете передать в
качестве параметра стиля mb_YesNo или mb_IconQuestion. Этот стиль
дает окно сообщений с двумя командными кнопками Yes и No и пик-
торгаммой вопросительного знака. Поразрядная операция or факти-
чески комбинирует две константы бит за битом. Полученный в ре-
зультате стиль представляет собой комбинацию обоих стилей.

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

Типы функций Windows
-----------------------------------------------------------------

Ниже перечислены виды функций Windows, которые вы можете ис-
пользовать в своих программах ObjectWindows.

Функции интерфейса с администратором Windows

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

Функции интерфейса
с графическими устройствами (GDI)

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

Функции интерфейса со служебными функциями системы

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



B.Pascal 7 & Objects/OW - 135 -

Функции системного вызова
-----------------------------------------------------------------

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

Функции Windows, требующие функций системного вызова (или
повторного вызова), включают в себя: EnimChildWindows,
EnumClipboardFormats, EnumFonts, EnumMetaFile, EnumObjects,
EnumPops, EnumTaskWindows и EnumWindows.

Функция системного вызова должна быть обычной функцией, а не
методов объекта. Указатель на эту функцию передается в качестве
первого параметра (типа TFarProc) данных методов. Например, если
вы определили в Паскале функцию системного вызова ActOnWindow
следующим образом:

function ActOnWindow(TheHandle: HWnd; The Value: Longint):
Integer; far; export;

то можете передать ее в качестве функции системного вызова при
вызове функции Windows EnumWindows:

ReturnValue := EnumWindows(TFarProc(ActOnWindow), ALongint);

Функция системного вызова должна иметь тот же тип возвращае-
мого значения, что и вызывающая ее функция Windows. Функция
ActOnWindows будет выполнять некоторое действие с окном, заданным
переданным указателем. Параметр TheValue - это любое значение,
выбранное для передачи в вызывающей программе.

Директива компилятора {$K+} позволяет автоматически управ-
лять функциями системного вызова. Если вы не выбираете {$K+}, то
для возврата адреса, по которому будет выполнять вызов Windows,
должны передавать свои функции системного вызова через функцию
API MakeProcInstance.



B.Pascal 7 & Objects/OW - 136 -

------------------------------------------------------------------
Глава 8. Объекты приложения
-----------------------------------------------------------------

При разработке приложения ObjectWindows вам нужно сначала
определить объект приложения, производный от типа ObjectWindows
TApplication. Этот объект инкапсулирует следующее поведение при-
ложения ObjectWindows:

* Создание и вывод основного окна приложения.

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

* Инициализацию каждого экземпляра приложения, например,
загрузку таблицы оперативных клавиш.

* Обработку сообщений Windows.

* Закрытие приложения.

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

Минимальные требования
-----------------------------------------------------------------

Чтобы ваше программа ObjectWindows стала рабочим приложением
Windows, она должна в своем основном блоке begin..end делать сле-
дующее:

- выполнять инициализацию;

- обрабатывать сообщения;

- по требованию завершать работу.

Используемый по умолчанию объект выполняет эти задачи путем
вызова трех его методов: Init, Run и Done. Основной блок любой
программы ObjectWindows содержит обычно эти три метода. Чтобы из-
менить поведение по умолчанию, методы нужно переопределить.

Поиск объекта приложения
-----------------------------------------------------------------

Когда программа выполняется, ObjectWindows поддерживает гло-
бальную переменную Application - указатель на объект приложения.
Этот указатель позволяет подпрограммам вне объекта приложения об-
ращаться к его полям и методам. По умолчанию Application устанав-
ливается в @Self конструктором объекта приложения и в nil дест-

B.Pascal 7 & Objects/OW - 137 -

руктором объекта.

Минимальное приложение
-----------------------------------------------------------------

Приведем пример минимального приложения ObjectWindows:

program MinApp;
uses OWindows;
var
MyApp: TApplication;
begin
MyApp.Init('TtstApp');
MyApp.Run;
MyApp.Done;
end;

MinApp - это абсолютный минимум приложения ObjectWindows.
Эта программа не требует определения других объектов. Обычно вы
определяете новый объектные типы как минимум для приложения и ос-
новного окна.

Методы Init, Run и Done
-----------------------------------------------------------------

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

Конструктор Init
-----------------------------------------------------------------

Первый оператор - это вызов конструктора Init приложения.
Этот вызов делает следующее:

* Строит объект.

* Инициализирует поля данных объекта.

* Устанавливает глобальную переменную Application на объект
(@Self).

* Выполняет два вида инициализации:

- Вызывает InitApplication при отсутствии других выполняе-
мых экземпляров данного приложения.

- Всегда вызывает InitInstance, устанавливая вызовом
InitMainWindow основное окно.

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

B.Pascal 7 & Objects/OW - 138 -

Метод Run
-----------------------------------------------------------------

Второй оператор вызывает метод Run приложения, который реа-
лизует работу приложения, вызывая MessageLoop. MessageLoop обра-
батывает сообщения от Windows и выполняет инструкции, которые уп-
равляют работой приложения. MessageLoop - это цикл, который про-
должает работу до закрытия приложения.

MessageLoop вызывает несколько методов, обрабатывающих конк-
ретные поступающие сообщения (см. далее).

Деструктор Done
-----------------------------------------------------------------

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

-----------------¬ ------------------¬
¦ Init +--T->¦ InitApplication ¦
L----------------- ¦ L------------------
¦
¦ ------------------¬ -----------------¬
L->¦ InitInstance +--->¦ InitMainWindow ¦
L------------------ L-----------------

-----------------¬ ------------------¬
¦ Run +---->¦ MessageLoop ¦
L----------------- L------------------

-----------------¬
¦ Done ¦
L-----------------

Рис. 8.1 Вызовы методов, управляющие работой приложения.

Инициализация приложения
-----------------------------------------------------------------

Выполнение методов, инициализирующих объект приложения, поз-
воляет вам настроить части процесса путем переопределения отдель-
ных методов. Один из методов, требующий переопределения, чтобы
приложения получило конкретный смысл - это InitMainWindow. Вы мо-
ете также переопределить InitInstance и InitApplication.



B.Pascal 7 & Objects/OW - 139 -

Инициализация основного окна
-----------------------------------------------------------------

Вы должны определить метод InitMainWindow, который строит и
инициализирует объект основного окна и сохраняет его в поле
MainWindow объекта приложения. Ниже показан пример описания объ-
екта приложения и метода InitMainWindow.

Данный метод создает новый экземпляр типа TWindow
ObjectWindows (PWindow - это указатель на тип TWindow). Обычно
ваша программа будет определять для своего основного окна новый
оконный тип, а InuitMainWindow будет использовать этот тип вмес-
то TWindow.

Примечание: Объекты окон подробно описываются в Главе
10.

Следующее простое приложение ObjectWindows объединяет в себе
новый тип TMyApplication и старое приложение MinApp. Оно отлича-
ется от MinApp только тем, что основное окно имеет заголовок:

program TestApp;
uses OWindows;

type
TMyApplication = object(TApplication)
procedure InitMainWindow; virtual;
end;

procedure TMyApplication.InitMainWindow;
begin
MainWindow := New(PWindow, Init(nil, 'Основное окно'));
end;


var
MyApp: TApplication;
begin
MyApp.Init('TestApp');
MyApp.Run;
MyApp.Done;
end;

Программа TestApp выводит окно с заголовком 'Основное окно'.
Вы можете легко перемещать это окно и изменять его размер, мини-
мизировать его, восстанавливать или максимизировать. Закрытие ок-
на завершает приложение. Короче, TestApp - это полнофункциональ-
ный "скелет" приложения, оснащенный только простейшим основным
окном.



B.Pascal 7 & Objects/OW - 140 -

Специальный вывод основного окна
-----------------------------------------------------------------

Начальный вывод основного окна управляется переменной
CmdShow модуля System. CmdShow содержит одну из констант sw_ и
передается в качестве параметра функции API Windows ShowWindow,
когда приложение создает свое основное окно.

С помощью CmdShow вы легко можете вывести основное окно в
нормальном виде (по умолчанию), распахнутым до размеров полного
экрана, минимизированным в пиктограмму или скрытым. Лучшим местом
присваивания значения CmdShow является конструктор объекта основ-
ного окна. Это обеспечивает передачу выбранного значения при соз-
дании элемента экрана.

Инициализация первого экземпляра
-----------------------------------------------------------------

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

Если текущим экземпляром является первый экземпляр, то конс-
труктор Init вызывает InitApplication. TApplication определяет
заместитель метода InitApplication, который вы можете для выпол-
нения специальной инициализации первого экземпляра переопреде-
лить.


B.Pascal 7 & Objects/OW - 141 -


Например, вы можете модифицировать TestApp таким образом,
чтобы о первом экземпляре сообщалось в заголовке основного окна.
Для этого добавьте в тип приложения TMyApplication булевское поле
с именем FirstApp, затем переопределите метод InitApplication,
чтобы он устанавливал FirstApp в True. Наконец, модифицируйте
InitMainWindow для проверки FirstApp и вывода в основном окне
приложения соответствующего заголовка (см. Рис. 8.2).

-----------------------------------------------------------------
------------------------------------------------------T-T-¬------
-¦-=---------------Первый экземпляр-------------------¦^¦v¦------
-+----------------------------------------------------+-+-+------
-¦ ¦------
-¦ -----------------------------------------------------T-T-¬---
-¦ ¦-=---------------Дополнительный экземпляр-----------¦^¦v¦---
-¦ +----------------------------------------------------+-+-+---
-¦ ¦ ¦---
-¦ ¦ -----------------------------------------------------T-T-¬
-¦ ¦ ¦-=-------------Дополнительный экземпляр-------------¦^¦v¦
-¦ ¦ +----------------------------------------------------+-+-+
-¦ ¦ ¦ ¦
-¦ ¦ ¦ ¦
-L--¦ ¦ ¦
----¦ ¦ ¦
----L--¦ ¦
-------¦ ¦
-------L---------------------------------------------------------

Рис. 8.2 Новая инициализация приложения.

program TestApp;
uses OWindows;

type
TMyApplication = object(TApplication)
FirstApp: Boolean;
procedure InitMainWindow; virtual;
procedure InitApplication; virtual;
end;

procedure TMyApplication.InitMainWindow;
begin
if FirstApp then
MainWindow := New(PWindow, Init(nil,
'Первый экземпляр'))
else MainWindow := New(PWindow, Init(nil,
'Дополнительный экземпляр'));
end;

procedure TMyApplication.InitApplication;
begin
FirstApp := True;

B.Pascal 7 & Objects/OW - 142 -

end;

var MyApp; TMyApplication;
begin
MyApp.Init('TestApp');
MyApp.Run;
MyApp.Done;
end.

Инициализация каждого экземпляра
-----------------------------------------------------------------

Пользователь может одновременно выполнять несколько экземп-
ляров ObjectWindows. Метод InitInstance инициализирует каждый эк-
земпляр приложения. Он должен инициализировать только само прило-
жение, а не его основное окно. Основное окно инициализируйте в
InitMaionWindow.

InitInstance вызывает InitMainWindow, а затем создает и вы-
водит основное окно. Для модификации стандартной инициализации
приложения (например, для загрузки таблицы оперативных клавиш)
вам нужно только переопределить InitInstance. Если вы переопреде-
ляете для своего приложения InitInstance, убедитесь сначала, что
он вызывает метод InitInstance, наследуемый из TApplication.

Приведем метод InitInstance, который перед выполнением при-
ложения загружает метод InitInstance. 'MeHotKeys' - это идентифи-
катор ресурса таблицы оперативных клавиш, определенный в файле
ресурса:

procedure TEditApplication.InitInstance;
begin
inherited InitInstance;
HAccTable := LoadAccelerators(HInstance, 'MyHotKeys');
end;

Вы можете также использовать InitInstance для регистрации
экземпляра приложения с внешней DLL (типа Paradox Engine).



B.Pascal 7 & Objects/OW - 143 -

Выполнение приложений
-----------------------------------------------------------------

Метод Run вашего приложения вызывает метод MessageLoop, ко-
торый вызывает цикл обработки сообщений вашей программы. Во время
выполнения вашей программы в цикле обработки сообщений обрабаты-
ваются поступающие от Windows сообщения. Программы ObjectWindows
наследуют цикл MessageLoop, который работает автоматически. До-
полняйте цикл обработки сообщений только специальными диалогами,
оперативными клавишами или обработкой MDI.

Метод MessageLoop для обработки сообщений Windows вызывает
три метода. ProcessDlgMsg работает с безрежимными диалоговыми ок-
нами, ProcessAccels - обрабатывает оперативные клавиши, а
ProcessMDIAccels - оперативные клавиши для приложений MDI. Для
приложений, не использующих командные клавиши или безрежимные ди-
алоговые окна или не являющихся приложениями MDI MessageLoop мож-
но несколько упростить. См. методы TApplication в Главе 21.

Закрытие приложений
-----------------------------------------------------------------

Вызов деструктора Done в основной программе вашего приложе-
ния уничтожает объект приложения. Однако, перед тем как это про-
исходит, программа должна прервать цикл обработки сообщения. Это
может произойти, когда пользователь пытается закрыть основное ок-
но приложения. Мы говорим, что это может произойти, так как
ObjectWindows предусматривает механизм изменения поведения прило-
жения при закрытии: вы можете задавать условия закрытия.

Модификация поведения при закрытии
-----------------------------------------------------------------

Все оконные объекты, наследуют булевский метод CanClose,
возвращающий по умолчанию True (что указывает на подтверждение
закрытия, то есть TestApp закрывается немедленно). Для изменения
поведения при закрытии вы можете переопределить методы CanClose
приложения или основного типа окна. Если какие-либо объекты возв-
ращают из CanClose значение False, то приложение завершиться не
может. Обычно вы можете изменить поведение при закрытии объектно-
го типа основного окна. Например, перед завершением можно убе-
диться, что приложение сохранило файлы.

Механизм CanClose

Механизм CanClose дает основному окну, объекту приложения и
другим окнам возможность подготовиться с закрытию или предотвра-
тить его. В итоге объект приложения должен разрешить закрытие
приложения. По умолчанию он проверяет основное окно. Обычная пос-
ледовательность закрытия выглядит следующим образом:

1. Windows посылает основному окну приложения сообщение
wm_Close.

B.Pascal 7 & Objects/OW - 144 -


2. Объект основного окна вызывает метод CanClose объекта
приложения.

3. Объект приложения вызывает метод CanClose.

4. Объект основного окна вызывает метод CanClose для каждого
из дочерних окон и возвращает True только в том случае,
если методы CanClose дочерних окон возвращают True.

Модификация CanClose

Методы CanClose редко возвращают значение False. Вместо это-
го они должны выполнять некоторые действия, позволяющие им возв-
ращать True. Метод CanClose должен возвращать False только в том
случае, если он не может выполнить действий, необходимых для нор-
мального завершения, или пользователь показывает, что он хочет
продолжать выполнение программы.

Например, метод CanClose окна редактора может проверять из-
менение редактируемого текста, а затем выводить диалоговое окно с
запросом, нужно ли сохранить текст перед закрытием, и восприни-
мать ответ Yes (Да), No (Нет) или Cancel (Отмена). Cancel будет
указывать, что пользователь пока не хочет закрывать приложение,
так что CanClose должен возвращать False. CanClose следует также
возвращать False при обнаружении ошибки в сохранении текста, пре-
доставляя пользователю другую возможность сохранения данных перед
закрытием.

Если метод CanClose не переопределяется, тип основного окна
наследует его от TWindowsObject, где CanClose возвращает True
после вызовов методов CanClose дочерних окон. Чтобы модифициро-
вать поведение при закрытии основного окна, переопределите метод
CanClose. Например, для проверки того, что пользователь собирает-
ся закрыть окно, он может проверять открытые файлы.



B.Pascal 7 & Objects/OW - 145 -

------------------------------------------------------------------
Глава 9. Интерфейсные объекты
-----------------------------------------------------------------

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

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

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

Для чего нужны интерфейсные объекты?
-----------------------------------------------------------------

Для чего нужны интерфейсные объекты, если в Windows уже есть
окна, диалоговые блоки и управляющие элементы?

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

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

Что делают интерфейсные объекты?
-----------------------------------------------------------------

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

Взаимосвязь объект/элемент во многом аналогична связи файла
DOS с переменной Паскаля. Имея файл, вы можете присвоить файловую
переменную, представляющую физическую структуру фактического фай-
ла на диске, а затем работать с этой файловой переменной. С по-
мощью ObjectWindows вы можете определить объект, представляющий
физическое окно, управляющий элемент или диалоговый блок, который
фактически обслуживается администратором окон Windows. Вы работа-
ете с объектом, а он берет на себя функции по обслуживанию эле-
мента экрана.



B.Pascal 7 & Objects/OW - 146 -

Общий интерфейсный объект
-----------------------------------------------------------------

Все интерфейсные объекты ObjectWindows наследуют из единс-
твенного абстрактного объектного типа TWindowsObject, который
определяет поведение, общее для окна, диалога и объектов управля-
ющих элементов, видоизменяемых и специализируемых в производных
объектных типах TDialog, TWindow и TControl.

В качестве общего предка всех интерфейсных объектов методы
TWindowsObject обеспечивают единообразный способ поддержки взаи-
мосвязи между объектами и элементами экрана (включая создание и
уничтожение объектов), обслуживают соотношения "родитель-потомок"
между интерфейсными объектами и регистрируют новый классы Windows
(см. Главу 10).

Новые типы, производные от TWindowsObject, определяются ред-
ко, но он служит основой объектно-ориентированной модели окон. Он
определяет большинство наследуемых объектами функциональных воз-
можностей, когда вы получаете из TWindow и TDialog новые типы.

Создание интерфейсных объектов
-----------------------------------------------------------------

Задание полного интерфейсного объекта с соответствующими ин-
терфейсными элементами требует двух шагов:

* Построения объекта.

* Создания элемента экрана.

Первым шагом является вызов конструктора Init, который стро-
ит интерфейсный объект и устанавливает его атрибуты, такие как
стиль и меню.

Второй шаг заключается в вызове метода создания окна объекта
приложения, MakeWindow, связывающего интерфейсный объект с новым
элементом экрана. Эта связь поддерживается полем HWindow экрана
(описателем окна).

Примечание: Об описателях окон рассказывается в Главе 7
"Иерархия ObjectWindows".

MakeWindow вызывает метод Create объекта, который всегда со-
общает Windows о необходимости создания элемента на экране.
Create создает также метод SetupWindow, который инициализирует
интерфейсный объект путем создания, например, дочерних окон.



B.Pascal 7 & Objects/OW - 147 -

Допустимость описателя окна
-----------------------------------------------------------------

Обычно в Windows вновь созданный интерфейсный элемент полу-
чает (от Windows) сообщение wm_Create, на которое требуется отве-
тить инициализацией. Интерфейсный объект ObjectWindows не будет
получать сообщений wm_Create, поэтому не забудьте определить для
инициализации метод SetupWindow.

Если инициализация интерфейсного объекта требует описателя
элемента экрана (например, для вызова функции API Windows), то
она не должна вызываться раньше SetupWindow. То есть, перед вызо-
вом SetupWindow поле HWindow интерфейсного объекта не является
допустимым и использоваться не должно. Если вы хотите вызывать
функцию API или нечто требующее описателя окна, не вызывайте их
в конструкторе Init. Поместите такие вызовы в метод SetupWindow.

¦<----HWindow допустим--->¦
¦ ¦
¦<-------------------интерфейсный объект допустим---------->¦
--+-----------------------------------------------------------+-->
^ ^ ^ ^ ^
¦ ¦ ¦ ¦ ¦
Init вызывает ¦ ¦ ¦ ¦
наследуемый Init ¦ ¦ ¦ ¦
¦ ¦ Done ¦
SetupWindow вызывает наследуемый ¦
SetupWindow ¦ Done вызывает наследуемый
¦ метод Done
¦
Наследуемый SetupWindow вызывает Create

Рис. 9.1 Когда окно имеет допустимый описатель.



B.Pascal 7 & Objects/OW - 148 -

Видимость на экране
-----------------------------------------------------------------

Создание интерфейсного объекта и соответствующего визуально-
го элемента не обязательно означает, что вы что-то видите на эк-
ране. Когда метод Create указывает Windows на создание элемента
экрана, Windows проверяет, включает ли стиль окна ws_Visible. Ес-
ли да, то интерфейсный элемент будет выводиться. В противном слу-
чае он будет скрытым.

ws_Visible и другие стили окна обычно устанавливаются или
сбрасываются конструктором Init в поле Attr.Style объекта.

В любой момент после создания элемента экрана вы можете вы-
вести или скрыть его, вызвав метод Show интерфейсного объекта.

Уничтожение интерфейсных объектов
-----------------------------------------------------------------

Как и в случае создания интерфейсный объектов, их уничтоже-
ние предполагает выполнение двух шагов:

* Уничтожение визуального интерфейсного элемента (Destroy).

* Уничтожение интерфейсного объекта (Dispose).

Уничтожением экранного элемента занимается метод Destroy ин-
терфейсного объекта, который делает следующее: он вызывает функ-
цию Windows DestroyWindow, чтобы избавиться от элемента экрана, и
устанавливает поле HWindow объекта в 0. Таким образом, проверив
указатель, вы можете сообщить, связан ли еще объект с элементом
экрана.

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

Примечание: Уничтожение самого окна обычно не требует-
ся. Это делается автоматически при закрытии окна.

Когда пользователь закрывает на экране окно, ObjectWindows
обнаруживает, что данный элемент экрана уничтожен, устанавливает
поле HWindow соответствующего объекта в 0 и вызывает деструктор
объекта Done.



B.Pascal 7 & Objects/OW - 149 -

Связь порождающего и дочернего объектов
-----------------------------------------------------------------

В приложении Windows совместная работа элементов экрана
(окон, диалоговых блоков и управляющих элементов) обеспечивается
с помощью связей "родитель-потомок". Порождающие окна управляют
своими дочерними окнами, а Windows отслеживает эти связи.
ObjectWindows поддерживает параллельный набор связей между соот-
ветствующими интерфейсными объектами.

Дочернее окно - это элемент экрана (оно не обязано быть ок-
ном), который управляется другим элементом экрана. Например, бло-
ки списка обслуживаются окном или диалоговым блоком, в котором
они выводятся. Они выводятся на экран только при выводе их порож-
дающих окон. Диалоговые блоки, в свою очередь, являются дочерними
окнами, управляемыми порождающими их окнами.

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

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

Список дочерних окон
-----------------------------------------------------------------

Когда вы строите объект дочернего окна, то можете в качестве
параметра конструктора Init можете задать порождающее окно (при-
мер вы можете найти в Главе 10). Объект дочернего окна отслежива-
ет свое порождающее окно через указатель на его поле Parent. Он
отслеживает также объекты его дочерних окон, сохраненные в поле
ChildList. Дочернее окно, на которое в данный момент установлен
ChildList, является последним созданным дочерним окном.



B.Pascal 7 & Objects/OW - 150 -

Построение дочерних окон
-----------------------------------------------------------------

Как и в случае интерфейсных объектов, объекты дочерних окон
создаются в два этапа (построение объекта и создание элемента эк-
рана). Объекты порожденного окна следует строить с помощью конс-
труктора Init порождающего окна. Например, объект окна, наследую-
щий из TWindow и содержащий командную кнопку должен иметь пример-
но следующий вид:

constructor TMyWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
TheButton := New(PButton, Init(@Self, id_TheButton,
'Текст кнопки', 20, 10, 100, 25, True));
end;

Обратите внимание на использование указателя Self для связи
дочернего объекта (TheButton) с порождающим (экземпляром
TMyWindow). Конструктор интерфейсного объекта автоматически до-
бавляет к своему списку дочерних окон новые объекты.

Создание дочерних элементов экрана
-----------------------------------------------------------------

Когда построен список дочерних элементов интерфейсного объ-
екта, создание элементов экрана для дочерних окон выполняется ав-
томатически. Создание родительского окна (через вызов MakeWindow)
включает в себя вызов метода SetupWindow порождающего окна. Одним
из наследуемых действий SetupWindow является вызов для каждого из
окон в списке дочерних окон методов SetupWindow.

Примечание: Автоматическое создание можно запретить.
См. ниже раздел "Запрещение автоматического создания".

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

procedure TMyCheckBox.SetupWindow;
begin
inherited SetupWindow; { сначала по умолчанию }
.
.
. { выполнить инициализацию объекта }
end;

Уничтожение дочерних окон
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 151 -

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

Запрещение автоматического создания
-----------------------------------------------------------------

Чтобы явно исключить дочернее окно из механизма автоматичес-
кого создания и вывода, вызовите после его создания метод
DisableAutoCreate. Чтобы явно добавить в механизм создания и вы-
вода дочернее окно (такое как диалоговый блок, который при нор-
мальном выводе будет исключен), вызовите после построения его ме-
тод EnableAutoCreate.

Итерация дочерних окон
-----------------------------------------------------------------

Иногда желательно написать методы, для реализации функции
выполняющие итерации по каждому дочернему окну данного окна. Нап-
ример, можно проверить в окне все кнопки с независимой фиксацией.
В этом случае используйте метод TWindowsObject.ForEach:

procedure TMyWindow.CheckAllBoxes;

procedure CheckTheBox(ABox: PWindowsObject); far;
begin
PCheckBox(ABox)^.Check;
end;

begin
ForEach(@CheckTheBox);
end;

Использование метода ForEach (и аналогичных методов
FirstThat и LastThat) похоже на применение методов с аналогичными
названиями в TCollection. Хотя ObjectWindows не использует наборы
для обслуживания дочерних окон, методы итерации работают анало-
гично.

Поиск определенного дочернего окна
-----------------------------------------------------------------

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

function TMyWindow.GetFirstChecked: PWindowsObject;

function IsThisOneChecked(ABox: PWindowsObject): Boolean;
far;
begin

B.Pascal 7 & Objects/OW - 152 -

IsThisOneChecked := (ABox^.GetCheck = bf_Checked);
end;

begin
GetFirstChecked := FirstThat(@IsThisOneChecked);
end;



B.Pascal 7 & Objects/OW - 153 -

------------------------------------------------------------------
Глава 10. Объекты окон
-----------------------------------------------------------------

Объекты окон (или оконные объекты) - это интерфейсные объек-
ты, предназначенные для облегчения работы с окнами. В данной гла-
ве поясняется, как создавать и заполнять окна приложения. Это
предусматривает следующие задачи:

* Инициализацию оконных объектов.

* Установку атрибутов создания.

* Создание экранных элементов окна.

* Установку атрибутов регистрации.

* Использование специализированных окон.

* Прокрутку окон.

Что такое объекты окон?
-----------------------------------------------------------------

Термин "объект окна" относится к любому интерфейсному объек-
ту, представляющему окно, а в Windows это почти все, что выводит-
ся на экран. В качестве шаблона определения большей части фунда-
ментального поведения основного окна и любого всплывающего окна
приложения ObjectWindows использует тип TWindow.


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

TWindow имеет три типа-потомка: TMDIWindow, TControl и
TEditWindow, так что все они также являются оконными объектами,
хотя на самом деле это не окна в полном смысле слова. Типы MDI
используются в приложениях ObjectWindows, которые соответствуют
стандарту многодокументального интерфейса Windows. Об MDI и этих
типах рассказывается в Главе 14. TControl определяет управляющие
элементы, такие как командные кнопки и блоки списков (см. Главу
12). Чаще всего новые оконные типы являются производными от
TWindow.

Эта глава охватывает типы TWindow и TEditWindow и содержит
примеры регистрации новых классов окон.



B.Pascal 7 & Objects/OW - 154 -

Где найти объекты окон
-----------------------------------------------------------------

Каждое приложение Windows имеет основное окно. Это окно мо-
жет выводиться в виде пиктограммы или не выводиться снова (скры-
тое окно), но существует всегда. Приложения ObjectWindows не яв-
ляются исключением: они должны иметь основное окно, представлен-
ное оконным объектом.

Примером минимальной программы ObjectWindows ("скелета"
программы) является TestApp в Главе 8. Основное окно программы
ObjectWindows является обычно экземпляром TWindow или определяе-
мого в программе наследующего типа. Многие приложения имеют дру-
гие окна, которые обычно являются дочерними окнами основного ок-
на. Эти дополнительные окна также являются экземплярами TWindow
или одного из его потомков.

Например, графическая программа может определять для своего
основного окна тип TPaintWindow, а для окна, показывающего графи-
ческий рисунок - тип TZoomWindow. В этом случае TPaintWindow и
TZoomWindow являются наследниками TWindow.

Инициализация объектов окон
-----------------------------------------------------------------

Оконные объекты представляют элементы окна, связанные через
описатели, сохраненные в наследуемом из TWindowsObject поле
HWindow. Так как объект окна имеет две части, его создание требу-
ет двух шагов: инициализации объекта и создания визуального эле-
мента.

Инициализация окна - это процесс создания оконного объекта
ObjectWindows путем вызова конструктора Init:

Window1 := New(PWindow,Init(nil, 'Заголовок окна 1'));
Window2 := New(PNewWindowType,Init(nil,'Заголовок окна 2'));

Init создает новый оконный объект и устанавливает поле Title
в Attr в передаваемый аргумент PChar. Первый аргумент вызова Init
- это оконный объект порождающего окна. Если окно является основ-
ным окном (не имеющим порождающего окна), то это nil.



B.Pascal 7 & Objects/OW - 155 -

Установка атрибутов создания
-----------------------------------------------------------------

Типичное приложение Windows имеет много различных типов
окон: перекрывающиеся или всплывающие, окна с рамкой, прокручива-
емые окна, окна с заголовком и др. Эти атрибуты стилей, а также
заголовок и меню окна задаются при инициализации оконного объекта
и используются при создании элементов окна.

Атрибуты создания оконного объекта, такие как стиль, заголо-
вок и меню, записываются в поле Attr объекта - записи типа
TWindowAttr. TWindowAttr содержит следующие поля:

Атрибуты создания окна Таблица 10.1
-------------T--------------T-----------------------------------¬
¦ Поле ¦ Тип ¦ Использование ¦
+------------+--------------+-----------------------------------+
¦ Title ¦ PChar ¦ Строка заголовка. ¦
¦ ¦ ¦ ¦
¦ Style ¦ Longint ¦ Комбинированная константа стиля. ¦
¦ ¦ ¦ ¦
¦ Menu ¦ HMenu ¦ Описатель ресурса меню. ¦
¦ ¦ ¦ ¦
¦ X ¦ Integer ¦ Горизонтальная координата экрана¦
¦ ¦ ¦ верхнего левого угла окна. ¦
¦ ¦ ¦ ¦
¦ Y ¦ Integer ¦ Вертикальная координата экрана¦
¦ ¦ ¦ верхнего левого угла окна. ¦
¦ ¦ ¦ ¦
¦ W ¦ Integer ¦ Начальная ширина окна в координа-¦
¦ ¦ ¦ тах экрана. ¦
¦ ¦ ¦ ¦
¦ H ¦ Integer ¦ Начальная высота окна в координа-¦
¦ ¦ ¦ тах экрана. ¦
¦ ¦ ¦ ¦
L------------+--------------+------------------------------------


B.Pascal 7 & Objects/OW - 156 -


^----------------------------------------------------------------
-(0,0)-----------------------------------------------------------
-----(X,Y)-------------------------------------------------------
-----v-----------------------------------------------------------
---------------------------------------------T--T--¬-------------
-----¦ ---------------- Title --------------¦ ¦ ¦ ^-----------
-----+---------------------------------------+--+--+ ¦-----------
-----¦ Menu ¦ ¦-----------
-----+---------------------------------------------+ ¦-----------
-----¦ ¦ ¦-----------
-----¦ ¦ ¦-----------
-----¦ ¦ H-----------
-----¦ ¦ ¦-----------
-----¦ ¦ ¦-----------
-----¦ ¦ ¦-----------
-----¦ ¦ ¦-----------
-----¦ ¦ ¦-----------
-----¦ ¦ v-----------
-----L-----------------------------------------------------------
-----¦<------------------W------------------------>¦-------------
-----------------------------------------------------------------
-----------------------------------------------------------------

Рис. 10.1 Атрибуты окна.

Используемые по умолчанию атрибуты окна
-----------------------------------------------------------------

По умолчанию TWindow.Init устанавливает Attr.Style в
ws_Visible. Если окно является основным окном приложения, то
Style равно ws_OverlappedWindow or ws_Visible.

Menu по умолчанию устанавливается в 0. Это означает, что ме-
ню не определено.

X, Y, W и H устанавливаются в cw_UseDefault, что дает в ре-
зультате перекрывающееся окно удовлетворительного размера. Когда
создается окно, не являющееся основным, значения X, Y, W и H вы
обычно устанавливаете сами.




B.Pascal 7 & Objects/OW - 157 -

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

При создании новых оконных типов, производных от TWindow, вы
обычно определяете новый конструктор Init (особенно если хотите
получить атрибут создания, отличных от используемого по умолча-
нию). Если вы хотите переопределить Init, то можете заново задать
атрибуты объекта, непосредственно изменяя поле Attr после вызова
Init.

Если вы переопределили Init, убедитесь, что первое, что он
делает - это вызов наследуемого метода TWindow.Init, устанавлива-
ющего используемые по умолчанию атрибуты. Затем вы можете изме-
нить по своему выбору любой из атрибутов. Например, типичное окно
может определять конструктор Init, который устанавливает атрибут
Menu:

constructor TWindowType.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
Attr.Menu := LoadMenu(HInstance, 'TheMenu');
AChildWindow := New(PChildWindowType, Init(@Self,
'Заголовок дочернего окна'));
List1 := New(PListBox, Init(@Self, id_ListBox,
201, 20, 20, 180, 80));
.
.
.
end;

Атрибуты порожденного окна
-----------------------------------------------------------------

Конструктор TWindowType отвечает за построение его дочерних
объектов, таких как всплывающие окна и блоки списка. Тип порож-
денного окна, в свою очередь, может устанавливать атрибуты в сво-
ем собственном конструкторе Init:

constructor TChilwWindowType.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
with Attr do
begin
Style := Style or ws_PopupWindow or ws_Caption;
X := 100; Y := 100; W := 300; H := 300;
end;
end;

В качестве альтернативы вы можете не определять потомка
типа окна, а сначала построить объект окна, а затем переустано-
вить его атрибуты (все это в конструкторе Init порождающего ок-

B.Pascal 7 & Objects/OW - 158 -

на):

constructor TWindowType.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
Attr.Menu := LoadMenu(HInstance, 'TheMenu');
AChildWindow := New(PChildWindowType, Init(@Self,
'Заголовок дочернего окна'));
with Attr do
begin
Style := Style or ws_PopupWindow or ws_Caption;
X := 100; Y := 100; W := 300; H := 300;
end;
.
.
.
end;

Создание элементов окна
-----------------------------------------------------------------

После построения оконного объекта вам нужно сообщить
Windows, что требуется создать связанные с объектом элементы эк-
рана. Это делается с помощью вызова MakeWindow объекта приложения
и передачи ему в качестве параметра указателя на объект окна.

if Application^.MakeWindow(AWindow) <> nil then
{ успешное создание }
else { неуспешное создание }

MakeWindow вызывает два важных метода: ValidWindow и Create.
ValidWindow проверяет успешность построение объекта окна, прове-
ряя поле Status. Если по каким-либо причинам конструктор завер-
шился неуспешно, то MakeWindow возвращает nil. При успешном вы-
полнении конструктора MakeWindow переходит на метод Create окон-
ного объекта.

Create - это метод, который фактически сообщает Windows о
создании элемента экрана. Если Create завершается неудачно,
MakeWindow возвращает nil. В противном случае возвращается указа-
тель на оконный объект. Для работы с элементом экрана Create так-
же устанавливает поле HWindow.

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

Все прочие окна приложения являются дочерними окнами, прямо
или косвенно порождаемыми основным окном, а дочерние окна созда-
ются обычно в методе SetupWindow или в его порождающих оконных
объектах, либо с помощью MakeWindow динамически на этапе выполне-

B.Pascal 7 & Objects/OW - 159 -

ния.

Примечание: Дочерние окна и SetupWindow описываются в
Главе 9 "Интерфейсный объекты".

В общем случае порождающие окна обычно вызывают для своих
дочерних окон методы Init и MakeWindow. Атрибуты оконного объекта
обычно устанавливаются их методами объекта порождающего окна.
Поскольку основное окно приложения не имеет порождающего окна,
объект приложения строит и создает его при запуске приложения.

Задание атрибутов регистрации
-----------------------------------------------------------------

В ходе инициализации оконного объекта путем заполнения поля
объекта Attr вы можете установить несколько атрибутов окна, такие
как его стиль, расположение и меню. Эти атрибуты используются для
создания соответствующего оконного элемента, поэтому они называ-
ются атрибутами создания.

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



B.Pascal 7 & Objects/OW - 160 -

Классы окон
-----------------------------------------------------------------

С каждым типом оконного объекта связан список атрибутов ре-
гистрации, которые называются классом окна. Список атрибутов ре-
гистрации во многом напоминает список атрибутов создания, запи-
санных в поле записи Attr объекта окна. Однако, атрибуты регист-
рации сохраняются в записи с именем TWndClass, который определя-
ется и поддерживается Windows.

Процесс связи класса окна с типом оконного объекта называет-
ся регистрацией класса окна. ObjectWindows автоматизирует процесс
регистрации. Таким образом, если вы хотите изменить какую-либо из
используемых по умолчанию характеристик объекта, то можете не
беспокоиться о классе регистрации окна.

Поля записи TWndClass и их типы перечислены в следующей таб-
лице:

Атрибуты регистрации окна Таблица 10.2
--------------------------T-------------------T-----------------¬
¦ Характеристика ¦ Поле ¦ Тип ¦
+-------------------------+-------------------+-----------------+
¦ стиль класса ¦ style ¦ Word ¦
¦ пиктограмма ¦ hIcon ¦ HIcon ¦
¦ курсор ¦ hCursor ¦ HCursor ¦
¦ фоновый цвет ¦ hbrBackground ¦ HBrush ¦
¦ меню по умолчанию ¦ lpszMenuName ¦ PChar ¦
L-------------------------+-------------------+------------------

Поля стиля класса

Это поле стиля отличается от атрибута стиля окна (ws_), за-
даваемого при инициализации окна, поскольку задает поведение,
присущее операциям окна (в отличие от их визуального представле-
ния). Это поле может заполняться комбинацией констант стиля
(cs_).

Например, cs_HRedraw приводит к повторному отображению окна
при изменении его размера по горизонтали; cs_DoubleClk позволяет
окну получать сообщения о двойном нажатии кнопки "мыши";
cs_NoClose предотвращает выбор параметра Close меню Control, а
cs_ParentDC дает окну контекст дисплея порождающего окна.

Поле пиктограммы

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

Поле курсора


B.Pascal 7 & Objects/OW - 161 -

Поле hCursor содержит описатель курсора, который использует-
ся для представления указателя "мыши" при позиционировании его в
окне.

Поле фонового цвета

Это поле задает фоновый цвет окна. Для большинства приложе-
ний используется стандартный назначаемый по умолчанию цвет окна,
который может устанавливаться пользователем в управляющей панели.
Однако вы можете путем установки этого поля в описатель физичес-
кой кисти подставить конкретный цвет. Либо вы можете установить
любое из значений цветов Windows, такие как color_ActiveCaption.
К любому значению цвета всегда добавляйте 1.

Поле используемого по умолчанию меню

Это поле указывает на имя ресурса меню, которое служит ис-
пользуемым по умолчанию меню для данного класса. Например, если
вы определите тип EditWindow, который всегда имеет стандартное
меню редактирования, то можете задать здесь это меню. Это устра-
нит необходимость задания меню в методе Init. Если данный ресурс
меню имеет идентификатор 'MyMenu', вы можете установить это поле
следующим образом:

AWndClass.IpszMenuName := 'MyMenu';



B.Pascal 7 & Objects/OW - 162 -

Используемые по умолчанию атрибуты регистрации
-----------------------------------------------------------------

Тип TWindow определяет класс окна 'TurboWindow' с пустой
пиктограммой, курсором-стрелкой и стандартным цветом окна. Ис-
пользуемый по умолчанию класс ObjectWindows (TurboWindow) имеет
следующие атрибуты:

* стиль: cs_HRedraw or cs_VRedraw (повторное отображение
после каждого изменения размера);

* пиктограмма: idi_Application (пустой прямоугольник);

* курсор: idc_Arrow (стандартная стрелка Windows);

* фоновый цвет: HBrush(color_Window + 1);

* меню по умолчанию: nil.

Регистрация нового класса
-----------------------------------------------------------------

Чтобы изменить атрибут регистрации, такой как курсор или
пиктограмму, вам нужно написать два метода - GetClassName и
GetWindowClass - и определить новый класс окна. Каждый раз, когда
вы изменяете атрибуты регистрации, вам нужно изменить имя класса.
Если класс регистрации с данным именем уже зарегистрирован в
Windows, другие классы с тем же именем класса регистрироваться не
будут - они получат атрибуты уже зарегистрированного класса.



B.Pascal 7 & Objects/OW - 163 -

Изменение имени класса
-----------------------------------------------------------------

GetClassName - это функция, которая возвращает имя (PChar)
класса окна. TWindow.GetClassName возвращает 'TurboWindow', имя
используемого по умолчанию класса окна. TWindow.GetClassName
возвращает 'TurboWindow' - имя используемого по умолчанию класса
окна:

function TWindow.GetClassName: PChar;
begin
GetClassName := 'TurboWindow';
end;

Чтобы определить тип объекта окна с именем IBeamWindow, ко-
торый использует вместо стандартной стрелки I-образный курсор,
переопределите наследуемый метод следующим образом:

function TBeamWindow.GetClassName: PChar;
begin
GetClassName := 'IBeamWindow';
end;

Примечание: Имя класса не обязательно должно соответс-
твовать имени объектного типа.

Имя класса должно быть уникальным.

Определение новых атрибутов регистрации
-----------------------------------------------------------------

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

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

Например, в поле hCursor хранится описатель ресурса курсора.
Для IBeamWindow определяется метод GetWindowClass:

procedure IBeamWindow.GetWindowClass(var AWndClass:
TWndClass);
begin
inherited GetWindowClass(AWndClass);
AWndClass.hCursor := LoadCursor(0, idc_IBeam);
end;

Примечание: idc_Beam - это константа, представляющая

B.Pascal 7 & Objects/OW - 164 -

один из курсоров Windows.

Кроме окон, диалоговым окнам (не диалоговым блокам) необхо-
димо регистрировать классы окна (см. Главу 11). Диалоговым блокам
и управляющим элементам классы окон не требуются.



B.Pascal 7 & Objects/OW - 165 -

Использование специализированных окон
-----------------------------------------------------------------

ObjectWindows предусматривает два потомка TWindow, являющих-
ся специализированными окнами для редактирования текста. Объект-
ный тип TEditWindow обеспечивает простой текстовый редактор, не
обладающий возможностями чтения из файла или записи в него. Тип
TFileWindow, наследующий из TEditWindow, обеспечивает текстовый
редактор с возможностями чтения/записи файлов.

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

Использование окон редактирования
-----------------------------------------------------------------

Окно редактирования - это окно с управляющим элементом ре-
дактирования, заполняющим его область клиента. TEditWindow.Init
инициализирует поле Editor окна редактирования, чтобы оно указы-
вало на управляющий элемент объекта редактирования.
TEditWindow.SetupWindow устанавливает размеры управляющего эле-
мента редактирования в соответствии с областью клиента окна и
создает экранный управляющий элемент редактирования.

Метод WMSize обеспечивает изменение размера управляющего
элемента редактирования при изменении размера его окна. Метод
WMSetFocus обеспечивает, что управляющий элемент редактирования
получает фокус ввода при получении окном сообщения wm_SetFocus.


B.Pascal 7 & Objects/OW - 166 -


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

------------------------------------------------------------T-T-¬
¦-=---------------------Edit Window Tester------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ Edit Text ¦
+---------------------------------------------------------------+
¦ Кого это может касаться: ¦
¦ ¦
¦ Я хотел бы зарегистрировать жалобу по поводу попугая, которого¦
¦ я купил в вашем магазине полгода назад. Он умер. ¦
¦ ------------------------------------¬ ¦
¦ Брюс ¦-=-------Передано сообщение--------¦ ¦
¦ +-----------------------------------+ ¦
¦ ¦ ¦ ¦
¦ ¦ 6 строк послано ¦ ¦
¦ ¦ -------------¬ ¦ ¦
¦ ¦ ¦----OK------¦ ¦ ¦
¦ ¦ L------------- ¦ ¦
¦ L------------------------------------ ¦
¦ ¦
L----------------------------------------------------------------

Рис. 10.2 Окно редактирования.

program EditWindowTester;
{$R EWNDTEST.RES}
uses ODialogs, WinTypes, WinProcs, Strings, OStdWnds;
const cm_sendText = 399;
type
TestApplication = object(TApplication)
procedure InitMainWindow; virtual;
end;

PMyEditWindow = ^MyEditWindow;
MyEditWindow = object(TEditWindow)
constructor Init(AParent: PWindowsObject;
ATitle: PChar);
procedure CMSendText(var Msg: TMessage); virtual
cm_First + cm_SendText;
end;

constructor MyEditWindow.Init(AParent: PWindowsObject;
Atitle: PChar);
begin
inherited Init(AParent, ATitle);
Attr.Menu := LoadMenu(HInstance, MakeIntResource(102));
end

procedure MyEditWindows.CMSendText(var Msg: TMessage);

B.Pascal 7 & Objects/OW - 167 -

var
Lines: Integer;
TestString: string[3];
Text: array[0..20] of Char;
begin
Lines := Editor^.GetNumLines;
Str(Lines, TextString);
StrCat(Text, ' строк послано');
MessageBox(HWindow, @Text, 'Передано сообщение', mb_Ok);
end;

procedure TestApplication.InitMainWindow;
begin
MainWindow := New(PMyEditWindow, Init(nil,
'Окно редактирования - попробуйте набор и редактирование'));
end;

var TestApp: TestApplication;
begin
TestApp.Init('EditWindowTester');
TestApp.Run;
TestApp.Done;
end.

Использование файловых окон
-----------------------------------------------------------------

Файловое окно - это окно редактирования с дополнительными
возможностями, позволяющими считывать и записывать данные в файл.
TFileWindow.Init воспринимает в качестве аргумента заголовок окна
и устанавливает поле FileDialog таким образом, чтобы оно указыва-
ло на файловый диалоговый объект.


B.Pascal 7 & Objects/OW - 168 -


Для работы с файлами TFileWindow имеет четыре метода. Методы
Open, Save и SaveAs для вывода пользователю подсказки с именем
файла используют поле TFileWindow.FileDialog (см. Главу 11). Ме-
тод New дает пользователю возможность отмены, если редактирование
нового файла приведет к потере изменений текущего текста. Чтобы
дать пользователю возможность доступа к этим методам, создайте
свое меню со следующими идентификаторами меню:

Методы и идентификаторы меню файлового окна Таблица 10.3
----------------------T-----------------------------------------¬
¦ Метод ¦ Идентификатор меню для вызова ¦
+---------------------+-----------------------------------------+
¦ New ¦ cm_FileNew ¦
¦ Open ¦ cm_FileOpen ¦
¦ Save ¦ cm_FileSave ¦
¦ SaveAs ¦ cm_FileSaveAs ¦
L---------------------+------------------------------------------

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

Прокрутка содержимого окон
-----------------------------------------------------------------

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

ObjectWindows управляет прокруткой окна, предоставляя каждо-
му оконному объекту поле Scroller, которое может указывать на
объект TScroller. Объект прокрутки TScroller обеспечивает автома-
тизированный способ прокрутки в окнах текста и графики. Кроме то-
го, TScroller может прокручивать окна, когда пользователь переме-
щает "мышь" за область клиента окна (это называется автоматичес-
кой прокруткой и действует даже для окон, которые не имеют полос
прокрутки).



B.Pascal 7 & Objects/OW - 169 -

Что такое объект прокрутки?
-----------------------------------------------------------------

TScroller содержит значения, определяющие, насколько должно
прокручивается окно. Эти значения записываются в полях XUnit,
YUnit, XLine, YLine, XRange, YRange, XPage и YPage объекта
TScroller. Поля, начинающиеся с буквы X, представляют горизон-
тальные значения, а начинающиеся с буквы Y - вертикальные.

Единицы прокрутки

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

Например, если вы выводите текст с шириной символа 8 элемен-
тов изображения и высотой 15, то в качестве значений XUnit и
YUnit полезно задать, соответственно, 8 и 15.

Строки, страницы и диапазон

Другие атрибуты прокрутки - строка, страница и диапазон -
выражаются в единицах прокрутки. Значения Line (строка) и Page
(страница) - это число единиц, на которые выполняется прокрутка в
ответ на запрос пользователя. Запрос может иметь форму щелчка
кнопкой "мыши" на концах полосы прокрутки (построчная прокрутка).
Щелчок "мышью" в самой полосе прокрутки (но не на маркере полосы
прокрутки) позволяет выполнять постраничную прокрутку. Атрибуты
диапазона (XRange, YRange) представляют общее число единиц, на
которое можно выполнять прокрутку. Обычно этот диапазон определя-
ется на основе размера редактируемого документа.


B.Pascal 7 & Objects/OW - 170 -


Типичный объект прокрутки

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

Типичные значения для окна редактирования Таблица 10.4
------------------T-------------T-------------------------------¬
¦ Поле ¦ Значение ¦ Смысл ¦
+-----------------+-------------+-------------------------------+
¦ XUnit ¦ 8 ¦ ширина символа ¦
¦ YUnit ¦ 15 ¦ высота символа ¦
¦ XLine, YLine ¦ 1 ¦ 1 единица на строку ¦
¦ XPage ¦ 40 ¦ 40 символов по горизонтали на¦
¦ ¦ ¦ страницу ¦
¦ YPage ¦ 50 ¦ 50 символов по вертикали на¦
¦ ¦ ¦ страницу ¦
¦ XRange ¦ 80 ¦ максимальный горизонтальный¦
¦ ¦ ¦ диапазон ¦
¦ YRange ¦ 400 ¦ максимальный вертикальный ди-¦
¦ ¦ ¦ апазон ¦
L-----------------+-------------+--------------------------------

Объект TScroller с данными значениями позволяет выполнять
построчную или постраничную прокрутку. С помощью полос прокрутки
или автоматической прокрутки выполняется просмотр всего файла.

Значения по умолчанию

По умолчанию XLine и YLine имеют значение 1, так что без яв-
ной необходимости устанавливать их в другие значения не нужно.
Для установки значений прокрутки на страницу также существует ис-
пользуемая по умолчанию схема, согласно которой страница прокрут-
ки будет соответствовать текущей высоте или ширине области клиен-
та окна (в зависимости от направлений прокрутки). Если вы не хо-
тите переопределить данный механизм, переустанавливать эти значе-
ния не требуется.



B.Pascal 7 & Objects/OW - 171 -

Задание для окна объекта прокрутки
-----------------------------------------------------------------

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

При использовании объекта прокрутки для автоматической прок-
рутки полосы прокрутки не требуются, но многие прокручиваемые
окна их имеют. Чтобы добавить в окно полосы прокрутки, добавьте
в поле Attr.Style ws_VScroll, ws_HScroll (или то и другое).

Приведем пример конструктора для текстового окна редактиро-
вания:

constructor TTextWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
Attr.Style := Attr.Style or ws_VScroll or ws_YScroll;
Scroller := New(PScroller, Init(@Self, 8, 15, 80, 400));
end;

В качестве аргументов TScroller воспринимает прокручиваемое
окно и начальные значения для полей XUnit, YUnit, XRange и YRange
соответственно. Атрибуты строки и страницы получают значения по
умолчанию.

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

Пример прокрутки
-----------------------------------------------------------------

Scroll - это полное приложение с графическим выводом, допус-
кающим прокрутку. Показанная ниже программа рисует последователь-
ность прямоугольников, затем увеличивает их размер, так что вся
картинка не умещается в область клиента окна, отображенного на
обычном экране VGA. С помощью полос прокрутки вы можете просмат-
ривать различные части рисунка или автоматически прокручивать
картинку, удерживая нажатой левую кнопку "мыши" и перемещая ее из
области клиента.

program Scroll;

uses Strings, WinTypes, WinProcs, OWindows;


B.Pascal 7 & Objects/OW - 172 -

type
TScrollApp = object(TApplication)
procedure InitMainWindow; virtual;
end;

PScrollWindow = ^TScrollWindow;
TScrollWindow = object(TWindow)
constructor Init(ATitle: PChar);
procedure Paint(PaintDC: HDC;
var PaintInfo: TPaintStruct); virtual;
end;

procedure TScrollApp.InitMainWindow;
begin
MainWindow := New(PScrollWindow, Init('Boxes'));
end;

constructor TScrollWindow.Init(ATitle: PChar);
begin
inherited Init(nil, ATitle);
Attr.Style := Attr.Style or ws_VScroll or ws_HScroll;
Scroller := New(PScroller, Init(@Self, 8, 15, 80, 60));
end;

procedure TScrollWindow.PAint(PaintDC: HDC;
var PaintInfo: TPaintStruct);
var X1, Y1, I: Integer;
begin
for I := 0 to 49 do
begin
X1 := 10 + I*8;
Y1 := 30 + I*5;
Rectangle(PaintDC, X1, Y1, X1 + X1, X1 + Y1 * 2);
end;
end;

var ScrollApp: TScrollApp;

begin
ScrollApp.Init('ScrollApp');
ScrollApp.Run;
ScrollApp.Done:
end.



B.Pascal 7 & Objects/OW - 173 -

Запрещение автоматической прокрутки
-----------------------------------------------------------------

Объект TScroller может по умолчанию выполнять автоматическую
прокрутку, но установка поля AutoMode TScroller в значение False
отключает это средство. Окно-владелец может сделать это в конс-
трукторе после построения объекта TScroller:

Scroller := New(PScroller, Init(@Self, 8, 15, 80, 60));
Scroller^.AutoMode :=False;

Если AutoMode равно False, то прокрутка может выполняться
только с помощью полос прокрутки. Полезная особенность автомати-
ческой прокрутки состоит в том, что чем дальше вы сдвинете "мышь"
от области клиента окна, тем быстрее будет происходить прокрутка
окна. В зависимости от удаления мыши приращение прокрутки будет
обратно пропорционально значению параметра строк и прямо пропор-
ционально значению параметра страницы.

Отслеживание полос прокрутки
-----------------------------------------------------------------

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

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

Scroller^.TrackMode:=False;

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



B.Pascal 7 & Objects/OW - 174 -

Модификация единиц прокрутки и диапазона
-----------------------------------------------------------------

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

Изменение диапазона

Метод SetRange воспринимает два целочисленных аргумента -
число горизонтальных и вертикальных единиц, которые определяют
общий диапазон прокрутки. Метод SetRange должен использоваться
при изменении размеров картинки. Например, при подготовке изобра-
жения картинки шириной 1 0 единиц и высотой 300, данная команда
установит диапазон прокрутки надлежащим образом:

Scroller^.setRange(100, 300);

Изменение единиц прокрутки

Если при инициализации объекта TScroller единицы неизвестны,
то их значения могут быть установлены непосредственно перед прок-
руткой. Например, они могут быть установлены методом окна
SetupWindow:

procedure ScrollWindow.SetupWindow;
begin
TWindow.SetupWindow;
Scroller^.XUnit:=10;
Scroller^.YUnit:=20;
end;

Изменение позиции прокрутки
-----------------------------------------------------------------

Windows с помощью методов ScrollTo и ScrollBy может выпол-
нять принудительную прокрутку. Каждый из них воспринимает два це-
лочисленных аргумента в терминах горизонтальных и вертикальных
единиц прокрутки. Например, если нужно переместиться к левому
верхнему углу картинки, то используется ScrollTo:

Scroller^.ScrollTo(0, 0);

Приведем другой пример. Если картинка имеет длину 400 единиц
в вертикальном направлении, то позицию прокрутки можно перемес-
тить к середине картинки следующим образом:

Scroller^.ScrollTo(0, 200);


B.Pascal 7 & Objects/OW - 175 -

Метод ScrollBy может перемещать позицию просмотра на задан-
ное число единиц вверх, вниз, влево или вправо. Отрицательные
значения осуществляют сдвиг к левому верхнему углу, а положитель-
ные - к правому нижнему. Если нужно сместиться на 10 единиц впра-
во и на 20 единиц вниз, то это можно сделать командой:

Scroller^.ScrollBy(10, 20);

Установка размеров страницы
-----------------------------------------------------------------

По умолчанию размер страницы (XPage и YPage) устанавливается
в соответствии с размером области клиента окна. При изменении
размеров окна механизм прокрутки учитывает эту информацию. Метод
окна WMSize вызывает метод прокрутки SetPageSize, который уста-
навливает поля объекта XPage и YPage на основании текущих разме-
ров области клиента окна и значений XUnit и YUnit. Для отмены
этого механизма и непосредственной установки размеров страницы вы
должны переписать унаследованный метод объекта окна WMSize и не
вызывать SetPageSize:

procedure TTestWindow.WMSize(var Msg: TMessage);
begin
DefWndProc(Msg);
end;

Затем вы можете непосредственно установить XPage и YPage в
конструкторе окна (или в производном конструкторе TScroller):

constructor ScrollWindow.Init(AParent:PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
Attr.Style:=Attr.Style or ws_VScroll or ws_HScroll;
Scroller:=New(PScroller, Init(@Self, 8, 15, 80, 400));
Scroller^.XPage:=40;
Scroller^.YPage:=100;
end;

Оптимизация методов Paint для прокрутки
-----------------------------------------------------------------

В приведенном выше примере рисуется 50 прямоугольников, но
не делается даже попытки определить, все ли прямоугольники видны
в области клиента окна. Это может привести к излишним усилиям на
дорисовку невидимых изображений. Для оптимизации рисования в окне
методом Paint можно использовать метод TScroller.IsVisibleRect.

Приведенный ниже метод ScrollWindow.Paint использует
IsVisibleRect для определения, нужно ли вызывать функцию Windows
Rectange. Rectange воспринимает аргументы в единицах устройства,
а VisibleRect в единицах прокрутки. С этой целью вершина прямоу-
гольника X1 Y1 и ширина прямоугольника (X2-X1) и его высота

B.Pascal 7 & Objects/OW - 176 -

(Y2-Y1) должны быть разделены на соответствующее число единиц до
вызова IsVisibleRect:

procedure TScrollWindow.Paint(PaintDC: HDC; var PaintInfo:
TPaintStruct);
var
X1, Y1, X2, Y2, I: Integer;
begin
for I:=0 to 49 do
begin
X1 := 10 + I * 8;
Y1 := 30 + I * 5;
X2 := X1 + X1;
Y2 := X1 + Y1 * 2;
if Scroller^.IsVisibleRect(X1 div 8,
Y1 div 15, (X2-X1) div 8,
(Y2-Y1) div 15) then
Rectangle(PaintDC, X1, Y1, X2, Y2);
end;
end;



B.Pascal 7 & Objects/OW - 177 -

------------------------------------------------------------------
Глава 11. Объекты диалоговых блоков
-----------------------------------------------------------------

Блоки диалога, или просто диалоги, являются интерфейсными
объектами, инкапсулирующими поведение диалоговых блоков. Это до-
черние окнам, которые обычно выводятся для выполнения специфичес-
ких задач (например, конфигурирования принтера или организации
ввода текста). Объект TDialog обеспечивает инициализацию, созда-
ние и исполнение всех типов блоков диалога. Для каждого типа диа-
лога вашего приложения, как и в случае оконных объектов, вы може-
те определить производные от TDialog диалоговые блоки.

ObjectWindows всегда предоставляет два типа диалогов наибо-
лее общего типа, ввод текста и диалог файла. Кроме того, в
ObjectWindows имеется тип TDlgWindow, который позволяет вам соз-
давать диалоги, поведение которых более похоже на окно.

Данная глава охватывает следующие темы:

* Использование объектов диалоговых блоков.
* Работа с управляющими элементами в диалоговых блоках.
* Связь объектов с управляющими элементами.
* Связь окон с ресурсами.

Использование объектов диалоговых блоков
-----------------------------------------------------------------

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

Подобно всплывающим окнам и управляющим элементам, диалого-
вые блоки являются дочерними окнами и при конструировании добав-
ляются к списку ChildList порождающих окон.

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

* Построение объекта.

* Выполнение диалогового окна.

* Закрытие диалогового окна.



B.Pascal 7 & Objects/OW - 178 -

Построение объекта
-----------------------------------------------------------------

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

Каждый ресурс диалогового блока имеет идентификатор, который
может быть номером идентификатора (Word) или строкой (PChar).
Этот идентификатор позволяет объекту диалогового блока задавать,
какой ресурс используется для определения его внешнего вида.

Вызов конструктора
-----------------------------------------------------------------

Чтобы построить объект диалогового блока, вызовите конструк-
тор Init. Init воспринимает в качестве своих параметров указа-
тель на порождающее окно и параметр типа PChar, представляющий
имя ресурса диалога:

ADlg:=New(PSampleDialog, Init(@Self, 'EMPLOYEEINFO'));

Если идентификатор задается номером, его требуется привести
с помощью MakeIntResource к PChar:

Dlg := New(PSampleDialog, Init(@Self, PChar(120)));

Так как диалоговые блоки обычно строятся внутри метода окон-
ного объекта, порождающее окно почти всегда задается как Self.
Объекты диалоговых блоков, не создаваемые оконными объектами,
должны иметь в качестве порождающего Applicartion^.MainWindow
(поскольку это единственный оконный объект, всегда присутствующий
в каждой программе ObjectWindows).

Выполнение диалоговых блоков
-----------------------------------------------------------------

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



B.Pascal 7 & Objects/OW - 179 -

Режимные и безрежимные диалоговые блоки
-----------------------------------------------------------------

Режимные диалоговые блоки являются наиболее общими блоками
диалога. Аналогично генерируемым функцией MessageBox блокам сооб-
щений, режимные диалоги отображаются для специфических целей на
короткий отрезок времени. Слово "режимный" означает, что пока
отображается диалог, пользователь не может выбрать или использо-
вать его порождающее окно. Пользователь должен воспользоваться
диалогом и выбрать командную кнопку OK или Cancel для прекращения
диалога и возвращению к работе с программой. Режимный диалог как
бы "замораживает" выполнение оставшейся части программы.

Безрежимный диалоговый блок не приостанавливает выполнения
программы. Как и оконный объект, он может создаваться и выпол-
няться в одном шаге с помощью MakeWindow:

Application^.MakeWindow(ADlg);

В любое момент вы можете считать данные из диалогового окна
(если объект диалогового блока еще существует). Чаще всего это
выполняется в методе OK, который вызывается при активизации поль-
зователем командной кнопки OK.

Выполнения режимных диалоговых блоков
-----------------------------------------------------------------

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

Объекты приложения имеют режимный эквивалент MakeWindow, ко-
торый называется ExecDialog. Аналогично MakeWindows, ExecDialog
проверяет допустимость передаваемого объекта диалогового блока
(то есть успешность выполнения конструктора объекта и отсутствие
ситуации нехватки памяти), а затем выполняет диалоговый блок, де-
лая его модальным.

ExecDialog возвращает целочисленное значение, указывающее,
что пользователь закрывает диалоговое окно. Возвращаемое значение
- это идентификатор задействованного пользователем управляющего
элемента, такой как id_Ok для командной кнопки OK или id_Cancel
для командной кнопки Cancel. После завершения выполнения диалого-
вого окна ExecDialog уничтожает объект диалогового окна.

Таким образом, с помощью одного вызова метода ExecDialog вы
можете создать, вывести на экран и завершить диалоговый блок.

ADlg := New(PSampleDialog, Init(@Self, 'RESOURCEID'));
ReturnValue := Application^.ExecDialog(ADlg);
if ReturnValue = id_OK then
{ кодирование для выборки данных и обработки диалога }

B.Pascal 7 & Objects/OW - 180 -

else
if ReturnValue = id_Cancel then { нажата Cancel }

Выполнение безрежимных диалоговых блоков
-----------------------------------------------------------------

Безрежимные диалоги похожи на всплывающие окна и управляющие
элементы. Основная причина, по которой вы не можете удалять без-
режимными диалогами сразу же после их отработки (в отличие от ре-
жимных), состоит в том, что вы заранее не знаете, когда пользова-
тель закроет блок диалога. (Помните о том, что в режимных диало-
гах метод ExecDialog не возвращает значения до закрытия диалога.)
Следовательно лучше всего конструировать безрежимные диалоги в
конструкторе его порождающего окна и хранить в поле порождающего
объекта.

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

constructor ParentWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
TWindow.Init(AParent, ATitle);
ADlg := New(PSampleDialog, Init(@Self, 'EMPLOYEEINFO'));
end;

Затем, каждый раз, когда вы хотите отобразить диалог, соз-
дайте и выведите его:

begin
Application^.MakeWindow(ADlg)
end;

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

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

Диалоговые блоки отличаются от других дочерних окон, таких
как всплывающие окна и управляющие элементы, тем, что они за вре-
мя существования своего порождающего окна создаются и уничтожают-
ся многократно и редко выводятся на экран и уничтожаются вместе с
порождающим окном. Обычно программа создает диалоговый блок в от-
вет на выбор меню, щелчок кнопкой "мыши", ошибку или другое собы-
тие.

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


B.Pascal 7 & Objects/OW - 181 -

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

Завершение диалогов
-----------------------------------------------------------------

Каждый блок диалога должен иметь способ его закрытия пользо-
вателем. Чаще всего это кнопки OK и/или Cancel. Потомки TDialog
автоматически отреагируют на нажатие одной из этих кнопок вызовом
метода EndDlg, который заканчивает диалог. Вы можете разработать
новые средства завершения диалога, если только они приводят к вы-
зову EndDlg. Для изменения поведения при закрытии вы можете пере-
определить методы OK и Cancel.

Например, вы можете переопределить метод OK таким образом,
что введенные данные будут копироваться в буфер, который находит-
ся вне объекта блока диалога. Если ввод был осуществлен некор-
ректно, вы можете вывести блок сообщения или сгенерировать звуко-
вой сигнал. Если ввод был сделан верно, вы можете вызвать EdnDlg.
Переданное в EndDlg значение становится возвращаемым значением
ExecDialog.

Как и в случае оконных объектов, объект диалога вызывает
CanClose до закрытия блока диалога, как это имело место для объ-
ектов окна. Вы можете переписать CanClose для учета условий зак-
рытия, как для блока диалога, который проверяет ввод пользовате-
ля. При переписывании CanClose нужно быть уверенным в том, что
вызывается унаследованный от него метод, т.к. он вызывает методы
CanClose дочерних окон.



B.Pascal 7 & Objects/OW - 182 -

Работа с управляющими элементами
-----------------------------------------------------------------

Все блоки диалога, кроме самых простейших, имеют (как дочер-
ние окна) несколько управляющих элементов (например, управления
редактированием, блоки списка и командные кнопки). Обратите вни-
мание на то, что эти управляющие элементы являются не объектами
управляющих элементов, а только управляющими интерфейсными эле-
ментами, без методов и полей объекта. Эта глава кроме того пока-
зывает альтернативные методы, позволяющие связывать объекты уп-
равления с элементами управления диалоговых блоков с использова-
нием InitResource.

Примечание: Использование управляющих объектов в окне
(но не блоков диалога) показано в Главе 12.

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

Взаимодействие с управляющим элементом
-----------------------------------------------------------------

Windows определят набор сообщений управляющих элементов, ко-
торые посылаются от приложения к Windows. Например, имеются сле-
дующие сообщения блока списка: lb_GetText, lb_GetCurSel и
lb_AddString. Сообщения управляющих элементов задают специфичес-
кое управление и несут с собой информацию в аргументах wParam и
lParam. Каждый управляющий элемент в ресурсе диалога имеет номер
идентификатора, который вы используете для задания управляющего
элемента, принимающего сообщение. Для посылки сообщения управляю-
щему элементу нужно вызвать метод TDialg SendDlgItemMsg. Напри-
мер, данный метод заполнит блок списка диалога элементами текста
путем посылки сообщения lb_AddString:

procedure TestDialog.FillListBox(var Msg: TMessage);
var
TextItem: PChar;
begin
TextItem := 'Item 1';
SendDlgItemMsg(id_LB1, lb_AddString, 0, Longint(TextItem));
end;

где id_LB1 есть константа, равная ID блока списка.

Если вам потребуется описатель одного из управляющих элемен-
тов диалога, его можно получить методом GetItemHandle:

GetItemHandle(id_LB1);


Реакция на сообщения управляющих элементов
-----------------------------------------------------------------

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

TTestDialog = object(TDialog)
procedure HandleBN1Msg(var Msg: TMessage); virtual
id_First + id_BN1;
procedure HandleListBox(var Msg: TMessage); virtual
id_First + id_LB1;
end;

В данном примере id_BN1 - это идентификатор кнопки управляю-
щего элемента, а id_LB1 - это идентификатор блока списка. Щелчок
"мышью" на командной кнопке даст сообщение, посылаемое в диалого-
вый блок. Объект диалогового блока реагирует через динамический
метод с индексом, основанным на идентификаторе кнопки IDBN1.

Примечание: Уведомляющие сообщения подробно поясняются
в Главе 16 "Сообщения Windows"

Каждое управляющее информационное сообщение поступает с ко-
дом уведомления - целочисленной константой, которая идентифициру-
ет произведенное действие. Например, результатом выбора элемента
из блока списка будет сообщение с кодом lbn_SelChange, где lbn_ -
уведомление блока списка (List Box Notification). Нажатие кнопки
"мыши" дает сообщение bn_Clicked. Ввод в управляющем элементе ре-
дактированием приводит к сообщению с кодом en_Changed. Имеются
коды уведомления для блоков списка, управляющих элементов редак-
тированием, комбинированных блоков и командных кнопок. Код уве-
домления передается в Msg.lParamHi сообщения. Для восприятия уп-
равляющих информационных сообщений напишем метод реакции для типа
диалога, обрабатывающий важные коды уведомления:

procedure TestDialog.HandleLB1Msg(var Msg: TMesage);
begin
case Msg.lParamHi of
lbn_SelChange: { изменение порядка выбора };
lbn_DblClk: { выбор с помощью двойного щелчка };
end;
end;
Управляющие элементы, имеющие соответствующие объекты, могут
отвечать на уведомления сами. См. Главу 16.

Пример связи
-----------------------------------------------------------------
В файле с текстом программы DIALTEST.PAS, основное окно име-

B.Pascal 7 & Objects/OW - 184 -

ет режимный диалог, определенный типом диалога TTestDialog. Эта
программа обеспечивает двухстороннюю связь между объектом диалога
и его управляющими элементами. Два метода - IDBN1 и IDLB1 - явля-
ются методами реакции, основанными на дочерних идентификаторах, и
вызываются при выборе пользователем управляющих элементов (дочер-
них окон). Например, при выборе пользователем кнопки диалога BN1
('Fill List Box') вызывается метод IDBN1. Аналогично, когда поль-
зователь делает выбор в блоке списка, вызывается IDLB1. С другой
стороны, для заполнения блока списка элементами текста код метода
IDBN1 посылает в диалог управляющее сообщение, lb_AddString, ис-
пользуя метод диалога SendDlgItemMsg,

Эта программа также показывает как путем создания нового ти-
па диалога и связывания его с ресурсом диалога в вызове конструк-
тора Init метода TestWindow.RunDialog создаются новые диалоги.
Полный текст программы вы можете найти на дистрибутивных дисках.

Ассоциирование объектов управляющих элементов
-----------------------------------------------------------------

До этого момента мы имели дело с реакцией блоков диалога на
управляющие информационные сообщения, которая использовала методы
реакции, основанные на дочерних идентификаторах. Однако, иногда
более предпочтительно, чтобы управляющий элемент сам реагировал
на сообщение. Например, вам может потребоваться управляющий эле-
мент редактирования, который позволяет вводить только цифры, или
командная кнопка, которая меняет стиль при своем "нажатии". Это
можно реализовать с помощью объектов управляющих элементов в ок-
нах (см. Главу 12). Однако, чтобы это имело место для управляющих
элементов диалога, созданного с файлом ресурса, вам нужно исполь-
зовать для конструирования объекта другой конструктор.

При организации связей вы создаете объект управляющего эле-
мента для представления управляющего объекта диалога. Этот объект
управления дает вам гибкость в реакции на управляющие сообщения.
Он дает вам возможность использования набор методов объектов уп-
равляющих элементов, описанных в Главе 12.

Для связи объекта с управляющим элементом определите сначала
объект управляющего элемента. Он должен быть создан в конструкто-
ре диалога. Однако, вместо того, чтобы использовать конструктор
Init, как это показано в Главе 12, следует использовать
InitResource, который берет в качестве параметров порождающее ок-
но и идентификатор управляющего элемента (из ресурса диалога).
Это приводит к вызову методов реакции на сообщения объектов уп-
равляющих элементов вместо обработки элементов по умолчанию. Для
этого нужно определить новый тип объекта, производный от предус-
мотренного типа управляющего элемента.

Обратите внимание, что в отличие от задания оконного объек-

B.Pascal 7 & Objects/OW - 185 -

та, которое предполагает два шага (Init и MakeWindow), поскольку
управляющий элемент уже существует, связь объекта с управляющим
элементов выполняется за один шаг: он загружается из диалогового
ресурса. Вам нужно только сообщить InitResource, какой управляю-
щий элемент из ресурса вы хотите связать с объектом, используя
идентификатор управляющего элемента.

Использование диалоговых окон
-----------------------------------------------------------------

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

Одним из подходов размещения управляющих элементов в окне
является использование объектов управляющих элементов (как пока-
зано в Главе 12). Другой подход - это слияние возможностей диало-
говых блоков и окон, как это делается в объектном типе
TDlgWindow, что позволяет получить гибридный объект, называемый
диалоговым окном. Второй подход предусматривает более удобный
способ построения и управления многими управляющими элементами в
окне. Кроме того, он предлагает для диалоговых блоков более гиб-
кие средства окон.

TDglWindow является потомком TDialog и наследует его методы,
такие как Execute, Create, Ok и EndDlg. Как и диалоговые блоки,
диалоговые окна имеют соответствующий ресурс диалогового блока. С
другой стороны, как и окна, диалоговые окна имеют соответствующий
класс окон, определяющий среди всего прочего пиктограмму, курсор
и меню. Из-за связи с оконным классом в потомке TDlgWindow следу-
ет переопределять методы GetClassName и GetWindowClass. Этот
класс должен быть тем же, что и перечисленный в диалоговом ресур-
се.

В большинстве случаев вы будете выполнять диалоговые окна
как и другие окна или безрежимные диалоговые окна с помощью мето-
дов Create и Show, а не метода Execute.

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



B.Pascal 7 & Objects/OW - 186 -

Использование предопределенных диалоговых окон
-----------------------------------------------------------------

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

Использование диалоговых блоков ввода
-----------------------------------------------------------------

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

Вы можете запускать диалоги ввода как режимные или безрежим-
ные диалоговые блоки, но обычно вы будете выполнять их как режим-
ные. С объектом диалога ввода связан ресурс диалога ввода. Он на-
ходится в файле ObjectWindows OSTDDLGS.RES.

Примечание: Использование модуля StdDlgs автоматически
включает ресурсы в OSTDDLGS.RES.

Каждый раз при конструировании диалога ввода с использовани-
ем метода Init, вы задаете для диалога заголовок, подсказку и
текст по умолчанию. Покажем вызов конструктора Init объекта диа-
лога ввода:

var SomeText: array[0..79] of Char;
begin
AnInputDlg.Init(@Self, 'Caption', 'Prompt', SomeText,
SizeOf(SomeText))
.
.
.
end;

B.Pascal 7 & Objects/OW - 187 -


В данном примере EditText - это текстовый буфер, который за-
полняется вводом пользователя, когда он "нажимает" кнопку OK.
Когда пользователь "нажимает" кнопку OK или клавишу Enter, строка
введенного в диалоге ввода текста автоматически передается в мас-
сив символов, который хранит текст по умолчанию. В данном примере
конструируется и отображается блок диалога и считывается текст:

procedure TSampleWindow.Test(var Msg: TMessage);
var
EditText: array[0..255] of Char;
begin
EditText:='Frank Borland';
if ExecDialog(New(PInputDialog, Init(@Self, 'Data Entry',
'Введите имя:', EditText, SizeOf(EditText)))) = id_OK then
MessageBox(HWindow, EditText, 'Имя =', mb_OK);
else MessageBox(HWindow, EditText,
'Имя пока имеет значение:',mb_OK);
end;



B.Pascal 7 & Objects/OW - 188 -

Файловые диалоговые блоки
-----------------------------------------------------------------

Файловые диалоговые блоки являются другим типом диалогов,
поставляемых с ObjectWindows в типе TFileDialog. Файловый диало-
говый блок следует использовать каждый раз, когда вы желаете по-
будить пользователя ввести имя файла, например в функциях File
Open и File Save во всех приложениях. См. Рис. 11.1.

------------------------------------------------------¬
¦-=---------------------File Open---------------------¦
+-----------------------------------------------------+
¦ ¦
¦ -------------------¬ -----------¬ ¦
¦ Имя файла: ¦ *.pas ¦ ¦----OK----¦ ¦
¦ L------------------- L----------- ¦
¦ -----------¬ ¦
¦ Каталог: a:\ ¦--Cancel--¦ ¦
¦ L----------- ¦
¦ Файлы: Каталоги: ¦
¦ ---------------T-¬ ---------------T-¬ ¦
¦ ¦collect3.pas ¦^¦ ¦[-a-] ¦^¦ ¦
¦ ¦collect4.pas +-+ ¦[-c-] +-+ ¦
¦ ¦diatest.pas ¦-¦ ¦[-f-] ¦-¦ ¦
¦ ¦edittest.pas ¦-¦ ¦[-g-] ¦-¦ ¦
¦ ¦ewndtest.pas ¦-¦ ¦[-h-] ¦-¦ ¦
¦ ¦helpwind.pas ¦-¦ ¦[-i-] ¦-¦ ¦
¦ ¦lboxtest.pas ¦-¦ ¦[-j-] ¦-¦ ¦
¦ ¦mditest.pas +-+ ¦[-k-] +-+ ¦
¦ ¦paltest.pas ¦v¦ ¦[-w-] ¦v¦ ¦
¦ L--------------+-- L--------------+-- ¦
¦ ¦
L------------------------------------------------------

Рис. 11.1 Файловый диалоговый блок.

В большинстве случаев файловые диалоговые блоки выполняются
как режимные. С объектом файлового диалога связан ресурс файлово-
го диалогового блока, имеющийся в ObjectWindows в файле
OSTDDLGS.RES. Использование модуля OStdDlgs автоматически включа-
ет файл ресурса.

B.Pascal 7 & Objects/OW - 189 -

Инициализация файлового диалогового блока
-----------------------------------------------------------------

TFileDialog определяет конструктор Init, который позволяет
задать маску файла и буфер для считывания имени файла. Маска фай-
ла (такая как '*.TXT') ограничивает файлы, перечисляемые в комби-
нированном блока (аналогично тому, как это делается в команде DOS
DIR *.TXT). Имя файла и маска передаются в записи типа
TFileDlgRec. Приведем пример вызова файлового диалогового блока
Init:

var
FileRec: TFileDlgRec;
IsOpen: Boolean;
begin
StrCopy(FileRec.Name, 'TEST1.TXT');
StrCopy(FileRec.Mask, 'C:\*.TXT');
IsOpen := True;
AFileDlg.Init(@Self, FileRec, IsOpen);
.
.
.
end;

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

Выполнение файловых диалоговых блоков
-----------------------------------------------------------------

Существует два вида файловых диалоговых блоков: диалоговый
блок открытия файла и диалоговый блок сохранения файла. Они раз-
личаются текстом кнопки в правом верхнем углу диалогового окна. В
зависимости от того, запрашивает пользователь открытие или сохра-
нение файла, на командной кнопке будет написано Open или Save.
Когда вы вызовите ExecDialog, то получите тип диалогового блока,
заданных в конструкторе IsOpen параметром типа Boolean. Если фай-
ловый диалоговый блок строится с IsOpen, установленным в True, то
диалоговый блок будет работать как диалоговый блок открытия фай-
ла. Если он строится с IsOpen, установленным в False, то файловый
диалоговый блок будет блоком сохранения файла.


B.Pascal 7 & Objects/OW - 190 -


Дополнительным средством файлового диалогового блока
ObjectWindows является то, что он выводит пользователю подсказку,
хочет ли пользователь сохранить файл с именем уже существующего
файла (см. Рис. 11.2). В другой раз вы можете запросить пользова-
теля, хочет ли он открыть новый файл или очистить текущий текст
без сохранения. Поскольку это должно происходить перед выводом
файлового диалогового блока, то не является частью поведения это-
го блока. В примере программы Steps в первой части данного руко-
водства перед загрузкой рисунка из файла проверяется метод
CanClose его основного окна.

--------------------------------------------¬
¦-=-------File exists! Overwrite it?--------¦
+-------------------------------------------+
¦ ¦
¦ C:\TEMP\NICELINE.PTS ¦
¦ ¦
¦ -----------¬ -----------¬ ¦
¦ ¦---Yes----¦ ¦---No-----¦ ¦
¦ L----------- L----------- ¦
¦ ¦
L--------------------------------------------

Рис. 11.2 Предупреждение пользователя о перезаписи существу-
ющих файлов.

File exists! Overwrite it? - файл существует, затереть его?

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

procedure TMyWindow.OpenSelectedFile;
var FileRec: TFileDlgRec;
begin
StrCopy(FileRec.Name, 'HEDGEHOG.PAS');
StrCopy(FileRec.Mask, '*.PAS');
if ExecDialog(New(PFileDialog,
Init(@Self, FileRec, True))) = id_Ok then
begin
Assign(AFile, StrPas(FileRec.Name));
.
.
.
end;
end;



B.Pascal 7 & Objects/OW - 191 -

------------------------------------------------------------------
Глава 12. Объекты управляющих элементов
-----------------------------------------------------------------

Windows предусматривает ряд стандартных интерфейсных элемен-
тов, называемых управляющими элементами. Управляющие элементы -
это специальные окна с некоторым предопределенным поведением.
ObjectWindows обеспечивает интерфейсные объекты для стандартных
управляющих элементов Windows, так что вы можете использовать эти
интерфейсные элементы в своих приложениях. Интерфейсные объекты
для управляющих элементов называются объектами управляющих эле-
ментов или просто управляющими объектами.

Примечание: Об интерфейсных объектах рассказывается в
Главе 9.

Данная глава охватывает следующие темы:

* Задачи, общие для всех управляющих объектов:

- построение и уничтожение объектов управляющих элементов;

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

* Установка и чтение значений управляющих элементов.

* Использование специализированных управляющих элементов.

Кроме того, в данной главе подробно описывается использова-
ние каждого интерфейсного объекта для стандартных управляющих
элементов Windows.

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

Управляющие элементы - это специализированные окна, которые
позволяют пользователю предопределенным образом задавать или вы-
бирать данные. Чаще всего управляющие элементы содержатся в диа-
логовом блоке. Диалоговый блок управляет их определением с по-
мощью ресурса диалогового блока, так что вам не потребуется часто
использовать в них объекты. Режимные диалоговые блоки не распола-
гают способами взаимодействия с управляющим объектом, поэтому в
диалоговых блоках объекты управляющих элементов используются
обычно для установки и считывания значений управляющих элементов
с помощью передачи. Передача для объектов управляющих элементов в
диалоговых блоках и в окнах выполняется одинаково (как описывает-
ся ниже в этой главе).

Примечание: Диалоговые блоки и их управляющие элементы
описываются в Главе 11 "Объекты диалоговых блоков".

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

B.Pascal 7 & Objects/OW - 192 -

равляющие элементы Windows, поддерживаемые типами объектов
ObjectWindows:

Управляющие элементы Windows,
поддерживаемые в ObjectWindows Таблица 12.1
----------------T------------T----------------------------------¬
¦ Управляющий ¦ Тип объекта¦ Использование ¦
¦ элемент ¦ ¦ ¦
+---------------+------------+----------------------------------+
¦ блок списка ¦TListBox ¦Прокручиваемый список элементов,¦
¦ ¦ ¦из которых можно сделать выбор. ¦
+---------------+------------+----------------------------------+
¦ полоса ¦TScrollBar ¦Полоса прокрутки, аналогичная¦
¦ прокрутки ¦ ¦тем, которые выводятся в прокру-¦
¦ ¦ ¦чиваемых окнах и блоках списка. ¦
+---------------+------------+----------------------------------+
¦ "нажимаемая" ¦TButton ¦Кнопка для "нажатия" со связанным¦
¦ кнопка ¦ ¦с ней текстом. ¦
+---------------+------------+----------------------------------+
¦ кнопка с ¦TCheckBox ¦Состоящая из блока кнопка, которая¦
¦ независимой ¦ ¦может выбираться или нет, со свя-¦
¦ фиксацией ¦ ¦занным текстом. ¦
+---------------+------------+----------------------------------+
¦ кнопка с ¦TRadioButton¦Кнопка, которая может выбираться¦
¦ зависимой ¦ ¦или нет. Обычно используется¦
¦ фиксацией ¦ ¦во взаимоисключающих группах. ¦
+---------------+------------+----------------------------------+
¦ блок группы ¦TGroupBox ¦Статический прямоугольник с текс-¦
¦ ¦ ¦том в левом верхнем углу. ¦
+---------------+------------+----------------------------------+
¦ управляющий ¦TEdit ¦Поле для ввода текста пользовате-¦
¦ элемент ¦ ¦лем. ¦
¦ редактирования¦ ¦ ¦
+---------------+------------+----------------------------------+
¦ статический ¦TStatic ¦Фрагмент отображаемого текста ¦
¦ управляющий ¦ ¦который не может быть изменен ¦
¦ элемент ¦ ¦пользователем. ¦
+---------------+------------+----------------------------------+
¦ Комбиниро- ¦TComboBox ¦Комбинация блока списка и управля-¦
¦ ванный блок ¦ ¦ющего элемента редактирования. ¦
L---------------+------------+-----------------------------------


B.Pascal 7 & Objects/OW - 193 -


-----------------------------------¬
Командная строка: ¦ ¦
L-----------------------------------
^
L редактируемый упрвляющий элемент

-----------¬ -----------¬
¦---OK-----¦ ¦--Cancel--¦ <- командные кнопки
L----------- L-----------

----T-----------------------------------------------T---¬
¦ < ¦-----------------------------------------------¦ > ¦
L---+-----------------------------------------------+----
^
полоса прокрутки --


---------------T-¬
¦collect3.pas ¦^¦ <- блок списка
¦collect4.pas +-+
¦diatest.pas ¦-¦
¦edittest.pas ¦-¦ -----------------¬
¦ewndtest.pas ¦-¦ ¦ *.txt ¦
¦helpwind.pas ¦-¦ L-T--------------+-¬
¦lboxtest.pas ¦-¦ ¦netlect3.txt ¦^¦
¦mditest.pas +-+ ¦netlect4.txt +-+
¦paltest.pas ¦v¦ ¦diatext.txt ¦-¦
L--------------+-- ¦readtxt.txt ¦-¦
¦vwndtext.txt ¦-¦
комбинированный блок -> ¦whelpwnd.txt ¦-¦
¦wboxtext.txt ¦-¦
¦ydrtest.txt +-+
¦xaltesx.txt ¦v¦
L--------------+--

Рис. 12.1 Стандартные управляющие элементы Windows.

B.Pascal 7 & Objects/OW - 194 -

Что такое объекты управляющих элементов?
-----------------------------------------------------------------

Для Windows управляющие элементы - это просто специализиро-
ванные виды окон. В ObjectWindows тип TControl является потомком
типа TWindow, так что большинство объектов управляющих элементов
можно использовать как все другие оконные объекты. Объекты управ-
ляющих элементов по способу их создания и уничтожения и способу
их поведения (как дочерние окна) аналогичны оконным объектам. Од-
нако они отличаются от других окон способом реакции на сообщения.
Например, методы Paint объектов управляющих элементов запрещены.
Windows берет на себя функции по отображению своих стандартных
управляющих элементов.

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

Тип TControl, как и TWindowsObject, является абстрактным
объектным типом. Вы можете создать экземпляры его потомков -
TListBox, TButton и другие - но не можете создать экземпляр
TControl.

Заметим, что вам, возможно, никогда не потребуется создавать
новый объектный тип, наследующий непосредственно из TControl.
TControl инкапсулирует свойства и стандартные управляющие элемен-
ты, о которых уже знает Windows. Создание специализированных уп-
равляющих элементов описывается в данной главе ниже.

Построение и уничтожение объектов управляющих элементов
-----------------------------------------------------------------

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

* Построение объекта управляющего элемента.

* Вывод управляющего элемента.

* Уничтожение управляющего элемента.



B.Pascal 7 & Objects/OW - 195 -

Построение объекта управляющего элемента
-----------------------------------------------------------------

Построение управляющих элементов отличается от построения
любых других дочерних окон. Обычно конструктор порождающего окна
вызывает конструкторы всех его дочерних окон. Однако в случае уп-
равляющих элементов не просто создается связь "родитель - пото-
мок", но устанавливается также связь "окно - управляющий эле-
мент". Это очень важно, поскольку кроме обычных связей между
предком и потомком управляющие элементы взаимодействуют с порож-
дающими окнами особыми способами (через уведомления).

Примечание: Уведомления описываются в Главе 16 "Сооб-
щения Windows".
Чтобы построить и инициализировать объект управляющего эле-
мента, нужно сделать следующее:

* добавить в объект порождающего окна поле (не обязательно);
* вызвать конструктор объекта управляющего элемента;
* изменить атрибуты управляющего элемента;
* инициализировать управляющий элемент в SetupWindows.

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

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

- объекта порождающего окна;
- идентификатора управляющего элемента;
- координату x верхнего левого угла;
- координату y верхнего левого угла;
- ширину;
- высоту.

TListBox.Init описывается следующим образом:

constructor TListBox.Init(AParent: PWindowsObject;
AnID: Integer; X, Y, W, H: Integer);

Все объекты управляющих элементов ObjectWindows (кроме
TMDIClient) требуют не менее 6 параметров. Большинство из них
воспринимают также параметр, задающий текст управляющего элемен-
та.

Присваивание полям объекта
-----------------------------------------------------------------
Часто при построении управляющего элемента в окне желательно

B.Pascal 7 & Objects/OW - 196 -

сохранять указатель на управляющий элемент в поле оконного объек-
та. Например, чтобы добавить в окно, определенное типом
TSampleWindow блок списка, вы можете задать в поле TSampleWindow
поле TheList и присвоить ему блок списка:

constructor SampleWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
TheList := New(PListBox,
Init(@Self, id_LB1, 20, 20, 100, 80));
end;

Порождающие окна автоматически поддерживают список своих до-
черних окон, включая управляющие элементы. Однако удобнее манипу-
лировать управляющими объектами, когда имеются соответствующие
поля объекта. Управляющие элементы, с которыми часто работать не
требуется (такие как статический текст или групповые блоки) могут
не иметь соответствующих полей.

При наличии поля объекта построение объекта управляющего
элемента не представляет труда. Например, чтобы добавить в
TSampleWindow групповой блок, нужно сделать следующее:

constructor SampleWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
TempGroupBox := New(PListBox,
Init(@Self, id_LB1, 'Group name',
140, 20, 100, 80));
end;



B.Pascal 7 & Objects/OW - 197 -

Изменение атрибутов объекта управляющего элемента
-----------------------------------------------------------------

Все управляющие объекты, кроме TMDIClient, получает от вызо-
ва TControl.Init используемые по умолчанию стили ws_Child и
ws_Visible. Если вы хотите изменить стиль управляющего элемента,
то можно изменить поле Attr.Style (как это описывается для окон в
Главе 10). Каждый тип управляющего элемента имеет также другие
стили, определяющие его конкретные характеристики.

Инициализация управляющего элемента
-----------------------------------------------------------------

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

При необходимости методом SetupWindow порождающего окна так-
же устанавливаются и заполняются управляющие элементы. Приведем
пример типичного метода SetupWindow:

procedure TSampleWindows.SetupWindow;
begin
inherited SetupWindow; { создает дочерние управляющие
элементы }
{ добавляет элементы в список }
TheList^.AddString('Элемент 1');
TheList^.AddString('Элемент 2');
end;

Заметим, что инициализация управляющего элемента, такая как
добавление строк в блок списка, должна выполняться в SetupWindow,
а не в конструкторе. Вызов такого метода как TListBox.AddString
приводит к передаче сообщений экранному управляющему элементу.
Так как экранный элемент до вызова наследуемого метода
SetupWindow не создается, попытки инициализации управляющих эле-
ментов до этого момента завершится неудачно.



B.Pascal 7 & Objects/OW - 198 -

Сохранение управляющих элементов
-----------------------------------------------------------------

Для вывода на экран управляющих элементов нет необходимости
вызывать метод Show. Как дочерние окна, они автоматически выво-
дятся на экран и повторно отображаются вместе с порождающим ок-
ном. Однако, вы можете использовать Show для сокрытия или вывода
управляющих элементов по запросу.

Уничтожение управляющих элементов
-----------------------------------------------------------------

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

Связь с управляющими элементами
-----------------------------------------------------------------

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

Работа с управляющими элементами окна
-----------------------------------------------------------------

Диалоговые окна работают с их управляющими элементами путем
передачи им сообщений с помощью метода SendDlgItemMsg с констан-
той управляющего сообщения (такой как lb_AddString) в качестве
параметра (см. Главу 11). Объекты управляющих элементов сильно
упрощают этот процесс путем использования методов (таких как
TListBox.AddString) для непосредственной работы с управляющими
элементами на экране.

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

TheListBox^.AddString('Scotts Valley');



B.Pascal 7 & Objects/OW - 199 -

Реакция на управляющие элементы
-----------------------------------------------------------------

Реакция на взаимодействие с пользователем с помощью управля-
ющих элементов несколько более сложна, чем просто вызов методов
объектов управляющих элементов. Чтобы узнать, как отвечать на со-
общения управляющих элементов, см. раздел "Команды, уведомления и
идентификаторы управляющих элементов" в Главе 16.

Действие, аналогичное диалоговому блоку
-----------------------------------------------------------------

Диалоговый блок с управляющими элементами позволяет пользо-
вателю с помощью клавиши Tab циклически перемещаться по всем эле-
ментам диалогового блока. Он может также использовать клавиши
стрелок для выбора в групповом блоке кнопок с зависимой фиксаци-
ей. Чтобы эмулировать этот клавиатурный интерфейс для окон с уп-
равляющими элементами, вызовите для оконного объекта в его конс-
трукторе метод EnableKBHandler объекта TWindowsObject.

Использование конкретных управляющих элементов
-----------------------------------------------------------------

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

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

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



B.Pascal 7 & Objects/OW - 200 -

Построение объектов блока списка
-----------------------------------------------------------------

Конструктор Init в TListBox воспринимает только шесть пара-
метров, которые необходимы всем объектам управляющих элементов.
Этими параметрами являются порождающее окно, идентификатор и раз-
меры управляющего элемента X, Y, W и H:

LB1 := New(PListBox, Init(@Self, id_LB1, 20, 20, 340, 100));

TListBox получает используемый по умолчанию стиль управляю-
щего элемента ws_Child or ws_Visible, затем прибавляется
lbs_Standard. lbs_Standard - это комбинация lbs_Notify (для полу-
чения уведомляющих сообщений), ws_VScroll (для получения верти-
кально полосы прокрутки), lbs_Sort (для сортировки списка элемен-
тов в алфавитном порядке) и ws_Border (для вывода рамки). Если вы
хотите получить другой стиль блока списка, то можете модифициро-
вать поле Attr.Style в TListBox. Например, для блока списка, не
сортирующего свои элементы, можно использовать следующее:

LB1 := New(PListBox, Init(@Self, id_LB1, 20, 20, 340, 100));
LB1^.Attr.Style := LB1^.Attr.Style and not lbs_Sort;

Модификация блоков списка
-----------------------------------------------------------------

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

Методы модификации блоков списка Таблица 12.2
---------------------------------T------------------------------¬
¦ Выполняемое действие ¦ Метод ¦
+--------------------------------+------------------------------+
¦ Добавление элемента ¦ AddString ¦
¦ Вставка нового элемента ¦ InsertString ¦
¦ Добавление элемента ¦ InsertString ¦
¦ Удаление элемента ¦ DeleteString ¦
¦ Удаление каждого элемента ¦ ClearList ¦
¦ Выбор элемента ¦ SetSellIndex или SetSelString¦
L--------------------------------+-------------------------------



Запрос в блоках списка
-----------------------------------------------------------------

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

Методы запроса блока списка Таблица 12.3
--------------------------------------------T-------------------¬
¦ Получаемая информация ¦ Вызываемый метод ¦
+-------------------------------------------+-------------------+
¦ Число элементов в списке ¦ GetCount ¦
¦ Элемент с конкретным индексом ¦ GetString ¦
¦ Длина конкретного элемента ¦ GetStringLen ¦
¦ Выбранный элемент ¦ GetSelString ¦
¦ Индекс выбранного элемента ¦ SEgSelIndex ¦
L-------------------------------------------+--------------------

Реакция на блок списка
-----------------------------------------------------------------

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

Пользователь может выполнять с блоком списка только следую-
щие действия: прокрутку списка, щелчок кнопкой "мыши" на элементе
списка, двойной щелчок кнопкой "мыши" на элементе. Когда выполня-
ется одно из этих действий, Windows посылает порождающему окну
блока списка уведомляющее сообщение блока списка. Обычно метод
реакции на уведомление для обработки сообщений для каждого управ-
ляющего элемента порождающего объекта определяется в порождающем
оконном объекте.

Каждое уведомляющее сообщение блока списка содержит в поле
lParamHi параметра Msg код уведомления (константу lbn_), который
специфицирует характер действия. Наиболее общие коды lbn перечис-
лены в следующей таблице:

Информационные сообщения блока списка Таблица 12.2
--------------T-------------------------------------------------¬
¦ wParam ¦ Действие ¦
+-------------+-------------------------------------------------+
¦lbn_SelChange¦Отдельным нажатием кнопки "мыши" был выбран¦
¦ ¦элемент. ¦
+-------------+-------------------------------------------------+
¦lbn_DblClk ¦Элемент был выбран двойным щелчком кнопки "мыши".¦
+-------------+-------------------------------------------------+
¦lbn_SetFocus ¦Пользователь переместил фокус на блок списка¦
¦ ¦простым или двойным нажатием кнопки "мыши", либо¦
¦ ¦клавишей Tab. Предшествует lbn_SelChange. ¦
L-------------+--------------------------------------------------

B.Pascal 7 & Objects/OW - 202 -


Приведем пример метода порождающего окна по обработке сооб-
щений блока списка:

procedure TLBoxWindow.HandleLB1Msg(var Msg: TMessage);
var
Idx: Integer;
ItemText: string[10]
begin
if Msg.lParamHi=lbn_SelChange then
begin
Idx:=LB1^.GetSelIndex;
if LB1^.GetStringLenIdx)<11 then
begin
LB1^.GetSelString(@ItemText, 10);
MessageBox(HWindow, @ItemText, 'Вы выбрали:', mb_OK);
end;
end;
else DefWndProc(Msg);
end;

Пользователь делает выбор, если Msg.lParamHi совпадает с
константой lbn_SelChange. Если это так, то берется длина выбран-
ной строки, проверяется, что она помещается в строку из 10 симво-
лов, и выбранная строка показывается в блоке сообщения.

Пример программы: LBoxTest
-----------------------------------------------------------------

Программа LBoxTest - это полная программа, которая создает
окно с блоком списка. После запуска приложения появляется основ-
ное окно с блоком списка. Когда пользователь выбирает элемент
блока списка, появляется диалог с выбранным элементом. Обратите
внимание на взаимоотношения между объектом окна и объектом блока
списка. Блок списка - это не просто дочернее окно основного окна,
основное окно владеет им как полем объекта. LB1 - это одно из по-
лей объекта основного окна, и оно содержит объект блока списка.
Полный текст программы содержится в файле LBOXTEST.PAS на ваших
дистрибутивный дискетах.


B.Pascal 7 & Objects/OW - 203 -

Использование статических управляющих элементов
-----------------------------------------------------------------

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

------------------------------------------------------------T-T-¬
¦-=------------------Static Control Tester------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ ¦
¦ Default Static Sample Text ¦
¦ ¦
¦ ss_Simple Sample Text ¦
¦ ¦
¦ ss_Left Sample Text ¦
¦ ¦
¦ ss_Center Sample Text ¦
¦ ¦
¦ ss_Right Sample Text ¦
¦ -------------------------------¬ ¦
¦ ss_BlackFrame ¦ ¦ ¦
¦ L------------------------------- ¦
¦ -------------------------------¬ ¦
¦ ss_BlackRect ¦------------------------------¦ ¦
¦ L------------------------------- ¦
¦ -------------------------------¬ ¦
¦ ss_GrayFrame ¦ ¦ ¦
¦ L------------------------------- ¦
¦ -------------------------------¬ ¦
¦ ss_GrayRect ¦------------------------------¦ ¦
¦ L------------------------------- ¦
¦ ¦
¦ ss_NoPrefix Sample & Text ¦
¦ ¦
L----------------------------------------------------------------

Рис. 12.2 Стили статических управляющих элементов.


B.Pascal 7 & Objects/OW - 204 -

Построение статических управляющих элементов
-----------------------------------------------------------------

Пользователь никогда не взаимодействует непосредственно со
статическими управляющими элементами, поэтому приложение будет
очень редко, если вообще будет, принимать уведомляющие сообщения
управляющих элементов относительно статического управляющего эле-
мента. Следовательно, большинcтво статических управляющих элемен-
тов можно сконструировать с идентификатором ресурса -1 или неко-
торым другим неиспользуемым числом.

Конструктор Init в TStatic конструирует новый объект стати-
ческого управления и описывается следующим образом:

constructor TStatic.Init(AParent: PWindowsObject;
AnID: Integer; ATitle: PChar;
X, Y, W, H: Integer; ATextLen: Word);

Кроме обычных параметров Init управляющего объекта,
TStatic.Init имеет два дополнительных параметра - текстовую стро-
ку ATitle и максимальную длину текста ATextLen. Текст должен за-
канчиваться нулевым символом, поэтому в действительности число
отображаемых символов на единицу меньше заданной в конструкторе
длины текста. Типичный вызов для построения статического управля-
ющего элемента может выглядеть так:

Stat1 := New(Static, Init(@Self, id_ST1, '&Text', 20, 50,
200, 24, 6));

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

Используемым по умолчанию стилем статического управляющего
элемента является назначенный по умолчанию стиль управляющего
элемента, то есть ws_Child or ws_Visible (выравнивание влево).
Чтобы изменить стиль, модифицируйте поле Attr.Style. Например,
чтобы центрировать текст управляющего элемента, сделайте следую-
щее:

Stat1^.Attr.Style := Stat1^.Attr.Style and (not ss_Left) or
ss_Center;

В статическом управляющем элементе есть возможность подчер-
кивания одного или нескольких символов в строке текста. Реализа-
ция и действие этого эффекта аналогичны подчеркиванию первого
символа в выборе меню: Insert и & должны непосредственно пред-
шествовать символу в строке, который будет подчеркиваться. Напри-
мер, для подчеркивания T в слове 'Text' нужно в вызове Init стро-
ку '&Text'. Если в строке вам нужно использовать &, применяйте
статический стиль Windows ss_NoPrefix (см. Рис. 12.2). Для уточ-
нения текущего текста, который хранится в статическом управляющем

B.Pascal 7 & Objects/OW - 205 -

элементе, используется метод GetText.

Модификация статического управляющего элемента

Для изменения текста статического управляющего элемента
TStatic имеет два метода. SetText устанавливает статический
текст, передаваемый аргументом PChar. Clear удаляет статический
текст. Однако, вы не можете сменить текст статического управляю-
щего элемента, созданный со стилем ss_Simple.

Опрос статических управляющих элементов

Чтобы считать текст, содержащийся в статическом управляющем
элементе, используйте метод GetText.

Пример программы StatTest
-----------------------------------------------------------------

Программа StatTest создает статическое тестовое приложение,
показанное на Рис.12.2. Обратите внимание на то, что метки
('Default Static' и 'ss_Simple') представляют собой статистичес-
кие управляющие элементы, также как и 'Sample Text', черные и се-
рые прямоугольники. Полный текст программы содержится в файле
STATTEST.PAS на ваших дистрибутивных дискетах.



B.Pascal 7 & Objects/OW - 206 -

Использование командных кнопок
-----------------------------------------------------------------

Управляющие элементы типа командных кнопок (которые иногда
называют "нажимаемыми" кнопками) выполняют некоторое действие при
"нажатии" такой кнопки. Есть два стиля командных кнопок, и оба
они имеют тип TButton. Эти два стиля - bs_PushButton и
DefPushButton. Используемые по умолчанию командные кнопки анало-
гичны командным другим кнопкам, но имеют жирную рамку и обычно
используются для указания реакции пользователя по умолчанию. На
Рис. 12.3 показан пример программы Windows, в которой используют-
ся обычные кнопки нажатия и командные кнопки по умолчанию.

----------------------------------T-¬
¦-=----------Hex Calculator-------¦v¦
+---------------------------------+-+
¦ ------------------¬ ¦
¦ ¦ 0 ¦ ¦
¦ L------------------ ¦
¦ ¦
¦ ----¬ ----¬ ----¬ ----¬ ----¬ ¦
¦ ¦¦D¦¦ ¦ E ¦ ¦ F ¦ ¦ + ¦ ¦ & ¦ ¦
¦ L---- L---- L---- L---- L---- ¦
¦ ----¬ ----¬ ----¬ ----¬ ----¬ ¦
¦ ¦ A ¦ ¦ B ¦ ¦ C ¦ ¦ - ¦ ¦ ¦ ¦ ¦
¦ L---- L---- L---- L---- L---- ¦
¦ ----¬ ----¬ ----¬ ----¬ ----¬ ¦
¦ ¦ 7 ¦ ¦ 8 ¦ ¦ 9 ¦ ¦ * ¦ ¦ ^ ¦ ¦
¦ L---- L---- L---- L---- L---- ¦
¦ ----¬ ----¬ ----¬ ----¬ ----¬ ¦
¦ ¦ 4 ¦ ¦ 5 ¦ ¦ 6 ¦ ¦ / ¦ ¦ < ¦ ¦
¦ L---- L---- L---- L---- L---- ¦
¦ ----¬ ----¬ ----¬ ----¬ ----¬ ¦
¦ ¦ 1 ¦ ¦ 2 ¦ ¦ 3 ¦ ¦ % ¦ ¦ > ¦ ¦
¦ L---- L---- L---- L---- L---- ¦
¦ ----¬ ----------¬ -----------¬ ¦
¦ ¦ 0 ¦ ¦ Back ¦ ¦ Equals ¦ ¦
¦ L---- L---------- L----------- ¦
L------------------------------------

Рис. 12.3 Программа Windows, использующая командные кнопки.



B.Pascal 7 & Objects/OW - 207 -

Построение командных кнопок
-----------------------------------------------------------------

Кроме обычных 6 параметров, конструктор Init объекта TButton
воспринимает текстовую строку типа PChar, AText и флаг типа
Boolean IsDefaultButton, указывающий, должна ли кнопка быть ис-
пользуемой по умолчанию или обычной командной кнопкой. Конструк-
тор Init объекта TButton описывается следующим образом:

constructor TButton.Init(AParent: PWindowsObject;
AnID: Integer; AText: PChar;
X, Y, W, H: Integer; IsDefault: Boolean);

Типичный конструктор для обычной кнопки выглядит так:

Push1 := New(PButton, Init(@Self, id_Push1, 'Test Button',
38, 48, 316, 24, False));

Реакция на командные кнопки
-----------------------------------------------------------------

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

Для организации реакции на сообщения кнопок нужно определить
основанный на дочернем идентификаторе метод для обработки каждой
кнопки. Например, следующий метод IDBut1 обрабатывает реакцию на
"нажатие" пользователем кнопки. Единственный код уведомления, оп-
ределенный в Windows для командных кнопок - это bn_Clicked, поэ-
тому код уведомления не нужно проверять.

type
TTestWindow = object(TWindow)
But1: PButton;
procedure IDBut1(var Msg: TMessage);
virtual id_First + idBut1;
.
.
.
end;

procedure TestWindow.IDBut1(var Msg: TMessage);
begin
MessageBox(HWindow, 'Clicked', 'The Button was:' mb_OK)
end;

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


B.Pascal 7 & Objects/OW - 208 -

Использование блоков выбора
-----------------------------------------------------------------

Тип TCheckBox наследует от TButton, а тип TRadioButton - от
TCheckBox. Кнопки с зависимой и независимой фиксацией мы будем
иногда кратко называть блоками выбора.

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

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

Однако, вы можете для выполнения ими некоторых действий при
нажатии создать типы, производные от TCheckBox и TRadioButton.
Если ваш тип определяет метод для nf_First + bn_Clicked, то он
сначала должен вызывать метод реакции BNClicked, а уже затем вы-
полнять любые дополнительные действия.

Построение кнопок с зависимой и независимой фиксацией
-----------------------------------------------------------------

Кроме обычных 6 параметров, конструктор Init для кнопок с
зависимой и независимой фиксацией воспринимает текстовую строку и
указатель на объект группового блока (см. "Групповые блоки"), ко-
торый логически и визуально выделяет кнопки. AGroup - это указа-
тель на объект группового блока. Если AGroup имеет значение nil,
то блок выбора не является частью какой-либо логической группы.
Конструкторы описываются следующим образом:

constructor Init(AParent: PWindowsObject; AnID: Integer;
ATitle: PChar; X, Y, W, H: Integer;
AGroup: PGroupBox);

Для обоих видов блоков выбора синтаксис идентичен. Конструк-
торы различаются только присваиваемым стилем, используемым по
умолчанию. Типичное использование конструкторов блока выбора име-
ет вид:

GroupBox1 := New(PGroupBox, Init(@Self, id_GB1,
'A Group Box', 38, 102, 176, 108));

B.Pascal 7 & Objects/OW - 209 -

ChBox1 := New(PCheckBox, Init(@Self, id_Check1,
'Check Box Text', 235, 12, 150, 26, GroupBox1));

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

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



B.Pascal 7 & Objects/OW - 210 -

Модификация блоков выбора
-----------------------------------------------------------------

Модификация (выбор или отмена выбора) блоков выбора выглядит
задачей пользователя программы, а не вашей. Но в некоторых случа-
ях программе требуется явно управлять состоянием блоков выбора.
Одним из таких случаев является вывод на экран параметров, кото-
рые были выбраны и сохранены ранее. Для модификации состояния
кнопки с независимой фиксацией TCheckBox определяет 4 метода:

Методы модификации кнопок с независимой фиксацией Таблица 12.5
----------------------------T-----------------------------------¬
¦ Выполняемое действие ¦ Вызов метода ¦
+---------------------------+-----------------------------------+
¦ Выбор кнопки ¦ Check или SetCheck(bf_Chacked) ¦
¦ Отмена выбора кнопки ¦ Uncheck или SetCheck(bf_Unchecked)¦
¦ Переключение кнопки ¦ Toggle ¦
L---------------------------+------------------------------------

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

Опрос блоков выбора
-----------------------------------------------------------------

Опрос блока выбора - это один из способов выяснения его сос-
тояния и организации реакции на него. Кнопки с зависимой и неза-
висимой фиксацией имеют два состояния: выбранные и невыбранные.
Для получения состояния блока выбора используется метод GetCheck
типа TheckBox:

MyState:=Check1^.GetCheck;

Для определения состояния блока возвращаемое GetCheck значе-
ние можно сравнить с заданными константами bf_Unchecked,
bf_Checked и bf_Grayed.

Примечание: Использование кнопок обоих видов показано
в примере программы BtnTest на ваших дистрибутивных дисках.

Использование групповых блоков
-----------------------------------------------------------------

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



B.Pascal 7 & Objects/OW - 211 -

Построение групповых блоков
-----------------------------------------------------------------

Конструктор Init группового блока кроме обычных 6 параметров
воспринимает текстовую строку метки группы.

constructor TGroupBoxInit(AParent: PWindowsObject;
AnID: Integer;
AText: PChar; X, Y, W, H: Integer);

Типичное использование конструктора группового блока может
быть следующим:

GroupBox1 := New(PGroupBox, Init(@Self, id_GB1, 'A Group Box',
38, 102, 176, 108));

Группирование управляющих элементов
-----------------------------------------------------------------

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

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

type
TSomeWindow = object(TWindow)
Group: PGroupBox;
FirstCheck, SecondCheck: PCheckBox:
constructor Init(AParent: PWindowsObject,
ATitle: PChar);
end;

constructor TSomeWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
Group := New(PCheckBox, Init(@Self, id_TheGroup,
'Various boxes', 10, 01, 100, 50));
FirstCheck := New(PCheckBox, Init(@Self, id_FirstCheck,
'One', 15, 20, 90, 10, Group));
SecondCheck := New(PCheckBox, Init(@Self, id_SecondCheck,
'Two', 15, 20, 90, 10, Group));
end;


B.Pascal 7 & Objects/OW - 212 -

Заметим, что передаваемый блоку выбора параметр группы - это
указатель на объект блока группы, а не идентификатор группового
управляющего элемента (как в API Windows). Использование указате-
ля позволяет вам строить объекты перед созданием методом
SetupWindows порождающего окна экранных элементов.



B.Pascal 7 & Objects/OW - 213 -

Реакция на групповые блоки
-----------------------------------------------------------------

Когда происходит событие, которое может изменить выбор блока
группы (например, "нажатие" пользователем кнопки или вызов прог-
раммой метода Check), порождающее окно блока группы принимает со-
общение, основанное на дочернем идентификаторе. Порождающий объ-
ект воспринимает сообщение, используя сумму id_First и идентифи-
катора группового блока. Это позволяет вам определить методы для
каждой группы вместо их задания для каждого блока выбора в груп-
пе.

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

Пример программы: BtnTest
-----------------------------------------------------------------

BtnTest - это полная программа, которая создает окно с ко-
мандной кнопкой, кнопками с зависимой и независимой фиксацией и
блоком группы управляющих элементов. После запуска приложения по-
является основное окно с управляющими элементами. Когда пользова-
тель "нажимает" на управляющий элемент, приложение реагирует на
это различными способами. См. Рис. 12.4.

Примечание: Полный текст программы содержится в файле
BTNTEST.PAS на ваших дистрибутивных дискетах.

------------------------------------------------------------T-T-¬
¦-=--------------------Button Tester------------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ ¦
¦ ----¬ ¦
¦ ¦ X ¦ Текст кнопки с независимой фиксацией ¦
¦ L---- ¦
¦ -----------------------------------------------------------¬ ¦
¦ ¦-----------Состояние кнопки с независимой фиксацией-------¦ ¦
¦ L----------------------------------------------------------- ¦
¦ ¦
¦ --Групповой блок-------------------------------¬ ¦
¦ ¦ ( ) Кнопка с зависимой фиксацией 1 ¦ ¦
¦ ¦ (*) Кнопка с зависимой фиксацией 2 ¦ ¦
¦ L----------------------------------------------- ¦
L----------------------------------------------------------------

Рис. 12.4 Окно с различными видами кнопок.


B.Pascal 7 & Objects/OW - 214 -

Использование полос прокрутки
-----------------------------------------------------------------

Полосы прокрутки являются важнейшим механизмом изменения об-
зора пользователем окна приложения, блока списка или комбиниро-
ванного блока. Однако, может возникнуть ситуация, когда нужна от-
дельная полоса прокрутки для выполнения некоторой специализиро-
ванной задачи (например, управление температурой в программе тер-
мостата или цветом в программе рисования). Когда нужна отдельная
специализированная полоса прокрутки, используются объекты
TScrollBar. Рис. 12.5 показывает типичное использование объекта
TSсrollBar.

------------------------------------------------------------T-T-¬
¦-=-----------------------Thermostat------------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ ¦
¦ 68 градусов ¦
¦ ¦
¦ ¦
¦ ¦
¦ ---T----------------------------------------------------T--¬ ¦
¦ ¦<-¦----------------------------------------------------¦->¦ ¦
¦ L--+----------------------------------------------------+--- ¦
¦ ¦
L----------------------------------------------------------------

Рис. 12.5 Объект полосы прокрутки.

Построение полос прокрутки
-----------------------------------------------------------------

Кроме обычных 6 параметров управляющего объекта, конструктор
Init полосы прокрутки воспринимает флаг типа Boolean, указываю-
щий, является ли полоса прокрутки горизонтальной. Приведем описа-
ние конструктора полосы прокрутки:

constructor TScrollBarInit(AParent: PWindowsObject;
AnID: Integer; X, Y, W, H: Integer;
IsHScrollBar: Boolean);

Если вы зададите нулевую ширину вертикальной полосы прокрут-
ки, Windows присвоит ей стандартную ширину (аналогичную полосе
прокрутки блока списка). То же самое касается задания нулевой вы-
соты горизонтальной полосы прокрутки. Вызов:

ThermScroll := New(PScrollBar, Init(@Self, id_ThermScroll,
20, 170, 340, 0, True));

создает горизонтальную полосу прокрутки стандартной высоты, как
это показано на Рис. 12.5. Init конструирует полосы прокрутки со
стилями ws_Child, ws_Visible и sbs_Horz или sbs_Vert для горизон-
тальной или вертикальной полосы прокрутки соответственно. Разно-

B.Pascal 7 & Objects/OW - 215 -

образные полосы прокрутки показаны на Рис. 12.6.

------------------------------------------------------------T-T-¬
¦-=--------------------Scroll Bar Tester--------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ ---¬ --¬ ¦
¦ ---T--¦/\¦---------------------------T--¬ ¦^¦ ¦
¦ ¦/-¦--+--+---------------------------¦-\¦ +-+ ¦
¦ ¦\-¦--¦--¦---------------------------¦-/¦ ¦-¦ ¦
¦ L--+--¦--¦---------------------------+--- ¦-¦ ¦
¦ ¦--¦ ¦-¦ ¦
¦ ¦--¦ ¦-¦ ¦
¦ ¦--¦ +-+ ¦
¦ +--+ ¦v¦ ¦
¦ ¦\/¦ L-- ¦
¦ L--- ¦
¦ ---T----------------------------------------------------T--¬ ¦
¦ ¦<-¦----------------------------------------------------¦->¦ ¦
¦ L--+----------------------------------------------------+--- ¦
¦ ¦
¦ ¦
L----------------------------------------------------------------

Рис. 12.6 Окно с разнообразными полосами прокрутки.

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

Один из атрибутов полосы прокрутки, инициализируемый при ее
конструировании, это диапазон. Диапазон полосы прокрутки - это
набор всевозможных положений указателя (маркера полосы прокрут-
ки). Маркер полосы прокрутки - это подвижный прямоугольник, кото-
рый пользователь может перемещать по ней. Каждой позиции соот-
ветствует целое число. Порождающее окно использует эту целую ве-
личину, позицию, для установки и запроса по полосе прокрутки.
После конструирования объекта полосы прокрутки его диапазон уста-
навливается от 1 до 100.

Положению маркера в "самой верхней" позиции (вершина верти-
кальной полосы прокрутки или крайнее левое положение горизонталь-
ной полосы прокрутки) соответствует позиция 1. "Самой нижней" по-
зиции маркера соответствует позиция 100. Для установки иного диа-
пазона нужно использовать метод SetRange, описанный в разделе
"Модификация полосы прокрутки".



B.Pascal 7 & Objects/OW - 216 -

Управление параметрами полосы прокрутки
-----------------------------------------------------------------

Два других атрибута объекта полосы прокрутки - это его при-
ращение по строкам и страницам. Приращение по строкам, установ-
ленное в 1, это расстояние в единицах диапазона, на которое пере-
местится указатель при нажатии пользователем стрелок на полосе
прокрутки. Приращение по страницам, установленное в 10, это расс-
тояние в единицах диапазона, на которое переместится указатель
при нажатии пользователем в области прокрутки. Эти значения можно
изменить непосредственной модификацией полей объекта TScrollBar,
LineSize и PageSize.

Опрос полосы прокрутки
-----------------------------------------------------------------

TScrollBar определяет два метода опроса полосы прокрутки:
GetRange и GetPosition. Метод GetRange - это процедура, использу-
ющая два целочисленных переменных аргумента. Процедура заносит в
эти целые значения верхнюю и нижнюю позиции из диапазона полосы
прокрутки. Этот метод очень удобен, когда нужно, чтобы ваша прог-
рамма переместила указатель в его верхнюю или нижнюю позицию.

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

Модификация полос прокрутки
-----------------------------------------------------------------

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

Методы модификации полос прокрутки Таблица 12.6
---------------------------------------T------------------------¬
¦ Выполняемое действие ¦ Вызываемый метод ¦
+--------------------------------------+------------------------+
¦ Задание диапазона прокрутки ¦ SetRange ¦
¦ Установка позиции маркера ¦ SetPosition ¦
¦ Перемещение позиции маркера ¦ DeltaPos ¦
L--------------------------------------+-------------------------

SetRange - это процедура, которая воспринимает два целочис-
ленных аргумента, наименьшую и наибольшую позицию диапазона. По
умолчанию новая полоса прокрутки имеет диапазон от 1 до 100. Вы
можете изменить этот диапазон для наилучшего расположения управ-
ляющих элементов полос прокрутки. Например, полоса прокрутки в
приложении для термостата может иметь диапазон от 32 до 120 гра-
дусов Фаренгейта:

ThermScroll^.SetRange(32, 120);

B.Pascal 7 & Objects/OW - 217 -



SetPosition - это процедура, которая воспринимает один цело-
численый аргумент - позицию, в которую нужно переместить указа-
тель полосы прокрутки. В рассмотренном ранее приложении для тер-
мостата, ваша программа может непосредственно установить темпера-
туру 78 градусов:

ThermScroll^.SetPosition(78);

Третий метод DeltaPos передвигает позицию указателя полосы
прокрутки вверх (налево) или вниз (направо) на величину, заданную
целым аргументом. Положительная целая величина перемещает указа-
тель вниз (направо). Отрицательная целая величина перемещает его
вверх (налево). Например, для уменьшения температуры термостата
на 5 градусов используется:

ThermScroll^.DeltaPos(-5);

Реакция на полосы прокрутки
-----------------------------------------------------------------

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

Однако, уведомляющие сообщения полосы прокрутки несколько
отличаются от других уведомляющих сообщений элемента управления.
Они основаны на сообщениях Windows wm_HScroll и wm_VScroll, а не
wm_Command. Единственное отличие, на которое нужно обратить вни-
мание состоит в том, что уведомляющие коды полосы прокрутки запи-
саны в Msg.wParam, а не в Msg.lParamHi.

Чаще всего встречаются коды sb_LineUp, sb_LineDown,
sb_PageUp, sb_PageDown, sb_ThumbPosition и sb_ThumbTrack. Наибо-
лее часто вы будете реагировать на каждое событие проверкой новой
позиции полосы прокрутки и организацией соответствующего дейс-
твия. В данном случае вы можете игнорировать уведомляющий код.
Например:

procedure TestWindow.HandleThermScrollMsg(var Msg:
TMessage);
var
NewPos: Integer;
begin
NewPos:=ThermScroll^.GetPosition;
{ обработка с помощью NewPos }
end;

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

B.Pascal 7 & Objects/OW - 218 -

его нового местоположения. В этом случае нужно реагировать на со-
общение с кодом sb_ThumbTrack.

procedure TestWindow.HandleThermScrollMsg(var Msg:
TMessage);
var
NewPos: Integer;
begin
if Msg.wParam <> sb_ThumbTrack
then begin
NewPos:=ThermScroll^.GetPosition;
{ некоторая обработка на основе NewPos. }
end;
end;

Иногда может потребоваться, чтобы объекты полосы прокрутки
сами реагировали на уведомляющие сообщения полосы прокрутки. При
этом конкретная реакция поведения должна быть встроена в объект
полосы прокрутки. Для программирования объекта полосы прокрутки,
который непосредственно реагировал бы на его информационные сооб-
щения, нужно определить для его типа метод реакции, основанный на
информации. В качестве идентификатора заголовка метода нужно ис-
пользовать сумму nf_First и информационного кода полосы прокрут-
ки. Этот процесс описан в разделе "Уведомляющие сообщения управ-
ляющих элементов" Главы 16.

Пример программы: SBarTest
-----------------------------------------------------------------

Программа SBarTest создает приложение для термостата, пока-
занное на Рис. 12.5. Полный текст программы содержится в файле
SBARTEST.PAS на ваших дистрибутивных дискетах.

Использование управляющих элементов редактирования
-----------------------------------------------------------------

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

- Ввод текста пользователем.
- Динамическое отображение текста приложением.
- Вырезание, копирование и вставка в буфер вырезанного изоб-
ражения.
- Многострочное редактирование (удобно для текстовых редак-
торов).


B.Pascal 7 & Objects/OW - 219 -

На Рис. 12.7 показано окно с двумя управляющими элементами
редактирования.

------------------------------------------------------------T-T-¬
¦-=------------------Edit Control Tester--------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ ¦
¦ Оригинал: Копия: ¦
¦ -----------------------¬ ----¬ -----------------------¬ ¦
¦ ¦Default Text ¦ ¦->-¦ ¦DEFAULT.TEXT ¦ ¦
¦ L----------------------- L---- L----------------------- ¦
¦ ¦
¦ ¦
L----------------------------------------------------------------

Рис. 12.7 Окно с управляющими элементами редактирования.



B.Pascal 7 & Objects/OW - 220 -

Построение управляющих элементов редактирования
-----------------------------------------------------------------

Конструктор Init управляющего элемента редактирования анало-
гичен конструктору статического управляющего элемента и восприни-
мает 6 обычных параметров, плюс начальная текстовая строка, мак-
симальная длина строки и флаг Multiline типа Boolean. Конструктор
TEdit описывается следующим образом:

constructor TEdit.Init(AParent: PWindowsObject;
AnID: Integer; ATitle: PChar;
X, Y, W, H, ATextLen: Integer; Multiline: Boolean);

По умолчанию управляющий элемент редактирования имеет стили
ws_Child, ws_Visible, es_TabStop, es_Left и es_AutoHScroll. Так
как управляющий элемент должен включать в себя завершающий нуле-
вой символ, параметр длины текста на самом деле на 1 превышает
максимальное число символов, допустимых в строке редактирования.

Если Multiline имеет значение True, то управление редактиро-
ванием имеет стиль es_MultiLine, es_AutoVScroll, ws_VScroll и
ws_HScroll. Приведем типичные конструкторы управляющих элементов
редактирования (один для однострочного элемента, другой - для
многострочного):

EC1 := New(PEdit, Init(@Self, id_EC1, 'Default Text', 20, 50,
150, 30, 40, False));
EC2 := New(PEdit, Init(@Self, id_EC2, '', 20, 20, 200, 150,
40, True));

Использование буфера вырезанного изображения и меню Edit
-----------------------------------------------------------------

Вы можете передавать текст непосредственно между объектом
управляющего элемента редактирования и буфером вырезанного изоб-
ражения Windows, используя для этого вызовы методов. Часто вам
бывает нужно предоставить пользователю доступ к этим методам че-
рез меню редактирования. Объект управляющего элемента редактиро-
вания автоматически отреагирует на выбор из меню таких вариантов,
как Edit¦Copy и Edit¦Undo. TEdit определяет основанные на коман-
дах методы (например, CMEditCopy и CMEditUndo), которые вызывают-
ся в ответ на конкретный выбор (команду) меню в порождающем окне
управляющего элемента редактирования. CMEditCopy вызывает Copy, а
CMEditUndo вызывает Undo.


B.Pascal 7 & Objects/OW - 221 -


Следующая таблица содержит список методов, которые вызывают-
ся в ответ на выбор пункта меню:

Управляющие элементы редактирования и меню Edit Таблица 12.7
------------------------T-------------------T-------------------¬
¦ Операция ¦ Метод TEdt ¦ Команда меню ¦
+-----------------------+-------------------+-------------------+
¦ Копирование текста в ¦ Cut ¦ cm_EditCut ¦
¦ буфер вырезанного ¦ ¦ ¦
¦ изображения. ¦ ¦ ¦
+-----------------------+-------------------+-------------------+
¦ Вырезание текста в ¦ Copy ¦ cm_EditCopy ¦
¦ буфер вырезанного ¦ ¦ ¦
¦ изображения. ¦ ¦ ¦
+-----------------------+-------------------+-------------------+
¦ Вставка текста из ¦ Paste ¦ cm_EditPaste ¦
¦ буфера вырезанного ¦ ¦ ¦
¦ изображения. ¦ ¦ ¦
+-----------------------+-------------------+-------------------+
¦ Очистка всего элемента¦ Clear ¦ cm_EditClear ¦
¦ редактирования. ¦ ¦ ¦
+-----------------------+-------------------+-------------------+
¦ Удаление выделенного ¦ DeleteSelection ¦ cm_EditDelete ¦
¦ текста. ¦ ¦ ¦
+-----------------------+-------------------+-------------------+
¦ Отмена последнего ¦ Undo ¦ cm_EditUndo ¦
¦ редактирования. ¦ ¦ ¦
L-----------------------+-------------------+--------------------

Чтобы добавить в окно меню редактирования, содержащее управ-
ляющий элемент редактирования, определите для окна с помощью ко-
манд, перечисленных в Таблице 12.7, ресурс меню. Никаких новых
методов вам писать не нужно.

Имеется также один дополнительный метод в виде булевской
функции CanUndo, который определяет, можно ли отменить последнюю
операцию редактирования.



B.Pascal 7 & Objects/OW - 222 -

Опрос управляющих элементов редактирования
-----------------------------------------------------------------

Иногда нужно организовать опрос управляющих элементов редак-
тирования для проверки допустимости введенного текста, записи
ввода для его последующего использования или копирования ввода в
другой управляющий элемент. TEdit поддерживает несколько методов
опроса. Многие из опросов управляющих элементов редактирования и
методов модификации возвращают или требуют от вас указать номер
строки или позицию символа в строке. Все эти индексы начинаются с
нуля. Другими словами, первая строка - это нулевая строка, а пер-
вый символ в любой строке это нулевой символ. Самыми важными ме-
тодами запроса являются GetText, GetLine, NumLines и LineLength.

Методы опроса управляющих элементов редактирования Таблица12.8
-------------------------------------------T--------------------¬
¦ Выполняемое действие ¦ Вызываемый метод ¦
+------------------------------------------+--------------------+
¦ Определение изменения текста ¦ IsModified ¦
¦ Считывание всего текста ¦ GetText ¦
¦ Считывание строки ¦ GetLine ¦
¦ Получение числа строк ¦ GetNumLines ¦
¦ Получение длины данной строки ¦ GetLineLength ¦
¦ Получение индекса выделенного текста ¦ GetSelection ¦
¦ Получение диапазона символов ¦ GetSubText ¦
¦ Подсчет символов перед строкой ¦ LineIndex ¦
¦ Поиск строки, содержащей индекс ¦ GetLineFromProc ¦
L------------------------------------------+---------------------

Вы можете заметить, что методы запросов TEdit, которые возв-
ращают текст из управляющего элемента редактирования, сохраняют
форматирование текста. Это важно только для многострочных управ-
ляющих элементов редактирования, которые допускают появление нес-
кольких строк текста. В этом случае возвращаемый текст, который
занимает несколько строк в управляющем элемента редактирования
содержит в конце каждой строки два дополнительных символа: возв-
рат каретки (#13) и смена строки (#10). Если этот текст снова по-
мещается в управляющий элемент редактирования, вставляется из бу-
фера вырезанного изображения, записывается в файл или выводится
на принтер, то строки разбиваются так, как это было в управляющем
элемента редактирования.

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

B.Pascal 7 & Objects/OW - 223 -


procedure TTestWindow.ReturnText(RetText: PChar);
var TheText: array[0..20] of Char;
begin
if EC1^.GetText(@TheText, 20) then
RetText:=@TheText
else RetText:=nil;
end;

procedure TTestWindow.ReturnText(RetText: PChar);
var TheText: array[0..20] of Char;
begin
RetText:=nil;
with EC^ do
if NumLines >= LineNum then
if LineLength(LineNum) < 11 then
if GetLine(@TheText, 20, LineNum) then
RetText := @TheText;
end;

procedure TestWindow.ReturnLineText(RetText: PChar;
LineNum: Integer);
var
TheText: array[0..20] of Char;
begin
with EC1^ do
begin
GetSelection(SelStart, SelEnd);
GetSubText(TheText, SelStart, SelEnd);
end;
RetText := TheText;
end;

Модификация управляющих элементов редактирования
-----------------------------------------------------------------

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

Методы модификации
управляющих элементов редактирования Таблица 12.9
-----------------------------------------T----------------------¬
¦ Выполняемое действие ¦ Вызываемый метод ¦
+----------------------------------------+----------------------+
¦ Удаление всего текста ¦ Clear ¦
¦ Удаление выделенного текста ¦ DeleteSelection ¦

B.Pascal 7 & Objects/OW - 224 -

¦ Удаление диапазона символов ¦ DeleteSubText ¦
¦ Удаление строки текста ¦ DeleteLine ¦
¦ Вставка текста ¦ Insert ¦
¦ Вставка текста из буфера ¦ Paste ¦
¦ вырезанного изображения ¦ ¦
¦ Замена всего текста ¦ SetText ¦
¦ Выделение диапазона текста ¦ SelectRange ¦
¦ Прокрутка текста ¦ Scroll ¦
L----------------------------------------+-----------------------

Пример программы: EditTest
-----------------------------------------------------------------

EditTest - это программа, которая помещает на экран основное
окно, которое будет порождающим для двух управляющих элементов
редактирования, двух статических управляющих элементов и кнопки.
Данное окно показано на Рис. 12.7.

Когда пользователь щелкает на командной кнопке кнопкой "мы-
ши", текст из левого управляющего элемента редактирования (EC1)
копируется в правый управляющий элемент редактирования (EC2). В
EC2 текст преобразуется в буквы верхнего регистра, поскольку оно
было построено со стилем es_UpperCase. Если в C1 никакой текст не
выбран, то в EC2 копируется весь текст. Если в EC1 выбран некото-
рый текст, то будет скопирован именно он. Меню редактирования
обеспечивает функции редактирования независимо от того, с каким
управляющим элементов редактирования идет работа. Полный файл
EDITTEST.PAS и файл ресурса EDITTEST содержатся на ваших дистри-
бутивных дискетах.

Использование комбинированных блоков
-----------------------------------------------------------------

Управляющий элемент типа комбинированного блока является со-
четанием двух других управляющих элементов: блока списка и управ-
ляющего элемента редактирования. Он служит тем же целям, что и
блок списка - позволяет пользователю выбрать один элемент списка
из прокручиваемого списка элементов текста, нажимая на кнопку
"мыши". Управление редактированием, вынесенное в верхнюю часть
блока списка предоставляет иной механизм выбора, позволяя пользо-
вателю ввести текст нужного элемента. Если отображается область
списка комбинированного блока, то автоматически выбирается нужный
элемент. Тип TComboBox является производным от типа TListBox и
наследует его методы модификации, опроса и выбора элементов спис-
ка. Кроме того, TComboBox предоставляет методы по манипулированию
списком, находящемся в комбинированном блоке, который в некоторых
случаях может раскрываться по запросу.



B.Pascal 7 & Objects/OW - 225 -

Три типа комбинированных блоков
-----------------------------------------------------------------

Имеются три типа комбинированных блоков: простые, раскрываю-
щиеся и раскрывающиеся со списком. На Рис. 12.8 показан вывод
трех типов комбинированных блоков с блоком списка.

------------------------------------------------------------T-T-¬
¦-=------------------Static Control Tester------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ ¦
¦ Блок списка Простой комбинированный блок ¦
¦ -----------------¬ ---------------------------¬ ¦
¦ ¦a ¦ ¦ ¦ ¦
¦ ¦b ¦ LT-------------------------+ ¦
¦ ¦c ¦ ¦a ¦ ¦
¦ ¦d ¦ ¦b ¦ ¦
¦ ¦e ¦ ¦c ¦ ¦
¦ ¦f ¦ ¦d ¦ ¦
¦ L----------------- L-------------------------- ¦
¦ ¦
¦ Раскрывающийся комбинированный Комбинированный блок с ¦
¦ блок раскрывающимся списком ¦
¦ ------------------------¬----¬ -----------------------T---¬ ¦
¦ ¦ ¦¦ v ¦ ¦c---------------------¦ v ¦ ¦
¦ L------------------------L---- L----------------------+---- ¦
¦ ¦
¦ ¦
¦ ¦
L----------------------------------------------------------------

Рис. 12.8 Три типа комбинированных блоков и блок списка.

Перечень стилей комбинированного блока Таблица 12.10
----------------------T---------------------T-------------------¬
¦ Стиль ¦Возможность скрытого ¦Соответствие текста¦
¦ ¦ списка ¦ списку ¦
+---------------------+---------------------+-------------------+
¦ Простой ¦ нет ¦ нет ¦
¦ Раскрывающийся ¦ есть ¦ нет ¦
¦ Раскрывающийся со ¦ есть ¦ да ¦
¦ списком ¦ ¦ ¦
L---------------------+---------------------+--------------------

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

* Простые комбинированные блоки.

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

B.Pascal 7 & Objects/OW - 226 -

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

* Раскрывающиеся комбинированные блоки.

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

* Раскрывающиеся комбинированные блоки списка.

Область списка в раскрывающемся комбинированном блоке
списка ведет себя подобно области списка в спускающемся
комбинированном блоке - появляется при необходимости и ис-
чезает, когда не нужна. Эти два типа комбинированных бло-
ков отличаются поведением их областей редактирования.
Раскрывающиеся области редактирования ведут себя подобно
обычным управляющим элементам редактирования. Раскрывающи-
еся области редактирования списка ограничиваются только
отображением одного элемента списка. Если редактируемый
текст соответcтвует элементу списка, то никаких дополни-
тельных символов ввести нельзя.

Выбор типа комбинированного блока
-----------------------------------------------------------------

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

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

Построение комбинированных блоков
-----------------------------------------------------------------

Кроме обычных 6 параметров объектов управляющих элементов
конструктор Init для TComboBox воспринимает в качестве аргументов

B.Pascal 7 & Objects/OW - 227 -

стиль и максимальную длину текста. Конструктор TComboBox описыва-
ется следующим образом:

constructor TComboBox.Init(AParent: PWindowsObject;
AnID: Integer: X, Y, W, H: Integer;
AStyle, ATextLen: Word);

Все комбинированные блоки, построенные с помощью Init, име-
ют стили ws_Child, ws_Visible, cbs_AutoHScroll, cbs_Sort (отсор-
тированный список), и VScroll (вертикальная полоса прокрутки).
Параметр стиля - это один из стандартных стилей комбинированных
блоков Windows: cbs_Simple, cbs_DropDown или cbs_DropDownList.
Параметр длины текста работает подобно соответствующему параметру
управляющего элемента редактирования, ограничивая число символов,
которые можно ввести в область редактирования комбинированного
блока.

Следующие строки приведут к созданию спускающегося комбини-
рованного блока списка с неотсортированным списком:

CB3: = New(PComboBox, Init(@Self, id_CB3, 190, 160,
150, 100, cbs_DropDownList, 40));
CB3^.Attr.Style:=CB3^.Attr.Style and (not cbs_Sort);

Модификация комбинированных блоков
-----------------------------------------------------------------

TComboBox определяет два метода для демонстрации и сокрытия
области списка в раскрывающихся комбинированных блоках и раскры-
вающихся комбинированных блоках списка: ShowList и HideList. Обе
эти процедуры не нуждаются в аргументах. Вызывать эти методы для
демонстрации или сокрытия списка, когда пользователь нажимает
стрелку вниз справа от области редактирования, не нужно. В этом
случае работает автоматический механизм комбинированных блоков.
Эти методы полезны только для принудительного вывода или сокрытия
списка.

Пример программы: CBoxTest
-----------------------------------------------------------------

Программа CBoxTest реализует приложение, показанное на Рис.
12.8. В нем использованы все три типа комбинированных блоков. CB1
- это простой комбинированный блок, CB2 это раскрывающийся комби-
нированный блок, а CB3 - это раскрывающийся комбинированный блок
списка. Нажатие кнопок Show и Hide выполняет принудительный вывод
и сокрытие правого верхнего комбинированного блока, CB3, путем
вызова методов ShowList и HideList.

Примечание: Полный текст файла CBOXTEST.PAS содержится
на ваших дистрибутивных дискетах.

Установка значений управляющих элементов
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 228 -


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

Для чего используется буфер передачи?
-----------------------------------------------------------------

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

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

Механизм передачи требует для представления управляющих
элементов, для которых вы будете передавать данные, использования
объектов ObjectWindows. Это означает, что вы должны использовать
InitResource для связывания объектов с управляющими элементами в
блоках и окнах диалога.

Примечания: Связь управляющих элементов с управляющими
объектами описывается в Главе 11 "Объекты диалоговых бло-
ков".

Чтобы использовать механизм передачи, вы можете сделать сле-
дующее:

* Определить буфер передачи.
* Определить соответствующее окно.
* Передать данные.

Определение буфера передачи
-----------------------------------------------------------------

Буфер передачи - это запись с одним полем для каждого управ-

B.Pascal 7 & Objects/OW - 229 -

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

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

type
TSampleTransferRecord = record
Stat1: array[0..TextLen-1] of Char; { статический текст }
Edit1: array[0..TextLen-1] of Char; { текст управляющего
элемента редактирования }
List1Strings: PStrCollection; { строки блока списка }
List1Selection: Integer; { индекс выбранных строк }
ComboStrings: PStrCollection; { строки комбинированного
блока }
ComboSelection: array[0..TextLen-1] of Char; { выбранные
строки }
Check1: Word; { проверка состояния блока}
Radio1: Word; { состояние кнопки с независимой фиксацией }
Scroll1: ScrollBarTransferRec; { диапазон полосы
прокрутки и т.д. }
end;


B.Pascal 7 & Objects/OW - 230 -


В каждом типе управляющего элемента хранится различная ин-
формация. Буфер передачи для каждого стандартного управляющего
элемента поясняется в следующей таблице:

Поля буфера передачи
для каждого типа управляющего элемента Таблица 12.11
------------------------T---------------------------------------¬
¦ Тип управляющего ¦ Буфер передачи ¦
¦ элемента ¦ ¦
+-----------------------+---------------------------------------+
¦ Статический ¦ Символьный массив размером до макси-¦
¦ ¦ мальной длины текста, плюс завершающий¦
¦ ¦ нулевой символ. ¦
¦ ¦ ¦
+-----------------------+---------------------------------------+
¦ Редактирование ¦ Текстовый буфер управляющего элемента¦
¦ ¦ редактирования размером до длины, оп-¦
¦ ¦ ределенной в текстовом поле TextLen. ¦
¦ ¦ ¦
+-----------------------+---------------------------------------+
¦ Блок списка ¦ ¦
¦ одиночный выбор ¦ Набор строк в списке, плюс целочислен-¦
¦ ¦ ный индекс выделенной строки. ¦
¦ ¦ ¦
¦ множественный выбор ¦ Набор строк в списке, плюс запись, со-¦
¦ ¦ держащая индексы всех выделенных эле-¦
¦ ¦ ментов. ¦
¦ ¦ ¦
+-----------------------+---------------------------------------+
¦ Комбинированный блок ¦ Набор строк в списке, плюс выбранная¦
¦ ¦ строка. ¦
¦ ¦ ¦
+-----------------------+---------------------------------------+
¦ Кнопка с независимой ¦ Значения Word с указывающими состояния¦
¦ фиксацией ¦ bf_Unchecked, bf_Checked и bf_Grayed. ¦
¦ ¦ ¦
+-----------------------+---------------------------------------+
¦ Кнопка с зависимой ¦ Значения Word с указывающими состояния¦
¦ фиксацией ¦ bf_Unchecked, bf_Checked и bf_Grayed. ¦
¦ ¦ ¦
+-----------------------+---------------------------------------+
¦ Полоса прокрутки ¦ Запись типа TScrollBarTransferRec, со-¦
¦ ¦ храняющая диапазон полосы прокрутки и¦
¦ ¦ позицию в ней. ¦
¦ ¦ ¦
L-----------------------+----------------------------------------

Тип TScrollBarTransferRec имеет вид:

TScrollBarTransferRec := record
LowValue : Integer;
HighValue: Integer;

B.Pascal 7 & Objects/OW - 231 -

Position : Integer;
end;

Определение окна
-----------------------------------------------------------------

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

Использование буфера передачи с диалоговым блоком
-----------------------------------------------------------------

Для случая окон с управляющими элементами объекты управляю-
щих элементов конструируются с использованием Init. Для диалогов
и окон диалогов нужно использовать конструктор InitResource. Нап-
ример (используется определенный ранее тип TSampleRecord):

type
TSampleTransferRecord = record
.
.
.
PParentWindow = ^TParentWindow;
TParentWindow = object(TWindow)
TheDialog: PDialog;
TheBuffer: SampleTransferRecord;
.
.

B.Pascal 7 & Objects/OW - 232 -

.
.
constructor TParentWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
var
Stat1: PStatic;
Edit1: PEdit;
List1: PListBox;
Combo1: PComboBox;
Check1: PCheckBox;
Radio1: PRadioButton;
Scroll1: PScrollBar;
begin
TWindow.Init(AParent, ATitle);
TheDialog^.Init(@Self, PChar(101));
New(Stat1, InitResource(TheDialog, id_Stat1));
New(Edit1, InitResource(TheDialog, id_Edit1));
New(List1, InitResource(TheDialog, id_List1));
New(Combo1, InitResource(TheDialog, id_Combo1));
New(Check1, InitResource(TheDialog, id_Check1));
New(Radio1, InitResource(TheDialog, id_Radio1));
New(Scroll1, InitResource(TheDialog, id_Scroll1));
TheDialog^.TranssferBuffer:=@TheBuffer;
end;

Для управляющих элементов, построенных с помощью
InitResource, механизм передачи разрешается автоматически.


B.Pascal 7 & Objects/OW - 233 -

Использование буфера передачи с окном
-----------------------------------------------------------------

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

constructor TSampleWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
inherited Init(AParent, ATitle);
Edit1 := New(PEdit, Init(@Self, id_Edit1, '', 10, 10,
100, 30, 40, False));
Edit1^.EnableTransfer;
end;

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

Передача данных
-----------------------------------------------------------------

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

Передача данных в окно
-----------------------------------------------------------------

После создания окна или диалогового блока данные автомати-
чески. Для создания экранного элемента, представляющего оконный
объект, конструктор вызывает SetupWindow. Затем для загрузки дан-
ных из буфера передачи вызывается TransferData. Окно SetupWindow
интерактивно вызывает SetupWindow для каждого из дочерних окон,
так что дочерние окна имеют возможность передать свои данные.
Поскольку порождающее окно устанавливает свои дочерние окна в по-
рядке их построения, данные в буфере передачи должны следовать в
том же порядке.

Если объект управляющего элемента был построен с помощью
InitResource или если порождающее окно явным образом разрешило
межанизм передачи путем вызова для управляющего элемента
EnableTransfer, то методы управляющего объекта SetupWindow вызы-
вают TransferData.

Передача данных из диалогового окна
-----------------------------------------------------------------

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

это сообщение указывает, что пользователь для завершения диалога
щелкнул "мышью" на кнопке OK, так что диалог автоматически обнов-
ляет свой буфер передачи. Затем, если вы снова выполняете диалог,
диалоговый блок передает текущие данные в управляющие элементы.

Передача данных из окна
-----------------------------------------------------------------

Однако, вы можете явно передавать данные в любом направлении
в любой момент времени. Например, вы можете передать данные из
управляющих элементов окна или безрежимного диалога. Вы также мо-
жете сбросить состояния управляющих элементов, используя данные
буфера передачи, в ответ на щелчок "мышью" на кнопке Reset
(сброс). В обоих случаях используется метод TransferData. Конс-
танта tf_SetData обозначает передачу данных из буфера в управляю-
щий элемент, а константа tf_GetData - передачу в другом направле-
нии. Например, вы можете вызвать TransferData в методе Destroy
объекта окна:

procedure TSampleWindow.Destroy;
begin
TransferData(tf_GetData);
TWindow.Destroy;
end;

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

Вы можете изменить способ передачи данных для конкретного
управляющего элемента или включить новый управляющий элемент, оп-
ределенный вами в механизме передачи. В обоих случаях вам просто
нужно написать метод Transfer для вашего управляющего объекта,
который если установлен флаг tf_GetData копирует данные из управ-
ляющего элемента в место, задаваемое указателем. Если установлен
флаг tf_SetData, то просто скопируйте данные по заданному указа-
телю в управляющий элемент. Рассмотрим в качестве примера
TStatic.Transfer:

function TStatic.Transfer(DataPrt: Pointer;
TransferFlag: Word): Word;
begin
if TransferFlag = tf_GetData then
GetText(DataPrt, TextLen)
else if TransferFlag = tf_SetData then
SetText(DataPtr);
Transfer:=TextLen;
end;

Метод Transfer должен всегда возвращать число переданных
байт информации.

Пример программы: TranTest
-----------------------------------------------------------------

Основное окно программы TranTest воспроизводит режимный диа-

B.Pascal 7 & Objects/OW - 235 -

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

Примечание: Полный текст программы содержится в файле
TRANTEST.PAS на ваших дистрибутивных дискетах.



B.Pascal 7 & Objects/OW - 236 -

Использование специализированных управляющих элементов
-----------------------------------------------------------------

Windows обеспечивает механизм, позволяющий вам создавать
свои собственные виды управляющих элементов, а ObjectWindows об-
легчает создание объектов, использующих преимущества управляющих
элементов. В данном разделе обсуждается использование специализи-
рованных управляющих элементов Borland, которые придают своеоб-
разный вид работающим в Windows приложениям Borland, а затем опи-
сывается, как создавать свои собственные уникальные управляющие
элементы.

Специализированные управляющие элементы Borland для Windows
-----------------------------------------------------------------

Специализированные управляющие элементы Borland для Windows
(BWCC) обеспечивают выразительный внешний вид приложений Borland
для Windows. Основными средствами BWCC являются:

* командные кнопки с графическими изображениями;

* серый "рельефный" фон диалоговый блоков;

* трехмерные кнопки с зависимой и независимой фиксацией.

ObjectWindows дает вам возможность простого доступа к BWCC,
так что вы можете придать своим приложениями стандартный для
Borland вид.



B.Pascal 7 & Objects/OW - 237 -

Использование стандартных BWCC
-----------------------------------------------------------------

ObjectWindows позволяет легко добавлять BWCC в ваши приложе-
ния Windows. Нужно просто добавить модуль BWCC в оператор uses
программы:

uses BWCC;

Использование BWCC автоматически позволяет вам делать следу-
ющее:

* использовать загружаемые из ресурсов управляющие элементы
BWCC;

* создавать в вашей программе BWCC.

Например, с помощью пакета разработчика ресурсов Resource
WorkShop вы можете создать ресурсы диалоговых блоков, использую-
щие специализированные управляющие элементы Borland. Включение в
оператор uses программы модуля BWCC обеспечивает для вашей прог-
раммы информацию о том, где искать динамически компонуемую библи-
отеку (BWCC.DLL), содержащую код, который обеспечивает работу
BWCC.

Кроме того, после добавления модуля BWCC любые создаваемые в
программе объекты управляющих элементов будут иметь вид и харак-
теристики управляющих элементов Borland.

Средства BWCC
-----------------------------------------------------------------

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



B.Pascal 7 & Objects/OW - 238 -

Расширение BWCC
-----------------------------------------------------------------

BWCC обеспечивает кнопки с графическими изображениями для
всех стандартных командных кнопок Windows. То есть, имеются гра-
фические изображения, предусмотренные для командных кнопок, для
которых Windows обеспечивает стандартный идентификатор: id_Abort,
id_Cancel, id_Ignore, id_No, id_Ok, id_Retry и id_Yes.

Создание кнопок с графическими изображениями

В своих приложениях вы можете обеспечить для командных кно-
пок собственные графические образы. Все что нужно предусмотреть -
это шесть ресурсов графических изображений (битовых массивов),
пронумерованных относительно идентификатора управляющего элемента
вашей командной кнопки. Например, если вы хотите создать графи-
ческую командную кнопку с идентификатором id_MyButton, то создае-
те ресурсы битовых массивов с идентификаторами ресурса 1000 +
id_MyButton, 2000 + id_MyButton, 3000 + id_MyButton, 4000 +
id_MyButton, 5000 + id_MyButton и 6000 + id_MyButton. Каждый
представляемый битовый массив показан в следующей таблице:

Ресурсы битовых массивов для командных кнопок BWCC Таблица 12.12
-------------------------T-----------------T--------------------¬
¦ Образ ¦ Идентификатор ¦ Идентификатор ¦
¦ ¦ ресурса VGA ¦ ресурса VGA ¦
+------------------------+-----------------+--------------------+
¦ Командная кнопка ¦ 1000 + идент. ¦ 2000 + идент. ¦
¦ в фокусе ¦ ¦ ¦
¦ ¦ ¦ ¦
+------------------------+-----------------+--------------------+
¦ Нажатая командная ¦ 3000 + идент. ¦ 4000 + идент. ¦
¦ кнопка ¦ ¦ ¦
¦ ¦ ¦ ¦
+------------------------+-----------------+--------------------+
¦ Командная кнопка ¦ 5000 + идент. ¦ 6000 + идент. ¦
¦ не в фокусе ¦ ¦ ¦
¦ ¦ ¦ ¦
L------------------------+-----------------+---------------------

Графические образы командных кнопок VGA должны иметь ширину
63 и высоту 39 элементов изображения. Графические образы команд-
ных кнопок EGA должны иметь ширину 63 и высоту 39 элементов
изображения.

B.Pascal 7 & Objects/OW - 239 -


Для текста следует использовать шрифт Helvetica размером 8
пунктов, а вокруг образа кнопки, находящейся в фокусе, следует
выводить рамку из точек. Набор графических изображений для ко-
мандных кнопок с идентификатором 201 показан на следующем рисун-
ке:

-------------------¬ -------------------¬ -------------------¬
¦------------------¦ ¦------------------¦ ¦------------------¦
¦-----------Add----¦ ¦-----------Add----¦ ¦-----------Add----¦
¦-----------Pen----¦ ¦-----------Pen----¦ ¦-----------Pen----¦
¦------------------¦ ¦------------------¦ ¦------------------¦
¦------------------¦ ¦------------------¦ ¦------------------¦
L------------------- L------------------- L-------------------
1201 3201 5201

-------------------¬ -------------------¬ -------------------¬
¦ ¦- ¦ ..... ¦ ¦ ..... -¦
¦ -- Add ¦- ¦ -- : Add : ¦ ¦ -- : Add : -¦
¦ ------ Pen ¦- ¦ ------ : Pen : ¦ ¦ ------ : Pen : -¦
¦ -- ¦- ¦ -- ..... ¦ ¦ -- ..... -¦
¦ ¦- ¦ ¦ ¦ -----------------¦
L-------------------- L------------------- L-------------------
-------------------
2201 4201 6201

Рис. 12.9 Графические ресурсы для командной кнопки BWCC с
идентификатором 201.

B.Pascal 7 & Objects/OW - 240 -

Создание ваших собственных
специализированных управляющих элементов
-----------------------------------------------------------------

Простейший способ создания специализированного управляющего
элемента состоит в фактическом создании окна, которое действует
как управляющий элемент, но вовсе не является окном. Этот подход
используется в программе Steps в Части 1 данного руководства. Тот
же используемый в программе Steps метод применяется для ее объек-
та палитры, который можно использовать, например, для создания
объекта инструментальной полосы. Таким "управляющие элементы" яв-
ляются наследниками TWindow, а не TControl, поскольку TControl
имеет дело только со стандартными управляющими элементами
Windows.

Другим стандартным способом создания специализированного уп-
равляющего элемента является построение в динамически компонуемой
библиотеке нового класса окон. После этого вы можете создавать
объекты ObjectWindows, использующие этот новый класс. Пакет раз-
работчика ресурсов также может использовать специализированные
управляющие элементы, созданные в DLL. Информацию об использова-
нии специализированных управляющих элементов в ресурсах диалого-
вых блоках вы можете найти в "Руководстве пользователя по пакету
разработчика ресурсов".

Примечание: О классах окон рассказывается в Главе 10.



B.Pascal 7 & Objects/OW - 241 -

------------------------------------------------------------------
Глава 13. Проверка допустимости данных
-----------------------------------------------------------------

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

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

* Три вид проверки допустимости данных.

* Использование объектов проверки допустимости.

* Как работает проверка допустимости.

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

Три вида проверки допустимости данных
-----------------------------------------------------------------

Существует три различных типа проверки допустимости данных,
и ObjectWindows поддерживает их по-разному. Этими тремя видами
являются:

* Фильтрация ввода.

* Проверка допустимости каждого элемента.

* Проверка допустимости полных экранов.

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

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


B.Pascal 7 & Objects/OW - 242 -

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

Фильтрация ввода
-----------------------------------------------------------------

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

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

Проверка допустимости каждого поля
-----------------------------------------------------------------

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

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

Проверка допустимости полных экранов
-----------------------------------------------------------------

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

* Проверкой допустимости режимных окон.
* Проверкой допустимости при изменении фокуса.
* Проверкой допустимости по запросу.

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

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

B.Pascal 7 & Objects/OW - 243 -

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

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

Проверка допустимости по запросу

В любой момент вы можете указать окну на необходимость про-
верки всех его подокон путем вызова метода CanClose. CanClose по
существу спрашивает окно "Если сейчас будет дана команда закры-
тия, являются ли все поля допустимыми?" Окно вызывает методы
CanClose всех своих дочерних окон в порядке включения и возвраща-
ет True, если все они возвращают значение True.

Вызов CanClose не обязывает вас фактически закрывать окно.
Например, вы можете вызвать CanClose, когда пользователь "нажима-
ет" командную кнопку Save (Сохранение), обеспечивая проверку до-
пустимости данных перед их сохранением.

Вы можете проверить любое окно (режимное или безрежимное) и
в любое время. Однако автоматическую проверку допустимости при
закрытии имеют только режимные окна. Если вы используете безре-
жимные окна ввода данных, то нужно обеспечить, чтобы приложение
перед выполнением действий с введенными данными вызывало метод
CanClose окна.

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

Использование объекта проверки допустимости данных с управ-
ляющим элементом редактирования требует двух шагов:

* Построение объекта проверки допустимости.
* Присваивание объекта проверки допустимости управляющему
элементу редактирования.

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



B.Pascal 7 & Objects/OW - 244 -

Построение объектов проверки допустимости
-----------------------------------------------------------------

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

constructor TRangeValidator.Init(AMin, AMax: Integer);

Добавление к управляющим элементам
редактирования средств проверки допустимости
-----------------------------------------------------------------

Каждый управляющий элемент редактирования имеет поле с име-
нем Validator, установленное по умолчанию в nil, которое может
указывать на объект проверки допустимости. Если вы не присваивае-
те объекта полю Validator, то управляющий элемент редактирования
ведет себя так, как описано в Главе 12. После присваивания с по-
мощью вызова SetValidator объекта проверки допустимости управляю-
щий элемент редактирования автоматически проверяется им при обра-
ботке основных событий и при самом вызове для проверки допусти-
мости.

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

.
. { создание трехсимвольного управляющего элемента редакти-
. рования }
Ed := New(PEdit, Init(@Self, id_Me, '', 10, 10, 50, 30, 3,
False));
Ed^.SetValidator(New(PRangeValidator, Init(100, 999)));
.
.
.

Как работает проверка допустимости
-----------------------------------------------------------------

В ObjectWindows предусмотрено несколько видов объектов про-
верки допустимости, которые должны охватывать большинство ваших
потребностей по проверке данных. Из абстрактных типов проверки
допустимости вы можете также построить свои собственные произ-
водные типы.

В данном разделе освещаются следующие темы:

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


B.Pascal 7 & Objects/OW - 245 -

Методы объекта проверки допустимости
-----------------------------------------------------------------

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

Этими четырьмя методами являются следующие:

* Valid

* IsValid

* IsValidInput

* Error

Единственными методами, вызываемыми вне объекта, являются
Valid и IsValidInput. Error и IsValid - единственные методы, вы-
зываемые другими методами объекта проверки допустимости.

Проверка допустимости данных
-----------------------------------------------------------------

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

При использовании средств проверки допустимости с управляю-
щими элементами редактирования вам никогда не требуется вызывать
или переопределять метод Valid объекта проверки допустимости. По
умолчанию Valid возвращает True, если возвращает True метод
IsValid. В противном случае для уведомления пользователя об ошиб-
ке и возврата значения False вызывается Error.

B.Pascal 7 & Objects/OW - 246 -

Проверка полной строки
-----------------------------------------------------------------

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

Заметим, что метод IsValid не вызывается вами явно. Исполь-
зуйте для вызова IsValid метод Valid, так как для уведомления
пользователя в случае возврата методом IsValid значения False
Valid вызывает метод Error. Не путайте также проверку допустимос-
ти сообщением об ошибке.

Проверка допустимости нажатий клавиш
-----------------------------------------------------------------

Когда объект управляющего элемента редактирования получает
имеющее для него значение событие нажатия клавиши, он вызывает
метод IsValidInput объекта проверки допустимости. По умолчанию
методы IsValid всегда возвращают True. Это означает, что воспри-
нимаются все нажатия клавиш. Однако, наследующие объекты проверки
допустимости могут переопределять метод IsValidInput, чтобы от-
фильтровывать нежелательные нажатия клавиш.

Например, средства проверки допустимости диапазона, которые
используются для числового ввода, возвращают из IsValidInput True
только для цифр и символов '+' и '-'.

IsValidInput воспринимает два параметра. Первый параметр -
это параметр-переменная, содержащая текущий текст ввода. Второй
параметр - это булевское значение, указывающее, следует ли перед
попыткой проверки допустимости применять к строке ввода дополне-
ние или заполнение. TPictureValidator - это единственный из стан-
дартных объектов проверки допустимости, использующий второй пара-
метр.

Сообщение о недопустимых данных
-----------------------------------------------------------------

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

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

B.Pascal 7 & Objects/OW - 247 -


Хотя большинство объектов проверки допустимости переопреде-
ляют Error, вам не следует вызывать его непосредственно. Метод
Error вызывается методом Valid, если IsValid возвращает False
(что является единственным моментом, когда необходимо вызывать
Error).



B.Pascal 7 & Objects/OW - 248 -

Стандартные средства проверки допустимости
-----------------------------------------------------------------

ObjectWindows включает в себя шесть стандартных типов объек-
тов проверки допустимости, включая абстрактный объект проверки
допустимости и следующие пять специальных типов таких объектов:

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

Абстрактный объект проверки допустимости
-----------------------------------------------------------------

Абстрактный тип TValidator служит базовым типом для всех
объектов проверки допустимости, но сам по себе он не делает ниче-
го полезного. По существу, TValidator - это объект проверки до-
пустимости, для которого всегда допустим любой ввод: IsValid и
IsValidInput возвращают True, а Error не выполняет никаких функ-
ций. Наследующие типы переопределяют IsValid и/или IsValidInput
для фактического определения того, какие значения являются допус-
тимыми.

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

Фильтрация
-----------------------------------------------------------------

Фильтрующие объекты проверки допустимости - это простая реа-
лизация средств проверки допустимости, при которой проверяется
только набираемый пользователем ввод. Конструктор фильтрующего
объекта проверки допустимости воспринимает один параметр - набор
допустимых символов:

constructor TFilterValidator.Init(AValidChars: TCharSet);

TFilterValidator переопределяет IsValidInput для возврата
True только в том случае, если все символы в текущей строке ввода
содержатся в наборе символов, переданных конструктору. Управляю-
щие элементы редактирования включают символы только в том случае,
если IsValidInput возвращает True, так что нет необходимости пе-
реопределять IsValid. Поскольку символы проходят через фильтр
ввода, полная строка допустима по определению.

Потомки TFilterValidator, такие как TRAngeValidator, могут
сочетать фильтрацию ввода с другими проверками завершенной стро-
ки.


B.Pascal 7 & Objects/OW - 249 -

Проверка диапазона
-----------------------------------------------------------------

Объект проверки допустимости диапазона TRangeVaidator - это
потомок TFilterValidator, которые воспринимают только числа и до-
бавляют к итоговым результатам проверку диапазона. Конструктор
воспринимает два параметра, определяющим минимальное и максималь-
ное допустимое значение:

constructor TRangeValidator.Init(AMin, AMax: Integer);

Объект проверки допустимости диапазона сам строит числовое
средство проверки-фильтрации, воспринимающее только цифры
'0'..'9' и символы плюса и минуса. Таким образом, наследуемый
IsValidInput обеспечивает отфильтрацию только цифр. Затем
TRangeValidator переопределяет IsValid, чтобы он возвращал True
только если введенные числа находятся в допустимом диапазоне, оп-
ределяемом в конструкторе. Метод Error выводит блок сообщения,
указывающий, что введенное значение находится вне диапазона.

Проверка допустимости с просмотром
-----------------------------------------------------------------

Абстрактный объект проверки допустимости с просмотром
TLookupValidator обеспечивает основу для общего типа объекта про-
верки допустимости, который для определения допустимости сравни-
вает введенное значение со списком воспринимаемый элементов.

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

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

Новый метод, вводимый объектом TLookupValidator называется
Lookup. По умолчанию Lookup возвращает значение False, но при об-
разовании производного абстрактного объекта проверки допустимости
c просмотром вы можете переопределить Lookup для сравнения пере-
данной строки со списком и возвращать True, если строка содержит
допустимую запись.

TLookupValidator переопределяет IsValid для возврата True
только если Lookup также возвращает True. В наследующих типах
проверки допустимости с просмотром вам следует переопределять не
IsValid, а Lookup.

Просмотр строк
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 250 -

списке строк. Если переданная строка содержится в списке, метод
объекта проверки допустимости с просмотром строки возвращает
True. Конструктор воспринимает только один параметр - список до-
пустимых строк:

constructor TStringLookupValidator.Init(AString:
PStringCollection);

Чтобы после построения объекта проверки допустимости с прос-
мотром использовать другой список строк, передайте новый список
методу NewStringList объекта проверки допустимости (который унич-
тожает старый список и задает новый).

TStringLookupValidator переопределяет методы Lookup и Error,
так что Lookup возвращает True, если переданная строка содержится
в наборе строк, а Error выводит на экран блок сообщения, указыва-
ющий, что строка отсутствует в списке.

Проверка допустимости по шаблону
-----------------------------------------------------------------

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

Примечание: Синтаксис шаблонов описывается в справоч-
нике. См. TPXPictureValidator.Picture.

constuctor TPictureValidator.Init(const APic: String;
AAutoFill: Boolean);

TPictureValidator переопределяет Error, IsValidInput и
IsValid и добавляет новый метод Picture. Изменения в Error и
IsValid просты: Error выводит на экран блок сообщения, указываю-
щий, какой формат должна иметь строка, а IsValid возвращает True
только если True возвращается функцией Picture, позволяя получать
новые производные типы проверки допустимости по шаблону путем пе-
реопределения только метода Picture. IsValidInput проверяет сим-
волы по мере набора их пользователем, допуская только те символы,
которые разрешены в шаблоне формата, и возможно дополняя лите-
ральные символы из шаблона.

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


B.Pascal 7 & Objects/OW - 251 -

------------------------------------------------------------------
Глава 14. Объекты MDI
-----------------------------------------------------------------
Многодокументальный интерфейс (MDI) - это стандарт интерфей-
са для приложений Windows, которые позволяют пользователю однов-
ременно работать с несколькими открытыми документами. Документ, в
этом смысле, это обычно связанная с файлом задача, например, ре-
дактирование текстового файла или работа с файлом электронной
таблицы. В приложениях MDI пользователь может, например, иметь
несколько открытых файлов в одном приложении. Возможно, что вы
уже использовали приложения MDI: Microsoft Exel, администратор
программ Windows, администратор файлов Windows. Стандарт MDI яв-
ляется также частью спецификации общего доступа пользователя
(CUA) фирмы IBM.
ObjectWindows предусматривает объекты, позволяющие легко пи-
сать приложения MDI.

Что такое приложение MDI?
-----------------------------------------------------------------
Имеются определенные компоненты, которые присутствуют в каж-
дом приложении MDI. Чаще всего основное окно вызывает окно с рам-
кой. В области клиента окна-рамки есть невидимое окно - окно кли-
ента MDI - которое содержит дочернее окно, вызывающее дочерние
окна MDI. Это очень важно, т.к. обработка дочерних окон MDI про-
исходит скрытно от пользователя.
------------------------------------------------------------T-T-¬
¦-=---------------------MDI Conformist----------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ MDI Children ¦
+---------------------------------------------------------------+
¦----------------------------------------------------¬ ¦
¦¦------------------Child #1-------------------------¦ ¦
¦+---------------------------------------------------+ ¦
¦¦ -------------------------------------------------------¬ ¦
¦¦ ¦ X¦--------------------Child #2-----------------------¦ ¦
¦¦ L--+---------------------------------------------------+ ¦
¦¦ ¦ ---------------------------------------------------T-T-¬¦
¦¦ ¦ ¦ X¦-=-----------------Child #3--------------------¦^¦v¦¦
¦L----¦ L--+-----------------------------------------------+-+-+¦
¦ ¦ ¦ ----¬ ^ ¦¦
¦ ¦ ¦ ¦ X ¦ CanClose блоки минимизации и ---- ¦¦
¦ L----¦ L---- максимизации ¦¦
¦ ¦ ^ ¦¦
¦ L-----------------------------+----------------------¦
¦ дочернее окно MDI -- ¦
¦ ----¬ ¦
¦ ¦ <+--- пиктограмма ¦
¦ L---- ¦
¦ Child #4 ^ ¦
L----------------------------+-----------------------------------
¦ ^
окно клиента MDI -- ¦
окно-рамка MDI --
Рис. 14.1 Компоненты приложения MDI.

B.Pascal 7 & Objects/OW - 252 -

Меню дочернего окна
-----------------------------------------------------------------

Строка меню окна-рамки содержит меню, управляющее дочерними
окнами MDI. Меню дочернего окна содержит такие элементы как Tile
(Вывод без перекрытия), Cascade (Вывод с перекрытием), Arrange
(Упорядочить) и Close All (Закрыть все). Имя каждого открытого
окна MDI автоматически добавляется к концу этого меню с выбором
текущего окна.

Дочерние окна MDI
-----------------------------------------------------------------

Каждое дочернее окно MDI имеет некоторые характеристики пе-
рекрывающего окна. Его можно максимизировать до полного размера
окна клиента MDI или минимизировать в пиктограмму, которая поме-
щается к нижней границе окна-рамки. Дочернее окно MDI никогда не
выходит за границы его окна-рамки (обрамляющего окна). Дочернее
окно MDI не может иметь меню, поэтому все его функции реализуются
меню окна-рамки. Заголовок каждого дочернего окна MDI часто
представляет собой имя открытого файла, связанного с этим окном,
хотя его поведение заранее неизвестно и определяется программой.
Можно рассматривать приложение MDI как мини-сеанс Windows, когда
несколько приложений представлены окнами или пиктограммами.

Окна MDI в ObjectWindows
-----------------------------------------------------------------

ObjectWindows определяет типы для представления рамок MDI и
клиентов MDI. Это соответственно TMDIWindow и TMDIClient.
TMDIWindow является производным от TWindow, но TMDIClient на са-
мом деле представляет собой управляющий элемент и является произ-
водным от TControl. В приложении MDI ObjectWindows, окно-рамки
владеет своим окном клиента MDI и хранит его в поле ClientWnd.
Окно-рамка также содержит каждое из дочерних окон MDI в связанном
списке ChildList. Дочерние окна MDI являются экземплярами типа
объекта, производного от написанного вами TWindow.

Методы TMDIWindow занимаются в основном конструированием и
управлением дочерними окнами MDI, окном клиента MDI и обработкой
выбора в меню. Главная работа TMDIClient происходит скрытно от
пользователя и состоит в управлении дочерними окнами MDI. При
разработке приложений MDI вы в общем случае будете создавать но-
вые производные типы для своих рамок и дочерних окон соответс-
твенно от TMDIWindow и TWindow.

Построение приложения MDI
-----------------------------------------------------------------

Построение приложения MDI в ObjectWindows представляет собой
относительно простую задачу:

* Построение основного окна MDI.

B.Pascal 7 & Objects/OW - 253 -


* Установка меню дочернего окна.

* Предоставление основному окну возможности создания дочер-
них MDI.

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

Построение рамки MDI
-----------------------------------------------------------------

Окно-рамка MDI всегда является основным окном приложения,
поэтому оно конструируется в методе InitMainWindow его объекта
приложения. Однако, существует два аспекта рамки MDI, которые от-
личают его от других основных окон:

* Рамка MDI всегда является основным окном, поэтому оно ни-
когда не имеет порождающего окна. Таким образом,
TMDIWindow.Init нет необходимости воспринимать в качестве
параметра указатель порождающего окна.

* Окно-рамка MDI всегда должно иметь меню, так что вторым
параметром Init является описатель меню. Для основных
окон, отличных от MDI и производных от TWindows, вы опре-
деляете Init для установки Attr.Menu в допустимый описа-
тель меню. TMDIWindow.Init устанавливает для вас AttrMenu.

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

procedure TMDIApplication.InitMainWindow;
begin
MainWindow := New(PMyFrame, Init('Заголовок рамки',
LoadMenu(HInstance, 'MenuName'));

Если предположить, что TMyFrame - это потомок TMDIWindow,
при этом будет создаваться окно-рамка MDI с заголовком "Заголовок
рамки" и строкой меню, заданной ресурсом "MenuName".

Создание меню дочерних окон
-----------------------------------------------------------------

Меню окна-рамки должно включать в себя меню дочернего окна в
стиле MDI. Открытие дочернего окна MDI добавляет его заголовок к
меню дочернего окна, а закрытие дочернего окна удаляет его из
списка. Это позволяет пользователю активизировать любое дочернее
окно, даже если оно не является видимым.

Окно-рамка должно знать, каким элементом меню верхнего уров-
ня является меню его дочернего окна. Объект TMDIWindow хранит це-
лое значение позиции в поле объекта ChildMenuPos. TMDIWindow.Init

B.Pascal 7 & Objects/OW - 254 -

первоначально устанавливает ChildMenuPos в ноль, указывая край-
ний левый элемент меню верхнего уровня. Однако, для установки по-
зиции ChildMenuPos вы можете переопределить Init для своего про-
изводного от TMDIWindow типа:

constructor TMyMDIWindow.Init(ATitle: PChar; AMenu: HMenu);
begin
inherited Init(ATitle, AMenu);
ChildMenuPos := 1;
end;

TMDIWindow.Init также вызывает InitClientWindow для констру-
ирования объекта TMDIClient, который будет служит его окном кли-
ента MDI. TMDIWindow.SetupWindow создает окно клиента MDI.

Создание дочерних окон MDI
-----------------------------------------------------------------

TMDIWindow определяет автоматический метод реакции
CreateChild, который вызывается при выборе из меню варианта, ре-
зультатом которого будет команда с идентификатором Create_Child.
Обычно этот вариант меню называется New или Create. Как это опре-
делено в TMDIWindow, CreateChild конструирует и создает дочернее
окно MDI типа TWindow вызовом TMDIWindow.InitChild. Для задания
корректного типа дочернего окна (производного от TWindow), пере-
определим InitChild для вашего типа окна-рамки MDI:

function MyMDIWindow.InitChild: PWindowsObject;
begin
InitChild:=New(PMyChild, Init(@Self,
'Новое дочернее окно'));
end;

Автоматические дочерние окна
-----------------------------------------------------------------

Может потребоваться, чтобы ваша окно-рамка воспроизводило
только одно дочернее окно MDI при своем первом появлении. Для
этого первого дочернего окна вы можете явно задать его размер. В
отличие от других дочерних окон, дочерние окна MDI должны быть
сконструированы и созданы в методе SetupWindow окна-рамки MDI, а
не в Init. Вы также должны явно создать экранный элемент дочерне-
го окна с помощью вызова MakeWindow:

procedure MyMDIWindow.SetupWindow;
var
ARect: TRect;
NewChild: PMyChild;
begin
TMDIWindow.SetupWindow;
NewChild:=PMyChild(InitChild);
GetClientRect(HWindow, ARect);
with NewChild^.Attr, ARect do

B.Pascal 7 & Objects/OW - 255 -

begin
W:=(right*4) div 5;
H:=(bottom*3) div 5;
Title:='Child #1';
end;
Application^.MakeWindow(NewChild);
end;

В некоторых приложениях вам может потребоваться создать до-
чернее окно MDI в ответ на более чем один выбор в меню. Например,
пункты меню New и Open в редакторе файла могут приводить к воз-
никновению нового дочернего окна с заголовком в виде имени файла.
В этом случае определите для построения дочернего окна методы ав-
томатической реакции. ObjectWindows определяет команды
cm_MDIFileOpen и cm_MDIFileNew, что облегчает дифференциацию от
стандартных cm_FileOpen и cm_FileNew.

Управление дочерним окном MDI
-----------------------------------------------------------------

Тип окна MDI в ObjectWindows содержит методы манипулирования
дочерними окнами MDI приложения MDI. Хотя большая часть скрытой
работы делается в TMDIClient, доступ к данным и функциям происхо-
дит через метод TMDIWindow.

TMDIWindow определяет методы реакции на сообщения Windows,
которые автоматически реагируют на выбор команды стандартного ме-
ню MDI: Title, Cascade, Arrange Icon и Close All. Эти методы ожи-
дают основанных на командах сообщений с заранее определенными
константами идентификаторов меню. Обязательно используйте эти
идентификаторы при построении ресурса меню дочернего окна:

Стандартные методы, команды и действия MDI Таблица 14.1
-----------------T------------------------T---------------------¬
¦ Действие ¦ Константа ID меню ¦ Метод TMDIWindow ¦
+----------------+------------------------+---------------------+
¦ Tile ¦ cm_TileChildren ¦ CM_TileChildren ¦
¦ Cascade ¦ cm_CascadeChildren ¦ CM_CascadeChildren ¦
¦ Arrange Icons¦ cm_ArrangeChildIcons ¦ CM_ArrangeChildIcons¦
¦ Close All ¦ cm_CloseChildren ¦ CM_CloseChildren ¦
L----------------+------------------------+----------------------

Методы реакции TMDIWindows, подобные CMTileChildren, вызыва-
ют другие методы TMDIWindows, такие как CMChildren. Эти методы
вызывают методы TMDIClient с тем же именем, например,
TMDIClient^.TileChildren. Для переопределения такого автоматичес-
кого поведения нужно переопределить TMDIWindow.TileChildren или
другой метод TMDIWindow. Для дочерних окон MDI не подходит реаги-
рование на основанные на командах сообщения, генерируемые меню
дочернего окна.



B.Pascal 7 & Objects/OW - 256 -

Настройка активизации дочернего окна
-----------------------------------------------------------------

Пользователь приложения MDI может свободно активизировать
любое открытое или минимизировать дочернее окно MDI. Однако, вам
может потребоваться предпринять некоторые действия, когда пользо-
ватель дезактивирует одно дочернее окно активизацией другого.
Например, меню окна-рамки может отражать текущее состояние актив-
ного дочернего окна, выделяя его цветом. Каждый раз, когда дочер-
нее окно становится активным или неактивным, оно получает сообще-
ние Windows wm_MDIActivate. Определив метод реакции на это с об-
щение для дочернего окна, вы можете отслеживать, какое дочернее
окно активно и соответственно реагировать.

Обработка сообщений в приложении MDI
-----------------------------------------------------------------

Как и для обычных порождающих и дочерних окон, основанные на
командах и дочерних идентификаторах сообщения Windows сначала
поступают в дочерние окна для их восприятия и обработки. Затем
сообщения поступают в порождающее окно. Однако, в случае приложе-
ния MDI сообщения поступают к текущему дочернему окну MDI, затем
к окну клиента MDI, и, наконец, к окну-рамке MDI (которое являет-
ся порождающим окном для всех дочерних окон MDI). Следовательно,
меню окна-рамки можно использовать для управления работой в теку-
щем активном дочернем окне MDI. Затем шанс отреагировать получают
окно клиента и окно-рамка.

Пример приложения MDI
-----------------------------------------------------------------

Программа MDITest создает приложение MDI, показанное на
Рис. 14.1. Полный текст файла MDITEST.PAS содержится на ваших
дистрибутивных дискетах.



B.Pascal 7 & Objects/OW - 257 -

------------------------------------------------------------------
Глава 15. Объекты печати
-----------------------------------------------------------------

Один из наиболее трудных аспектов программирования в Windows
- это вывод на принтер. ObjectWindows путем использования ряда
модулей и инкапсуляции поведения устройства печати и самой распе-
чатки делает печать более простой.

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

* Построение объекта принтера.

* Создание распечатки.

- Печать документа.

- Печать содержимого окна.

* Передача распечатки на принтер.

* Выбор другого принтера.

* Настройка конфигурации принтера.

Почему печать представляет трудности?
-----------------------------------------------------------------

С одной стороны печать в Windows достаточно проста. Вы може-
те использовать для генерации распечатки те же функции GDI, что
используются для вывода образов на экран. Для вывода текста ис-
пользуется функция TextOut, а для вычерчивания прямоугольника -
Rectangle.

С другой стороны, процесс осложняется, так как Windows тре-
бует непосредственного "общения" с драйверами принтера через вы-
зовы Escape или получения адреса DeviceMode или ExtDeviceMode.
Это еще более осложняется требованием Windows, чтобы приложение
считывало имя драйвера устройства из файла WIN.INI. Кроме того,
устройства печати обладают большими возможностями проверки допус-
тимости и возможностями разрешения, чем видеоустройства.

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

Печать в ObjectWindows
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 258 -

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

TPtintout инкапсулирует задачу печати документа. К принтеру
этот объект имеет такое же отношение, как TWindow - к экрану. Ри-
сование на экране выполняется методом Paint объекта TWindow, а
печать на принтере - методом PrintPage объекта TPrintout. Чтобы
напечатать что-то на принтере, приложение должно передать методу
Print объекта TPrinter экземпляр TPrintout.

Построение объекта принтера
-----------------------------------------------------------------

В большинстве случаев приложению требуется в каждый момент
времени доступ только к одному принтеру. Простейшим способом реа-
лизации этого является задание в объекте основного окна поля с
именем Printer (типа PPrinter), которые другие объекты в програм-
ме вызывают для целей печати. Чтобы сделать принтер доступным,
поле Printer должно указывать на экземпляр TPrinter.

В большинстве приложений это просто. Основное окно приложе-
ния инициализирует объект принтера, который использует заданный
по умолчанию принтер, указанный в WIN.INI:

constructor TSomeWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
Inherited Init(AParent, ATitle);
.
.
.
Printer := New(PPrinter, Init);
end;

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

Хотя вы можете сомневаться насчет переопределения конструк-
тора TPrinter для использования принтера, отличного от заданного
в системе по умолчанию, рекомендуемой процедурой является исполь-
зование конструктора по умолчанию, а затем смена связанного с
объектом устройства. См. раздел "Выбор другого принтера".



B.Pascal 7 & Objects/OW - 259 -

Создание распечатки
-----------------------------------------------------------------

Единственной "хитрой" частью процесса печати в ObjectWindows
являются создание распечатки. Этот процесс аналогичен написанию
метода Paint для объекта окна: вы используете графические функции
Windows для генерации в контексте устройства нужного графического
образа. Контекст устройства оконного объекта обрабатывает ваши
взаимодействия с устройством экрана; аналогичным образом контекст
устройства распечатки изолирует вас от устройства печати.

Примечание: Графические функции Windows поясняются в
Главе 17.

Чтобы создать объект распечатки, постройте новый тип, произ-
водный от TPtintout, который переопределяет PrintPage. В очень
простых случаях это все, что требуется сделать. Если документ
имеет размер более одной страницы, то вам нужно также переопреде-
лить HasNextPage для возврата True. Текущий номер страницы пере-
дается в качестве параметра PrintPage.

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

Модуль OPrinter включает в себя два специализированных объ-
екта распечатки, которые показывают диапазон сложности распеча-
ток. Объект TWindowPrintout, печатающий содержимое окна, очень
прост. TEditPrintout, который печатает содержимое управляющего
элемента редактирования, очень сложен, так как имеет множество
возможностей.

Печать документа
-----------------------------------------------------------------

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

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

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

* Устанавливать параметры принтера.


B.Pascal 7 & Objects/OW - 260 -

* Подсчитывать страницы.

* Отображать каждую страницу в контексте устройства.

* Указывать, есть ли еще страницы.

Остальная часть этой главы ссылается на пример программы
PrnTest, записанной на ваших дистрибутивных дискетах под именем
PRNTEST.PAS. PrnTest считывает текстовый файл в набор строк, а
затем по команде печатает документ. Объект PrnTest описывается
следующим образом:

type
PTextPrint = ^TTextPrint;
TTextPrint = object(TPrintout);
TextHeight, LinesPerPage, FirstOnPage, LastOnPage:
Integer;
TheLines; PCollection;
constructor Init(ATitle: PChar;
TheText: PPCharCollection);
function GetDialogInfo(var Pages: Intger): Boolean;
virtual;
function HasNextPage(Page: Word): Boolean; virtual;
procedure SetPrintParams(ADC: HDC; ASize: TPoint);
virtual;
procedure PrintPage(Page: Word; var Rect: TRect;
Flags: Word); virtual;
end;

Задание параметров печати
-----------------------------------------------------------------

Перед запросом распечатки документа объект принтера предос-
тавляет вашему документу возможность разбивки на страницы. Для
этого вызываются два метода объекта распечатки - SetPrintParams и
GetDialogInfo.

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

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

Подсчет страниц
-----------------------------------------------------------------

После вызова SetPrintParams объект печати вызывает булевскую

B.Pascal 7 & Objects/OW - 261 -

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

Функция GetDialogInfo воспринимает единственный параметр-пе-
ременную Pages, которую она должна устанавливать в число страниц
в документе или в 0, если она не может подсчитать страницы. Возв-
ращаемое значение равно True, если вы хотите вывести диалоговый
блок, и False для подавления его вывода.

По умолчанию GetDialogInfo устанавливает Pages в 0 и возвра-
щает True, что означает, что она не знает, сколько может полу-
читься страниц, и что перед печатью будет выводиться диалоговый
блок. GetDialogInfo обычно переопределяется для установки Pages в
число страниц в документе и возвращает True.

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

procedure TTextPrint.SetPrintParams(ADC: HDC;
ASize: TPoint);
var TextMetrics: TTextMetric;
begin
inherited SetPrintParams(ADC, ASize); { установить DC и
размер Size }
GetTextMetrics(DC, TextMetrics); { получить информацию о
размере текста }
TextHeigh := TextMetrics.tmHeight; { вычислить высоту
строки }
LinesPerPages := Size.Y div TextHeight; { и число строк
на странице }
end;

function TTextPtint.GetDialogInfo(var Pages: Integer):
Boolean);
begin
Pages:= TheLines^.Count div LinesPerPage + 1;
GetDialogInfo := True { вывод перед печатью диалогового
блоки }
end;

Печать каждой страницы
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 262 -

жать на экране. Например, можно отметить подобие методов отобра-
жения окна и отображения страницы:

procedure TTextWindow.Paint(PaintDC: HDC;
var PaintInfo: TPaintStruct);
var
Line: Integer;
TextMetrics: TTextMetric;
TheText: PChar;

function TextVisible(ALine: Integer): Boolean;
begin
with Scroller^ do
TextVisible := IsVisible(0, (ALine div YUnit) +
YPos, 1, Attr.W div YUnit);
end;

begin
GetTextMetrics(PaintDC, TextMetrics);
Scroller^.SetUnits(TextMetrics.tmAveCharWidth,
TextMetrics.tmHeight);
Line := 0;
while (Line < FileLines^.Count) and TextVisible(Line) do
begin
TheText := PChar(FileLines^.At(Line));
if TheText <> nil then
TextOut(PaintDC, 0, Line * Scroller^.YUnit, TheText,
StrLen(TheText));
Inc(Line);
end;
end;

procedure TTextPrint.PrintPage(Page: Word; var Rect: TRect;
Flags: Word);
var
Line: Integer;
TheText: PChar;
begin
FirstOnPage := (Page - 1) * LinesPerPage;
LastOnPage := (Page * LinesPerPage) - 1;
if LastOnPage >= TheLines^.Count then
LastOnPage := TheLines^.Count - 1;
for Line := FirstOnPage to LastOnPage do
begin
TheText := Theines^.At(Line);
if TheText <> nil then
TextOut(DC, 0, (Line - FirstOnPage) * TextHeight,
TheText, StrLen(TheText));
end;
end;

При написании методов PrintPage следует иметь в виду следую-
щее:

B.Pascal 7 & Objects/OW - 263 -


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

* Возможности устройств. Хотя большинство видеоустройств
поддерживают все операции GDI, некоторые принтеры этого не
делают. Например, многие устройства печати (такие как гра-
фопостроители) совсем не воспринимают графических изобра-
жений. При выполнении сложных задач вывода в программе
следует вызывать функцию API Windows GetDeviceCaps, кото-
рая возвращает важную информацию о данном устройстве выво-
да.

Указание оставшихся страниц
-----------------------------------------------------------------

У объектов распечатки имеется также последняя обязанность -
указать объекту принтера, имеются ли после данной страницы еще
печатаемые страницы. Метод HasNextPage воспринимает в качестве
параметра номер строки и возвращает значение Boolean, указываю-
щее, существуют ли еще страницы. По умолчанию HasNextPage всегда
возвращает значение False. Чтобы напечатать несколько страниц,
ваши объекты распечатки должны переопределять HasNextPage для
возврата True, если документ имеет больше страниц для печати, и
False, если переданным параметром является последняя страница.

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

function TTextPrint.HasNextPage(Page: Word): Boolean;
begin
HasNextPage := LastOnPage < TheLines^.Count - 1;
end;

Убедитесь, что HasNextPage возвращает в некоторой точке зна-
чение False. Если HasNextPage всегда возвращает True, то процесс
печати попадет в бесконечный цикл.

Другие соглашения по печати
-----------------------------------------------------------------

Объекты распечатки содержат также несколько других методов,
которые вы можете при необходимости переопределить. Методы
BeginPrintint и EndPrinting вызываются, соответственно, перед пе-
чатью и после печати любого документа. Если вам требуется специ-
альная установка, вы можете выполнить ее в BeginPrinting и отме-
нить в EndPrinting.


B.Pascal 7 & Objects/OW - 264 -

Печать страниц выполняется последовательно. То есть, для
каждой страницы в последовательности принтер вызывает метод
PrintPage. Однако, перед первым вызовом PrintPage объект принтера
вызывает BeginDocument, передавая номер первой и последней стра-
ницы, которые будут печататься. Если для вашего документа при пе-
чати страниц, отличных от первой, требуется специальная подготов-
ка, переопределите метод BeginDocument. После распечатки послед-
ней страницы вызывается соответствующий метод EndDocument.

Может потребоваться также переопределение метода
GetSelection. GetSelection указывает в своем возвращаемом булевс-
ком значении, имеет ли документ выделенную часть. Если это так,
диалоговое окно печати предоставляет вам возможность распечатать
только эту выделенную часть. Позицию выделения указывают два па-
раметра-переменных Start и Stop. Например, TEditPrintout интерп-
ретирует Start и Stop как позиции символов, но может представлять
также строки текста, страницы и т.д.

Печать содержимое окна
-----------------------------------------------------------------

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

Чтобы еще более облегчить эту общую операцию, ObjectWindows
обеспечивает дополнительный вид объекта распечатки -
TWindowPrint. Любой оконный объект ObjectWindows может без моди-
фикации печатать свое содержимое в объект TWindowPrintout. Объек-
ты распечатки масштабируют образ для заполнения нужного числа
страниц и поддерживают коэффициент относительного удлинения.

Создание объекта распечатки окна требует только одного шага.
Все, что требуется сделать - это построить объект печати окна,
передавая ему строку заголовка и указатель на окно, которое тре-
буется напечатать:

PImage := New(PWindowPrintout, Init('Заголовок',
PSomeWindow));

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

procedure TSomeWindow.CMPrint(var Msg: TMessage);
var P: PPrintout;
begin
P := New(PWindowPrintout, Init('Дамп экрана', @Self));
{ передать образ на экран }
Dispose(P, One);
end;

TWindowPrintout не предусматривает разбивки на страницы. При

B.Pascal 7 & Objects/OW - 265 -

печати документа вам нужно печатать каждую страницу отдельно, но
так как окна не имеют страниц, вам нужно напечатать только один
образ. Окно уже знает, как создать этот образ - оно имеет метод
Paint. TWindowsPrintout печатается путем вызова метода Paint окна
объекта с контекстом устройства печати вместо контекста дисплея.

Вывод распечатки на принтер
-----------------------------------------------------------------

При наличии объекта принтера и объекта распечатки фактичес-
кая печать выполняется достаточно просто, независимо от того,
происходит это из документа или из окна. Все, что вам нужно сде-
лать - это вызов метода Paint объекта принтера, передача указате-
ля на порождающее окно и указателя на объект распечатки:

Printer^.Print(PParentWindow, PPrintoutObject);

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

Предположим, у вас есть приложение, основное окно которого
является экземпляром TWidGetWindow. В меню этого окна вы можете
выбрать команду меню для печати содержимого окна, генерирующую
команду cm_Print. Метод реакции на сообщения может иметь следую-
щий вид:

procedure TWidgetWindow.CMPrint(var Msg: TMessage);
var P: PPrintout;
begin
P := New(PWindowPrint, Init('Widgets', @Self));
Printer^.Print(@Self, P);
Dispose(P, Done);
end;

Выбор другого принтера
-----------------------------------------------------------------

Когда у вас в приложении есть объект принтера, вы можете
связать его с любым установленным в Windows устройстве печати. По
умолчанию TPrinter использует заданный по умолчанию принтер
Windows (как это определено в разделе устройств файла WIN.INI).

Существует два способа задания альтернативного принтера: не-
посредственно в программе и через диалоговое окно пользователя.



B.Pascal 7 & Objects/OW - 266 -

Выбор принтера пользователем
-----------------------------------------------------------------

Наиболее общим способом назначения другого принтера является
вывод диалогового окна, предоставляющего пользователю возможность
выбора из списка установленных устройств печати. TPtinter делает
это автоматически при вызове его метода Setup. Как показано на
Рис. 15.1, Setup использует для этого диалогового окна объект
TPrinterSetupDlg.

----------------------------------------------------------------¬
¦-=--------------------SelectPrinter----------------------------¦
+---------------------------------------------------------------+
¦ ¦
¦ Printer and port: ¦
¦ ---------------------------------------------T-¬ ¦
¦ ¦PostScript Printer on LPT1: ¦v¦ ¦
¦ L--------------------------------------------+-- ¦
¦ ------------¬ ------------¬ ------------¬ ¦
¦ ¦----OK-----¦ ¦--Setup----¦ ¦--Cancel---¦ ¦
¦ L------------ L------------ L------------ ¦
¦ ¦
L----------------------------------------------------------------

Рис. 15.1 Диалоговое окно задания принтера.

Настройка конфигурации принтера

Одна из командных кнопок в диалоге выбора принтера позволяет
пользователям изменить конфигурацию конкретного принтера. Кнопка
Setup выводит диалоговый блок конфигурации, определенной в драй-
вере принтера. Ваше приложение не может управлять внешним видом
или функциями диалогового блока конфигурации драйвера.

Назначение конкретного принтера
-----------------------------------------------------------------

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

SetDevice воспринимает в качестве параметров три строки: имя
устройства, имя драйвера и имя порта.



B.Pascal 7 & Objects/OW - 267 -

------------------------------------------------------------------
Часть 3. Продвинутое
программирование с использование ObjectWindows
-----------------------------------------------------------------


Глава 16. Сообщения Windows
-----------------------------------------------------------------

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

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

* что такое сообщение?

* как выполняется диспетчеризация сообщений?

* обработка сообщений Windows;

* определение ваших собственных сообщений;

* передача и адресация сообщений;

* диапазоны сообщений.

Что такое сообщение?
-----------------------------------------------------------------

Если вы не используете программирование, управляемое событи-
ями, Windows может выглядеть достаточно странной операционной
средой. Возможно, вам придется писать программы, которые основную
часть своего времени просто ждут ввода от пользователя (например,
в операторе Readln).

Программирование, управляемое событиями, обходит эту ситуа-
цию, возлагая обработку ввода от пользователя на центральную
подпрограмму, которую вам даже не нужно вызывать. В этом случае
Microsoft Windows сама взаимодействует с пользователем и опраши-
вает список взаимодействий для каждого работающего приложения.
Эти информационные пакеты называются сообщениями и представляют
собой просто структуры записей типа TMsg:

type
TMsg = record
hwnd: HWnd;
message: Word;
wParam: Word;
lParam: Longint;

B.Pascal 7 & Objects/OW - 268 -

time: Longint;
pt: TPoint;
end;

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

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

Именующие сообщения
-----------------------------------------------------------------

Наиболее важным полем сообщений является поле message, кото-
рое содержит одну из констант сообщений Windows, начинающихся с
wm_. Каждое сообщение Windows уникальным образом идентифицируется
16-битовым числом с соответствующим мнемоническим идентификато-
ром. Например, сообщение, являющееся результатом нажатия клавиши,
содержит в поле сообщения wm_KeyDown ($0100). На сообщения обычно
ссылаются по их мнемоническим именам.

Откуда поступают сообщения
-----------------------------------------------------------------

Генерировать сообщения позволяют несколько различных событий:

* взаимодействия с пользователем, такие как нажатия клавиш,
щелчок кнопкой "мыши" или ее буксировка;
* вызовы функций Windows, которым нужно информировать об из-
менениях другие окна;
* ваша программа явно посылает сообщение;
* другое приложение посылает сообщение через DDE (динамичес-
кий обмен данными);
* сообщение генерируется самой Windows (например, сообщение
об останове системы).

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



B.Pascal 7 & Objects/OW - 269 -

Обычная диспетчеризация сообщений
-----------------------------------------------------------------

Обычные приложения Windows (то есть не использующие
ObjectWindows) имеют цикл сообщения, в котором выполняется выбор-
ка и диспетчеризация сообщения. По существу, в цикле сообщения
вызывается связанная с окном функция, заданная описателем окна в
поле hwnd записи сообщения.

Каждое окно имеет функцию окна, заданную при его создании.
Когда Windows находит сообщение для конкретного окна, она переда-
ет сообщение функции данного окна. Функция окна отсортировывает
сообщения на основе типа сообщения, а затем вызывает подпрограмму
реакции на конкретное сообщение.

Обычный способ обработки сообщений в приложении и его окнах
показывает программа GENERIC.PAS. Вы можете видеть, что оконная
функция каждого окна для сортировки сообщение содержит большой
оператор case. Все это может выглядеть не так плохо, пока вы не
осознаете тот факт, что в окне может потребоваться обрабатывать
более 100 различных сообщений Windows. После этого идея написания
и обслуживания такого оператора case будет выглядеть менее впе-
чатляющей.

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

Способ, предлагаемый ObjectWindows
-----------------------------------------------------------------

ObjectWindows вносит в это обычный способ диспетчеризации
сообщений два основных улучшения. Первое состоит в том, что цикл
сообщений скрыт в ядре вашего объекта приложения. Все, что вам
нужно сделать - это привести свое приложение в действие, вызвав
метод Run объекта приложения. После этого оно будет получать со-
общения Windows.

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



B.Pascal 7 & Objects/OW - 270 -

Динамические виртуальные методы
-----------------------------------------------------------------

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

Например, сообщение, генерируемое при нажатии в окне левой
кнопки "мыши", содержит в своем поле message wm_LButtonDown
($0201). Когда цикл сообщения ObjectWindows считывает для одного
из своих окон такое сообщение, то выполняется поиск в таблице
виртуальных методов данного оконного объекта и определяется дина-
мический метод, описанный для данного значения. Если такой метод
найден, то он вызывается, и ему в качестве параметра передается
распакованная запись сообщения типа TMessage. Если оконный объект
не описывает метод с данным индексом динамического метода, то
цикл сообщения вызывает используемую по умолчанию оконную проце-
дуру.

Написание методов реакции на сообщение
-----------------------------------------------------------------

Чтобы описать методы реакции на сообщение, нужно задать в
оконном объекте процедуру, названную по имени константы сообще-
ния. Например, чтобы ответить на сообщение wm_LButtonDown, вам
нужно описать методы следующим образом:

type
TMyWindow = object(TWindow)
.
.
.
procedure WMLButtonDown(var Msg: TMessage);
virtual wm_First + wm_LButtonDown;
.
.
.
end;

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

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

B.Pascal 7 & Objects/OW - 271 -

ческого метода. Подробнее о диапазонах сообщений рассказывается в
разделе "Диапазоны сообщений" данной главы.

Что такое сообщение?
-----------------------------------------------------------------

Теперь, когда вы знаете, как написать метод реакции на сооб-
щение, можно рассмотреть, какая информация содержится в сообще-
нии. Запись TMessage, передаваемая методу реакции на сообщение,
выглядит следующим образом:

type
TMessage = record
Receiver: HWnd;
Message: Word;
case Integer of
0: (
WParam: Word;
LParam: Longint;
Result: Longint);
1: (
WParamLo: Byte;
WParamHi: Byte;
LParamLo: Word;
LParamHi: Word;
ResultLo: Word;
ResultHi: Word);
end;

Поля Receiver и Message для объектов ObjectWindows не осо-
бенно полезны, поскольку описатель Receiver обычно представляет
собой тоже самое, что и поле HWindow оконного объекта, а Message
уже отсортировано в цикле сообщения ObjectWindows.

Однако другие три поля очень важны. WParam и LParam - это
16- и 32-битовые параметры, передаваемые в сообщениях от Windows.
Result содержит код результата, который может потребоваться пере-
дать обратно. Заметим, что TMessage - вариантная запись, так что
вы можете обращаться к старшему и младшему байту слов параметров.

Поля параметров
-----------------------------------------------------------------

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

WParam

Параметр WParam типа Word обычно содержит описатель, иден-
тификатор (например, идентификатор управляющего элемента) или бу-
левское значение. Например, параметр WParam сообщения
wm_SetCursor содержит описатель окна, в котором находится курсор.
Уведомляющие сообщения управляющего элемента, такие как

B.Pascal 7 & Objects/OW - 272 -

bn_Clicked, содержат в WParam идентификатор соответствующего уп-
равляющего элемента. wm_Enable использует WParam для булевского
значения, указывающего, разрешено или запрещено соответствующее
окно.

LParam

Параметр LParam типа Longint обычно содержит значение-указа-
тель двух переменных размером в слово, таких как координаты x и
y. Например, параметр LParam сообщения wm_SetText указывает на
строку с завершающим нулем, содержащую устанавливаемый текст. Со-
общения "мыши", такие как wm_LButtonDown, используют LParam для
записи координат события "мыши". Благодаря вариантным частям за-
писи сообщения, LParamLo содержит x-координату, а LParamHi -
y-координату.

Поле Result
-----------------------------------------------------------------

Поле Result сообщения TMessage управляет возвращаемым значе-
нием сообщения. Иногда программа, посылающая сообщение, ожидает
возврата конкретного значения, такого как булевское значение,
указывающее успешное или неуспешное выполнение или код ошибки. Вы
можете задать возвращаемое значение, присвоив значение полю
Result.

Например, когда пользователь пытается восстановить окно из
состояния пиктограммы, ему посылается сообщение wm_QueryOpen. По
умолчанию wm_QueryOpen возвращает булевское значение True (не
ноль). Если вы хотите иметь окно, которое всегда выводится в виде
пиктограммы, то вы можете ответить на сообщение wm_QueryOpen и
установить Result в 0. Это означает, что окно не может быть отк-
рыто:

procedure TIconWindow.WMQueryOpen(var Msg: TMessage);
begin
Msg.Result := 0;
end;

Объектно-ориентированная обработка сообщения
-----------------------------------------------------------------

Одним из огромных преимуществ обработки сообщения в
ObjectWindows (кроме того, что можно избавиться от больших опера-
торов case) является обработка сообщений объектно-ориентированным
способом. То есть, ваши оконные объекты наследуют возможность оп-
ределенной реакции на сообщения, и вам нужно только изменить ре-
акцию на конкретные сообщения, которые ваш объект обрабатывает
по-другому.

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


B.Pascal 7 & Objects/OW - 273 -

Иногда, когда вы переопределяете используемую по умолчанию
реакцию на сообщение, это делается потому что данное поведение
просто нежелательно. Простейшим случаем является ситуация, когда
объект должен игнорировать сообщение, а не отвечать на него. Для
этого вы можете просто написать пустой метод реакции на сообще-
ние. Например, следующий метод сообщает управляющему элементу ре-
дактирования, что нужно игнорировать передаваемые в сообщении
wm_Char символы:

procedure TNonEdit.WMChar(var Msg: TMessage);
begin
end;

Замена поведения по умолчанию
-----------------------------------------------------------------

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

procedure TBeepEdit.WMChar(var Msg: TMessage);
begin
MessageBeep(0);
end;

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

Дополнение поведения по умолчанию
-----------------------------------------------------------------

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

Вызов наследуемых методов
-----------------------------------------------------------------

Предположим, например, что вы создали новый оконный объект и
хотите, чтобы он в дополнение к другим обычно выполняемым дейс-
твиям он давал звуковой сигнал при щелчке в окне левой кнопкой
"мыши". Все, что вам нужно сделать - это вызов в вашем новом ме-
тоде наследуемого метода TWindow.WMLButtonDown:


B.Pascal 7 & Objects/OW - 274 -

procedure TBeepWindow.WMLButtonDown(var Msg: TMessage);
begin
inherited WMLButtonDown(Msg);
MessageBeep(0);
end;

В данном случае неважно, размещаете ли вы вызов наследуемого
метода WMLButtonDown перед или после вызова MessageBeep. Вам нуж-
но решить, должен ли ваш метод вызывать наследуемые действия пе-
ред специальной обработкой или после нее (на основе того, нужны
ли вам параметры сообщения, или требуется их изменить).

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

Вызов процедур, используемых по умолчанию
-----------------------------------------------------------------

Как вы могли заметить, в данном разделе при вызове наследу-
емых методов используется не такой пример, как в предыдущих раз-
делах. Вы, возможно, ожидали, что новый управляющий элемент ре-
дактирования для обработки действия по умолчанию будет вызывать
свой наследуемый метод WMChar. Это имеет смысл, но не будет рабо-
тать, так как TEdit не имеет метода WMChar, поэтому производный
из TEdit объект не может вызывать WMChar в качестве наследуемого
метода.

К счастью, ваши объекты все равно могут наследовать реакцию
на сообщения. Когда ObjectWindows диспетчеризует сообщение объек-
ту, и этот объект не определяет конкретного метода реакции,
ObjectWindows передает запись TMessage методу с именем DefWndProc
- используемой по умолчанию оконной процедуре. DefWndProc знает,
как применять действия по умолчанию для всех сообщений. Таким об-
разом, если компилятор дает ошибку, когда вы пытаетесь наследо-
вать метод реакции на сообщения, поскольку для данного сообщения
нет наследуемого метода, вызовите вместо этого DefWndProc.

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

procedure TBeepEdit.WMChar(var Msg: TMessage);
begin
MessageBeep(0);
DefWndProc(Msg);
end;

Вызов DefWndProc вы можете рассматривать как используемый

B.Pascal 7 & Objects/OW - 275 -

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

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

Сообщение - это просто запись данных, идентифицируемая конк-
ретным значением в поле message, а ObjectWindows экономит вам
массу времени и усилий путем сортировки этих сообщений и диспет-
черизации их методам реакции на сообщения в ваших объектах. Одна-
ко, сообщение Windows wm_Command имеет много вариантов, которые
нужно отсортировывать с помощью большого оператора case.
ObjectWindows также выполняет это для вас.

Например, сообщение wm_Command посылается при выборе элемен-
та меню или нажатии оперативной клавиши. В обычном приложении
сообщение Windows передавалось бы вашей функции окна, где в боль-
шом операторе case нужно было бы отсортировать различные сообще-
ния, вызывая другие подпрограммы при обнаружении wm_Command. Эта
подпрограмма должна в свою очередь определить, какая была переда-
на команда (с помощью другого большого оператора case).

Командные сообщения
-----------------------------------------------------------------

ObjectWindows обрабатывает команды меню и оперативных клавиш
путем отдельной диспетчеризации командных сообщений в основном
аналогично другим сообщениям Windows. Реально обработка выполня-
ется внутри метода WMCommand ваших оконных объектов, наследуемого
из TWindowsObject. Но вместо обработки самих команд WMCommand вы-
полняет диспетчеризацию командных сообщений на основе генерируе-
мого командой идентификатора меню или оперативной клавиши.

Например, если вы определяете элемент меню с идентификатором
cm_DoSomething, в ваших объектах следует на основе этого иденти-
фикатора определить методы реакции:

type
TSomeWindow = object(TWindow)
.
.
.
procedure CMDoSomething(var Msg: TMessage);
virtual cm_First + cm_DoSomething;
end;

procedure TSomeWindow.CMDoSomething(var Msg: TMessage);
begin
{ реакция на команду }

B.Pascal 7 & Objects/OW - 276 -

end;

Аналогично wm_First, cm_First - это константа ObjectWindows,
определяющая начало диапазона сообщений. Ваши командные константы
должны лежать в диапазоне 0..24319.

Обработка команд по умолчанию

Чтобы вызвать используемую по умолчанию реакцию на команду,
для нее обычно вызывается наследуемый метод реакции. Если в объ-
екте-предке не определяется метод реакции на конкретную команду,
по умолчанию обработка выполняется с помощью DefCommandProc.
DefCommandProc работает во многом аналогично методу DefWndProc
для сообщений Windows, но обрабатывает команды.

Уведомляющие сообщения
-----------------------------------------------------------------

Команды не обязательно должны поступать от меню или команд-
ных клавиш. Управляющие элементы в окнах посылают сообщения своим
порождающим окнам, когда вы щелкаете на них "мышью" или что-либо
набираете. Эти сообщения называются уведомляющими сообщениями, и
ObjectWindows обрабатывает их двумя различными путями.

В основном уведомления могут передаваться объекту управляю-
щего элемента или его порождающему окну. Если управляющий элемент
имеет связанный с ним объект ObjectWindows, ObjectWindows дает
объекту возможность сначала ответить на команду. Это называется
уведомлением управляющего элемента. Если управляющий элемент не
имеет соответствующего объекта, или объект управляющего элемента
не определяет реакцию на команду, то ответить имеет возможность
порождающее окно. Это называется уведомлением порождающего объек-
та.

Уведомления управляющих элементов
-----------------------------------------------------------------

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

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

type
TBeepButton = object(TButton)
procedure BNClicked(var Msg: TMessage);
virtual nf_First + bn_Clicked;
end;


B.Pascal 7 & Objects/OW - 277 -

procedure TBeepButton.BNClicked(var Msg: TMessage);
begin
MessageBeep(0);
end;

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

Уведомление порождающего объекта
-----------------------------------------------------------------

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

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

type
TMyWindow = object(TWindow)
.
.
.
procedure IDMyControl(var Msg: TMessage);
virtual id_First + id_MyControl;
end;

procedure TMyWindow.IDMyControl(var Msg: TMessage);
begin
{ реакция на сообщение }
end;

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

Windows редко определяет реакцию на конкретные управляющие
элементы, заданную по умолчанию. Однако, если вы хотите позабо-
титься о заданном по умолчанию поведении, то можете вызвать
DefChildProc. DefChildProc работает аналогично DefWndProc, но об-
рабатывает вместо сообщений Windows уведомляющее сообщение по-
рождающему объекту.



B.Pascal 7 & Objects/OW - 278 -

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

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

Например, с учетом приведенного выше объекта TBeepButton вы
можете также уведомлять порождающее окно с помощью добавления вы-
зова DefNotificationProc:

procedure TBeepButton.BNClicked(var Msg: TMessage);
begin
MessageBeep(0);
DefNotificationProc(Msg);
end;

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

Определение ваших собственных сообщений
-----------------------------------------------------------------

Windows резервирует для собственного использования 1024 со-
общения. В этот диапазон попадают все стандартные сообщения. На-
чало диапазона сообщений определяется константой wm_User. Чтобы
определить сообщение, используемое окнами вашей программы, опре-
делите идентификатор сообщения, попадающий в диапазон
wm_User..wm_User+31744.

Чтобы избежать конфликта со стандартными сообщениями, вам
следует определить идентификаторы своих сообщений как константы
на основе wn_User. Например, в приложении, где требуется три оп-
ределенных пользователем сообщения, вы можете описать их следую-
щим образом:

const
wm_MyFirstMessage = wm_User;
wm_MySecondMessage = wm_User + 1;
wm_MyThirdMessage = wm_User + 2;

Реакция на ваши сообщения аналогично реакции на любое другое
сообщение:

TCustomWindow = object(TWindow)

B.Pascal 7 & Objects/OW - 279 -

.
.
.
procedure WMMyFirstMessage(var Msg: TMessage);
virtual wm_First + wm_MyFirstMessage

Согласно общему правилу, определенные пользователем сообще-
ния следует использовать для внутреннего обмена сообщения. Если
вы посылаете определенное пользователем сообщение другому прило-
жению, нужно убедиться, что это другое приложение определяет со-
общение также, как это делается в коде вашего приложения. Внешние
коммуникации лучше обрабатываются с помощью динамического обмена
данными (DDE).

Передача сообщений
-----------------------------------------------------------------

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

ObjectWindows уже обеспечивает для вас способы передачи мно-
гих сообщений, которые в противном случае пришлось бы передавать
вручную. Например, общим случаем для генерации сообщений является
работа с управляющим элементами. Чтобы добавить строку в блок
списка, Windows определяет такие сообщения как lb_AddString, а
чтобы отменить выбор кнопки с зависимой фиксацией или выбрать ее
- bm_SetCheck. ObjectWindows определяет методы для объектов уп-
равляющих элементов (TListBox.AddString и TCheckBox.SetCheck),
посылающие для вас эти сообщения, так что вам даже не нужно ду-
мать об их использовании.

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

Передача и отправление сообщений
-----------------------------------------------------------------

Тем не менее, иногда возникает необходимость передачи сооб-
щений в окна вашего приложения. Windows предусматривает две функ-
ции, позволяющие вам генерировать сообщения - SendMessage и
PostMessage. Основное отличие этих двух функций состоит в том,
что SendMessage ожидает обработки сообщения перед возвратом.
PostMessage просто добавляет сообщение в очередь сообщений и
возвращает управление.

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

B.Pascal 7 & Objects/OW - 280 -

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

Передача сообщения
-----------------------------------------------------------------

Для передачи сообщения требуется следующее: описатель ок-
на-получателя, номер сообщения и параметры Word и Longint. В при-
ложении ObjectWindows описателем получателя является обычно поле
HWindow интерфейсного объекта. Идентификатор сообщения - это
просто константа, идентифицирующая конкретное сообщение, которое
вы хотите передать (такая как wm_More или em_SetTabStops). Пара-
метры в зависимости от сообщения могут быть различными.

Значение, возвращаемое SendMessage - это значение поля
Result в записи сообщения при завершении обработки. Имейте в ви-
ду, что если вы вызываете наследуемый или используемый по умолча-
нию метод реакции на сообщение, ваше значение может быть переза-
писано.

Windows с помощью SendMessage обеспечивает ограниченное
средство циркулярной рассылки сообщений. Если вы в качестве опи-
сателя окна, в которое нужно передать сообщение, зададите $FFFF,
Windows посылает сообщения всем всплывающим и перекрывающимся ок-
нам в системе (не только в вашем приложении). Таким образом, вы
не должны использовать циркулярную рассылку сообщений, опреде-
ляемых пользователем, так как не может быть уверены, что другое
приложение не определило данное сообщение каким-то другим спосо-
бом.

Отправление сообщения
-----------------------------------------------------------------

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

Передача сообщения управляющему элементу
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 281 -

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

Если управляющий элемент имеет связанный с ним объект, вы
можете просто использовать для получения идентификатора управляю-
щего элемента поле HWindow объекта. Если диалоговый блок имеет
связанный с ним объект, вы можете вызвать метод SendDlgItemMsg
объекта диалогового блока, для которого задаются идентификатор
управляющего элемента, идентификатор сообщения и два параметра
сообщения. В большинстве приложений ObjectWindows для вас досту-
пен любой их этих подходов.

Если по каким-то причинам у вас нет ни объекта диалогового
блока, ни доступного объекта управляющего элемента, вы можете
послать сообщение управляющему элементу в диалоговом окне с по-
мощью функции API Windows SendDlgItemMessage, которая воспринима-
ет в качестве параметров описатель диалогового блока, идентифика-
тор управляющего элемента, идентификатор сообщения и два парамет-
ра сообщения.



B.Pascal 7 & Objects/OW - 282 -

Диапазоны сообщений
-----------------------------------------------------------------

Сообщение определяется полем message записи сообщения
(16-битовое значение). Windows резервирует для своих собственных
стандартных сообщений 0..$03FF, а остальные сообщения до $7FFF
резервируются для сообщений, определенных пользователем. Диапа-
зоны остальных сообщений в ObjectWindows подразделяются на диа-
пазоны команд и уведомлений (как показано в следующей таблице):

Диапазоны сообщений Таблица 16.1
--------------------------------------T----------------¬
¦ Диапазон ¦ Значения ¦
+-------------------------------------+----------------+
¦ Сообщения, зарезервированные ¦ $0000-$7FFF ¦
¦ для Windows. ¦ ¦
+-------------------------------------+----------------+
¦ Сообщения, определяемые ¦ $0400-$8FFF ¦
¦ пользователем. ¦ ¦
+-------------------------------------+----------------+
¦ Уведомляющие сообщения ¦ $8000-$8FFF ¦
¦ управляющих элементов. ¦ ¦
+-------------------------------------+----------------+
¦ Зарезервированные в Windows ¦ $8F00-$8FFF ¦
¦ уведомляющие сообщения ¦ ¦
¦ управляющих элементов. ¦ ¦
+-------------------------------------+----------------+
¦ Уведомляющие сообщения ¦ $9000-$9FFF ¦
¦ порождающего объекта. ¦ ¦
+-------------------------------------+----------------+
¦ Зарезервированные в Windows ¦ $9F00-$9FFF ¦
¦ уведомляющие сообщения ¦ ¦
¦ порождающего объекта. ¦ ¦
+-------------------------------------+----------------+
¦ Командные сообщения. ¦ $A000-$FFFF ¦
+-------------------------------------+----------------+
¦ Команды, зарезервированные ¦ $FF00-$FFFF ¦
¦ в ObjectWindows. ¦ ¦
L-------------------------------------+-----------------


B.Pascal 7 & Objects/OW - 283 -


-------------------------¬
cm_Internal ($FF00) +------------------------+
¦ ¦
¦ ¦
¦ Команды ¦
¦ ¦
¦ ¦
cm_First ($A000) +------------------------+
nf_Internal ($9F00) +------------------------+
¦ ¦
¦ Уведомления ¦
¦ управляющих элементов ¦
¦ ¦
nf_First ($9000) +------------------------+
id_Internal ($8F00) +------------------------+
¦ ¦
¦ Уведомления ¦
¦ порождающих объектов ¦
¦ ¦
id_First ($8000) +------------------------+ ¬
¦ ¦ ¦
¦ ¦ ¦
¦ Сообщения, ¦ ¦
¦ определенные ¦ + wm_Count
¦ пользователем ¦ ¦ ($8000)
¦ ¦ ¦
¦ ¦ ¦
wm_User ($A000) +------------------------+ -
¦ Сообщения Windows ¦
wm_First($0000) L-------------------------

Рис. 16.1 Диапазоны сообщений и команд.



B.Pascal 7 & Objects/OW - 284 -

------------------------------------------------------------------
Глава 17. Интерфейс с графическими устройствами
-----------------------------------------------------------------

Многим типам приложений Windows для организации полного ин-
терфейса пользователя нужны только окна, блоки диалога и управля-
ющие элементы. Но некоторым приложениям (например, программами
рисования и манипулирования изображениями) требуется наличие гра-
фических средств для заполнения окон. Эта графика может быть в
форме линий, форм, текста и побитовых образов.

Для предоставления приложениям графических функциональных
возможностей Windows имеет набор функций, называемый интерфейсом
с графическим устройством - GDI. GDI можно представить себе как
графическую машину, которую используют приложения Windows для
отображения и манипулирования графикой. Функции GDI предоставляют
вашему приложению возможности рисования, которые не зависят от
используемого дисплея. Например, вы можете использовать одни и те
же функции для организации вывода на дисплей EGA, на дисплей VGA
и даже на принтер PostScript.

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

Запись на устройство вывода
-----------------------------------------------------------------

В отличие от традиционных графических программ DOS программы
Windows никогда не выводят элементы изображения непосредственно
на экран или на принтер, а записывают их в логическую сущность,
называемую контекстом дисплея. Контекст дисплея - это виртуальная
поверхность с присущими ей атрибутами, такими как перо, кисть,
шрифт, цвет фона, цвет текста и текущая позиция. Для вашего при-
ложения, независимо от того, какое это на самом деле устройство,
все контексты устройства выглядят аналогично.

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

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

B.Pascal 7 & Objects/OW - 285 -

Windows элемент, похожий на элемент окна с тем исключением, что
контекст дисплея не имеет соответствующего элемента
ObjectWindows.

Нужно помнить о том, что контекст устройства представляет
собой только часть устройства, на котором вы реально рисуете. Хо-
тя вы можете рассматривать вывод в терминах всего окна (рамки,
меню, области клиента) или печатаемой страницы, контекст устройс-
тва охватывает только ту часть, где вы рисуете - область клиента
окна или печатаемую часть страницы.

Контекст устройства - это элемент, управляемый Windows (ана-
логично оконному элементу, только контекст устройства не имеет
соответствующего объекта ObjectWindows).

Чем отличаются контексты устройства?
-----------------------------------------------------------------

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

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

Управление контекстом дисплея
-----------------------------------------------------------------

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



B.Pascal 7 & Objects/OW - 286 -

Работа с контекстом дисплея
-----------------------------------------------------------------

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

type
TMyWindows = object(TWindow)
TheDC: HDC;
.
.
.
end;

Чтобы получить для окна контекст дисплея, вызовите функцию
Windows GetDC:

TheDC := GetDC(HWindow);

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

LineTo(TheDC, Msg.LParamLo, Msg.LParamHi);

Как только вы закончите работу с контекстом дисплея, освобо-
дите его с помощью вызова функции ReleaseDC:

ReleaseDC(HWindow, TheDC);

Не вызывайте GetDC в строке дважды, не включив между вызова-
ми вызов ReleaseDC. В итоге это приведет к сбою системы при рабо-
те программы, так как она исчерпает все доступные контексты дисп-
лея.

Что содержится в контексте устройства?
-----------------------------------------------------------------

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

Перо, например, это просто удобный способ интерпретации ха-
рактеристик линий на устройстве. Графическая линия между двумя
точками имеет три характеристики: ширину, цвет и стиль (например,
пунктирная линия и линия из точек), которые совместно можно расс-
матривать как "перо". Эти логические группы изобразительных ха-
рактеристик значительно упрощают графику в Windows.

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

B.Pascal 7 & Objects/OW - 287 -

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

Побитовая графика
-----------------------------------------------------------------

Действительная поверхность контекста дисплея называется по-
битовым отображением (битовым массивом). Побитовые отображения
представляют конфигурацию памяти конкретного устройства. Следова-
тельно, они зависят от вида адресуемого устройства. Это создает
проблему, поскольку охраненные для одного устройства побитовые
отображения будут несовместимы с другим устройством. GDI имеет
ряд средств для разрешения этой проблемы, включая аппаратно-неза-
висимые побитовые отображения. Имеются следующие функции GDI, ко-
торые создают побитовые отображения: CreateCompatibleDC,
CreateCompatibleBitmap и CreateDIBitmap. Имеются следующие функ-
ции GDI по манипулированию побитовыми отображениями: BitBlt,
StretchBlt, StretchDIBits и SetDIBitsToDevice.

Изобразительные средства
-----------------------------------------------------------------

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

Перья

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

Кисти

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

Шрифты

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

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

B.Pascal 7 & Objects/OW - 288 -

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



B.Pascal 7 & Objects/OW - 289 -

Цвет
-----------------------------------------------------------------

Цвет, который устройство использует для рисования, хранится
в цветовой палитре. Если вы желаете добавить цвет, которого нет в
цветовой палитре, то его можно добавить. Более часто вы будете
настраивать драйвер устройства на аппроксимацию нужного цвета пу-
тем смешивания цветов палитры. Работа с цветовой палитрой более
подробно рассматривается в разделе данной главы "Использование
цветовой палитры".

Режимы отображения
-----------------------------------------------------------------

Очень трудно выбрать устройство рисования, когда заранее не-
известно, какое устройство будет использоваться для отображения.
Большинство приложений игнорируют эту проблему и предполагают,
что вполне удовлетворительно будет работать единица рисования по
умолчанию (один элемент изображения). Однако, некоторые приложе-
ния требуют, чтобы отображение точно воспроизводило размеры нуж-
ного образа. Для таких приложений GDI допускает различные режимы
отображения, некоторые из которых не зависят от аппаратуры. Каж-
дый из методов распределения имеет свою единицу размерности и
систему координатной ориентации. Режим распределения по умолчанию
устанавливает начало координат в левом верхнем углу контекста
дисплея с положительным направлением оси X вправо и положительным
направлением оси Y вниз. Каждый контекст дисплея имеет атрибуты
распределения для интерпретации задаваемых вами координат.

Иногда нужно транслировать логические координаты, используе-
мые вами для рисования, в физические координаты побитового отоб-
ражения. Для большинства приложений начало координат для экрана -
это его левый верхний угол, но для окна началом координат будет
левый верхний угол области клиента. Некоторые окна прокручивают
свою поверхность клиента так, что начало координат не будет даже
находиться в области клиента. Некоторые функции GDI работают
только в конкретной системе координат, поэтому преобразование ко-
ординат просто необходимо. В GDI имеется ряд функций для подобно-
го пересчета координат: ScreenToClient, ClientToScreen, DPToLP и
LPToDP.

Обрезание областей
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 290 -


Инструментальные средства рисования
-----------------------------------------------------------------

Контекст дисплея управляет отображением графики на экране.
Для иного способа отображения графики можно изменить инструмен-
тальные средства, с помощью которых создается изображение. Атри-
буты инструментальных средств задают проявление изображений с по-
мощью функций GDI, например, LineTo, Rectange и TextOut. Перья
задают внешний вид линий, кисти задают внешний вид закрашенных
областей и шрифт задает внешний вид изображаемого текста.

Для задания атрибутов инструмента программа Windows выбирает
логический инструмент в контекст дисплея. Логический инструмент
создается вашей программой путем заполнения полей определенной
записи, TLogPen, TLogBrush или TLogFont. Текущий инструмент - это
инструмент, определенный в Windows, представляющий самый общие
варианты атрибута, например, непрерывное черное перо, серая кисть
или системный шрифт.

Основные инструментальные средства
-----------------------------------------------------------------

Основные инструментальные средства создаются функцией GDI
GetStockObject. Например:

var
TheBrush: HBrush
begin
TheBrush:=GetStockObject(LtGray_Brush);
.
.
.
end;

где LtGray_Brush - это целая константа, определенная в модуле
WinTypes в ObjectWindows. Приведем список всех имеющихся констант
основного инструментального средства:

Основные инструменты рисования Таблица 17.1
--------------------T------------------T------------------------¬
¦ Кисти ¦ Перья ¦ Шрифты ¦
+-------------------+------------------+------------------------+
¦ White_Brush ¦ White_Pen ¦ OEM_Fixed_Font ¦
¦ LtGray_Brush ¦ Black_Pen ¦ ANSI_Fixed_Font ¦
¦ Gray_Brush ¦ Null_Pen ¦ ANSI_Var_Font ¦
¦ DkGray_Brush ¦ ¦ System_Font ¦
¦ Black_Brush ¦ ¦ Device_Default_Font ¦
¦ Null_Brush ¦ ¦ System_Fixed_Font ¦
¦ Hoolow_Brush ¦ ¦ ¦
L-------------------+------------------+-------------------------

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

B.Pascal 7 & Objects/OW - 291 -

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

Логические инструментальные средства
-----------------------------------------------------------------

Записи логических инструментов, TLogPen, TLogBrush и
TLogFont, содержат поля для хранения каждого атрибута инструмен-
та. Например, TLogPen.lopnColor содержит значение цвета ручки.
Каждый тип записи определяет свой собственный набор атрибутов,
соответствующий типу инструмента.

Логические перья
-----------------------------------------------------------------

Вы можете создавать логические перья с помощью функций
Windows CreatePen или CreatePenInderect. Например:

ThePen := CreatePen(ps_Dot, 3, RGB(0, 0, 210));
ThePen := CreatePenInderect(@ALogPen);

Определение записи TLogPen имеет следующий вид:

TLogPen = record
lopnStyle: Word;
lopnWidth: TPoint;
lopnColor: Longint;
end;

Поле стиля, lopnStyle, содержит константу, задающую стиль
линии.


B.Pascal 7 & Objects/OW - 292 -


-----------------------------------------------------------------
Константа Результат
-----------------------------------------------------------------
PS_SOLID -------------------------------------
PS_DASH -------------------------------------
PS_DOT .....................................
PS_DASHDOT .-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
PS_DASHDOTDOT -..-..-..-..-..-..-..-..-..-..-..-..-
PS_NULL
-----------------------------------------------------------------

Рис.17.1 Стили линий для пера.

Поле толщины, lopnWidth, содержит точку, координата x кото-
рой задает толщину линии в координатах устройства. На экране VGA,
если задано значение 0, то будет рисоваться линия толщиной в один
элемент изображения. Значение координаты y игнорируется. Поле
цвета, lopnColor, содержит значение Longint, байты которого зада-
ют величины интенсивности основных цветов (красного, зеленого и
синего), смешение которых и дает нужный цвет. Значение lopnColor
должно иметь вид $00bbggrr, где bb - значение синего цвета, gg -
значение зеленого цвета, а rr - значение красного цвета. Доступ-
ный диапазон интенсивности для каждого первичного цвета от 0 до
255, или от 0 до FF в шестнадцатиричном исчислении. Следующая
таблица показывает некоторые примеры значений цвета:

Примеры значений цвета
Таблица 17.2
---------------T--------------¬
¦ Значение ¦ Цвет ¦
+--------------+--------------+
¦ $00000000 ¦ черный ¦
¦ $00FFFFFF ¦ белый ¦
¦ $000000FF ¦ красный ¦
¦ $0000FF00 ¦ зеленый ¦
¦ $00FF0000 ¦ синий ¦
¦ $00808080 ¦ серый ¦
L--------------+---------------

В качестве альтернативы для воспроизведения цвета можно ис-
пользовать функцию RGB. RGB(0,0,0) возвратит черный цвет,
RGB(255,0,0) возвратит красный и т.д.



B.Pascal 7 & Objects/OW - 293 -

Логические кисти
-----------------------------------------------------------------

Вы можете создавать логические кисти с помощью функций
Windows CreateHatchBrush, CreatePatternBrush,
CreateDIBPatternBrush или CreateBrushInderect. Например:

TheBrush := CreateHatchBrush(hs_Vertical, RGB(0, 255, 0));
TheBrush := CreateBrushInderect(@ALogBrush);

Определение записи TLogBrush имеет следующий вид:

TLogBrush = record
lbStyle: Word;
lbColor: Longint;
lbHatch: Integer;
end;

Поле стиля, lbStyle, содержит константы, задающие стиль кис-
ти:

* bs_DIBPattern указывает, что образец кисти задан аппарат-
но-независимым побитовым отображением.

* bs_Hatched задает один из заранее определенных образцов
штриховки (см. lbHatch).

* bs_Hollow - это пустая кисть.

* bs_Pattern использует левый верхний угол 8 на 8 элементов
побитового отображения, которое находится в этот момент в
памяти.

* bs_Solid - это непрерывная кисть.

Поле lbColor содержит значение цвета, аналогично записи
TLogPen. Это поле игнорируется кистями со стилями bs_Hollow и
bs_Pattern.

Поле lbHatch содержит целую константу, задающую образец
штриховки для кисти со стилем bs_Hatched. Если стиль
bs_DIBPattern, то lbHatch содержит описатель побитового отображе-
ния.


B.Pascal 7 & Objects/OW - 294 -


-----------------------------------------------------------------
Константа Результат
-----------------------------------------------------------------

//////////////////////////////////////
HS_BDIAGONAL //////////////////////////////////////
//////////////////////////////////////

++++++++++++++++++++++++++++++++++++++
HS_CROSS ++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
HS_DIAGCROSS xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
HS_FDIAGONAL \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

--------------------------------------
HS_HORIZONTAL --------------------------------------
--------------------------------------

¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
HS_VERTICAL ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦

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

Рис. 17.2 Стили штриховки для кисти.

Логические шрифты
-----------------------------------------------------------------

Вы можете создавать логические шрифты с помощью функций
Windows CreateFont или CreateFontInderect.

Определение записи TLogBrush следующее:

TLogFont = record
lfHight: Integer;
lfWidht: Integer;
lfEscapement: Integer;
lfOrientation: Integer;
lfWeight: Integer;
lfItalic: Byte;
lfUnderline: Byte;
lfStrikeOut: Byte;
lfCharSet: Byte;
lfOutPrecision: Byte;
lfClipPrecision: Byte;

B.Pascal 7 & Objects/OW - 295 -

lfQuality: Byte;
lfPitchAndFamily: Byte;
lfFaceName: array[0..lf_FaceSize - 1] of Byte;
end;

При использовании TLogFont для создания шрифта вы задаете
атрибуты нужного вам шрифта. Однако, ваша программа не использует
эту информацию для генерации шрифта на экране. Вместо этого она
отображает запрос экранного шрифта в текущий экранный шрифт се-
анса Windows.

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

Поле lfWidht задает нужную ширину букв в единицах устройс-
тва. Если задан ноль, то коэффициент относительного удлинения
сохраняется.

Для поворачиваемого текста lfEscapement задает значение в
десятых долях градуса, на которое поворачивается текст против ча-
совой стрелки. lfOrientation делает аналогичный поворот каждого
символа.

Параметр lfWeight задает нужный вес символов. В качестве
значений можно использовать константы fw_Light, fw_Normal,
fw_Bold и fw_DontCare.

Для трех атрибутов шрифта - lfItalic, lfUnderline и
lfStrikeOut - нужно задать ненулевые значения.

В поле lfCharSet требуется задать конкретный набор символов,
ANSI_CharSet, OEM_CharSet или Symbol_CharSet. Набор символов ANSI
содержится в "Руководстве пользователя по Microsoft Windows", в
Приложении B. OEM_CharSet является системно-зависимым.

Поле lfOutPrecision задает, как точно создаваемый Windows
шрифт должен соответствовать запросам на размеры и позиционирова-
ние. Значение поля по умолчанию - Out_Default_Precis. Поле
lfClipPrecision задает способ рассмотрения частично видимых сим-
волов. Значение поля по умолчанию Clip_Default_Precis.

Поле lfQuality показывает как точно предоставляемый Windows
шрифт соответствует запрошенным атрибутам шрифта. Может быть ус-
тановлено значение Default_Quality, Draft_Quality или
Proof_Quality. Для значения Proof_Quality жирные, подчеркнутые,
наклонные шрифты и шрифты с надпечаткой синтезируются, даже если
их нет. Поле lfPitchAndFamily задает шаг и семейство шрифта. Оно
может быть результатом логической операции or между константой
шага и константой семейства.

Константы шага и семейства шрифта Таблица 17.3

B.Pascal 7 & Objects/OW - 296 -

----------------------T----------------------------¬
¦ Константы шага ¦ Константы семейства ¦
+---------------------+----------------------------+
¦ Default_Pitch ¦ ff_Modern ¦
¦ Fixed_Pitch ¦ ff_Roman ¦
¦ Variable_Pitch ¦ ff_Script ¦
¦ ¦ ff_Swiss ¦
¦ ¦ ff_Decorative ¦
¦ ¦ ff_DontCare ¦
L---------------------+-----------------------------

И, наконец, lfFaceName - это строка, которая задает запро-
шенный вид букв. Если задано значение 0, то вид букв будет стро-
иться на основании значений других полей TLogFont. Приведем нес-
колько примеров исходного кода, определяющего записи TLogFont:

procedure MyWindow.MakeFont;
var
MyLogFont: TLogFont;
begin
with MyLogFont do
begin
lfHight := 30;
lfWidht := 0;
lfEscapement := 0;
lfOrientation := 0;
lfWeight := fw_Bold;
lfItalic := 0;
lfUnderline := 0;
lfStrikeOut := 0;
lfCharSet := ANSI_CharSet;
lfOutPrecision := Out_Default_Precis;
lfClipPrecision := Clip_Default_Precis;
lfQuality := Default_Quality;
lfPitchAndFamily := Variable_Pitch or ff_Swiss;
StrCopy(@FaceName, 'Helv');
end;
TheFont := CreateFontInderect(@MyLogFont);
end;

procedure MyWindow.MakeFont;
var
MyLogFont: TLogFont;
begin
with MyLogFont do
begin
lfHight := 10;
lfWidht := 0;
lfEscapement := 0;
lfOrientation := 0;
lfWeight := fw_Normal;
lfItalic := Ord(True);
lfUnderline := Ord(True);

B.Pascal 7 & Objects/OW - 297 -

lfStrikeOut := 0;
lfCharSet := ANSI_CharSet;
lfOutPrecision := Out_Default_Precis;
lfClipPrecision := Clip_Default_Precis;
lfQuality := Default_Quality;
lfPitchAndFamily := Fixed_Pitch or ff_DontCare;
StrCopy(@FaceName, 'Courier');
end;
TheFont := CreateFontInderect(@MyLogFont);
end;

procedure MyWindow.MakeFont;
var
MyLogFont: TLogFont;
begin
with MyLogFont do
begin
lfHight:=30;
lfWidht:=0;
lfEscapement:=0;
lfOrientation:=0;
lfWeight:=fw_Normal;
lfItalic:=0;
lfUnderline:=0;
lfStrikeOut:=0;
lfCharSet:=Symbol_CharSet;
lfOutPrecision:=Out_Default_Precis;
lfClipPrecision:=Clip_Default_Precis;
lfQuality:=Proof_Quality;
lfPitchAndFamily:=Fixed_Pitch or ff_Roman;
StrCopy(@FaceName, 'Rmn');
end;
TheFont:=CreateFontInderect(@MyLogFont);
end;



B.Pascal 7 & Objects/OW - 298 -

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

Контекст дисплея позволяет вам рисовать в окне и, кроме это-
го, он содержит инструментальные средства рисования: перья, кис-
ти, шрифты и палитры, которые вы используете для рисования текста
и изображений. При рисовании линии в контексте дисплея линия вы-
водится со следующими атрибутами текущего пера: цвет, стиль (неп-
рерывная, пунктирная и т.п.) и толщина. При закрашивании области
она выводится со следующими атрибутами текущей кисти: образец и
цвет. При рисовании текста в контексте дисплея он выведется с ат-
рибутами текущего шрифта: шрифт (Modern, Roman, Swiss и т.п.),
размер, стиль (наклонный, жирный и т.п.). Палитра содержит набор
текущих доступных цветов.

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

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

var
NewPen, OldPen: HPen;
TheDC: HDC;
begin
{ задать ширину пера 10 }
NewPen := CreatePen(ps_Solid, 10, RGB(0, 0, 0));
TheDC := GetDC(AWindow^.HWindow);
OldPen := SelectObject(TheDC, NewPen);
{ выполнить черчение }
SelectObject(TheDC, OldPen);
ReleaseDC(AWindow^.HWindow, TheDC);
DeleteObject(NewPen);
end;

Как показано в данном примере, новый инструмент рисования
должен быть создан, а затем удален. Подобно контексту дисплея,
элементы хранятся в памяти Windows. Если их не удалить, это при-
водит к потерям памяти и возможности возникновения сбоя. Как и
для контекста дисплея, вы должны хранить описатели инструменталь-
ных средств рисования в переменных типа HPen, HBrush, HFont и
HPalette.

Функция Windows DeleteObject удаляет инструментальные средс-
тва рисования из памяти Windows. Ни в коем случае не удаляйте

B.Pascal 7 & Objects/OW - 299 -

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

Контекст дисплея может хранить только по одному инструменту
рисования каждого типа в данный момент времени, поэтому нужно
отслеживать доступные инструментальные средства отображения.
Очень важно удалить их все до завершения работы вашего приложе-
ния. Один из методов, (использован в примере Главы 2) состоит в
определении поля объекта окна с именем ThePen для хранения описа-
теля текущего пера. Когда пользователь выбирает новый стиль пера,
создается новое перо, а старое удаляется. Следовательно, оконча-
тельное перо будет удалено методом основного окна CanClose. Вам
не нужно удалять набор инструментальных средств по умолчанию,
поставляемый во вновь полученном контексте дисплея.

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

Для установки основного инструментального средства в объекте
контекста дисплея используются методы SetStockPen, SetStockBrush,
SetStockFont и SetStockPalette. Например:

ThePen:=GetStockObject(Black_Pen);

Не удаляйте основные инструменты из памяти Windows, посколь-
ку вы будете настраивать их. Иногда возникает ситуация, когда нет
основного инструмента, который имел бы нужный вам атрибут. Напри-
мер, все основные перья воспроизводят тонкие линии, а вам требу-
ется толстая. В этом случае имеется два способа создания настро-
енных инструментальных средств рисования. Один способ состоит в
вызове функций Windows CreatePen, CreateFont, CreateSolidBrush
или CreateDIBPatternBrush. Эти функции используют параметры, ко-
торые описывают нужный инструмент, и возвращают описатель инстру-
ментального средства, который используется в вызовах
SelectObject.

Другой способ создания настроенных инструментальных средств
состоит в построении описания атрибутов логического инструмента.
Логический инструмент реализуется структурами данных Windows
TLogPen, TLogBrush, TLogFont и TLogPalette. Например, TLogPen
имеет поля для хранения толщины цвета и стиля. После создания
записи данных логического инструмента, она передается в качестве
параметра в CreatePenInderect, CreateBrushInderect,
CreateFontInderect или CreatePalette. Эти функции возвращают опи-
сатели инструментального средства которые могут быть использованы
в вызовах SelectObject. В данном примере устанавливается синее
перо для изображения в контексте дисплея окна:

procedure SampleWindow.ChangePenToBlue;
var

B.Pascal 7 & Objects/OW - 300 -

ALogPen: TLogPen;
ThePen: HPen;
begin
ALogPen.lopnColor:=RGB(0, 0, 255);
ALogPen.lopnStyle:=ps_Solid;
ALogPen.lopnWidth.X:=0;
ALogPen.lopnWidth.Y:=0;
ThePen:=CreatePenInderect(@ALogPen);
SelectObject(TheDC, ThePen);
end;

Отображение графики в окнах
-----------------------------------------------------------------

Рисование - это процесс отображения контекста окна. Приложе-
ние Windows отвечает за рисование его окон при их первом появле-
нии и их изменении, например, после восстановления из пиктограммы
или перекрытия другими окнами. Windows не обеспечивает автомати-
ческого рисования контекста окон, она только информирует окно,
когда ему нужно нарисовать себя. Данный раздел показывает, как
рисовать в окне, объясняет механизм рисования и объясняет исполь-
зование контекста дисплея.

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

Изображение окон
-----------------------------------------------------------------

Когда возникает необходимость нарисовать окно, оно становит-
ся запрещенным. Это значит что изображение дисплея не соответс-
твует действительности и должно быть изменено. Это происходит в
момент первоначального отображения окна, восстановления из пик-
тограммы или удаления другого окна, которое перекрывало часть
данного окна. Во всех этих случаях Windows посылает сообщение
wm_Paint соответствующему приложению. Это сообщение автоматически
вызывает метод Paint вашего окна. Один из параметров Paint,
PaintDC, представляет собой контекст дисплея, который использует-
ся для рисования.

Метод TWindow Paint ничего не рисует, поскольку объекты
TWindow не имеют графики для рисования. В типе вашего окна опре-
делим метод Paint, который будет вызывать методы и функции, изоб-
ражающие в окне текст и графику.

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

B.Pascal 7 & Objects/OW - 301 -

инструменты в контексте дисплея рисования вашего метода Paint.

После завершения работы метода Paint контекст дисплея рисо-
вания автоматически освобождается.

Стратегия графики
-----------------------------------------------------------------

Метод Paint отвечает за рисование текущего содержимого окна
в любой момент времени, включая первое появление этого окна. Сле-
довательно, метод Paint должен уметь рисовать все "постоянные"
изображения окна. Кроме того, он должен уметь восстанавливать лю-
бые изображения, добавленные в окно после его первого появления.
Для воспроизведения этой "динамической" графики метод Paint дол-
жен иметь доступ к инструкциям или данным, с помощью которых было
создано изображение.

Вы можете выбрать один из двух возможных вариантов. Первый
подход состоит в выделении нескольких графических методов и при
динамическом рисовании вызывать их из метода Paint. Другой под-
ход, показанный в примере Главы 3, состоит в хранении данных, от-
носящихся к графическому контексту окна, в полях объекта этого
окна. Эти данные могут включать, например, координаты, формулы и
побитовые распределения. Затем метод Paint повторно вызывает гра-
фические функции, которые нужны для преобразования этих данных в
изображения.

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

Рисование в окнах
-----------------------------------------------------------------

Для рисования любого текста или изображения в объекте окна
сначала нужно получить контекст дисплея. После рисования контекст
дисплея нужно освободить. (В одном сеансе Windows доступны только
пять элементов контекста дисплея.) Вы можете использовать описа-
тель контекста дисплея в качестве аргумента любой графической
функции Windows.

Вызов графических функций окна

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

TheDC := GetDC(HWindow);
TextOut(TheDC, 50, 50, 'Sample Text', 11);
ReleaseDC(HWindow, TheDC);


B.Pascal 7 & Objects/OW - 302 -

Графические функции GDI
-----------------------------------------------------------------

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

Функции изображения текста
-----------------------------------------------------------------

Функция рисования текста использует для рисования заданный
текущий шрифт контекста дисплея. Функция TextOut рисует текст в
заданной точке. TextOut выравнивает текст в зависимости от теку-
щих значений флагов форматирования текста. По умолчанию происхо-
дит выравнивание слева. Текущий метод выравнивания можно посмот-
реть с помощью функции GetTextAlign и установить с помощью функ-
ции SetTextAlign.

Функция TextOut - это самая часто используемая функция рисо-
вания текста. Используя установленные по умолчанию флаги формати-
рования текста, данный метод Paint рисует выравненный слева мас-
сив символов, левый верхний угол которого имеет координаты
(10,15).

procedure TMyWindow.Paint(PaintDC: HDC;
var PaintINfo: TPaintStruct);
var
MyTextString: array[0..20] of Char;
begin
StrCopy(MyTextString, 'Hello, World');
TextOut(PaintDC, 10, 15, MyTextString,
StrLen(MyTextString));
end;

---------------------------------
¦
¦ (10, 15)
¦ * Hello Word
¦
¦

Рис. 17.3 Результат выполнения функции TextOut.



B.Pascal 7 & Objects/OW - 303 -

Функции рисования линий
-----------------------------------------------------------------

Функции рисования линии используют для рисования заданное
текущее перо контекста дисплея. Большинство линий рисуется с ис-
пользованием функций MoveTo и LineTo. Эти функции воздействуют на
атрибут контекста дисплея - текущую позицию. Если использовать
аналогию с карандашом и листом бумаги, то текущая позиция это
точка, где карандаш касается бумаги.

Функции MoveTo и LineTo

Функция MoveTo перемещает текущую позицию в заданные коорди-
наты. Функция LineTo рисует линию из текущей позиции к точке с
заданными координатами. Заданные координаты затем становятся те-
кущей позицией. Следующий метод Paint рисует линию от (100,150)
до (10,15).

procedure TMyWindow.Paint(PaintDC: HDC; var PaintINfo:
TPaintStruct);
begin
MoveTo(PaintDC, 100, 150);
LineTo(PaintDC, 10, 15);
end;

---------------------------------
¦
¦ (10, 15)
¦ *
¦ \
¦ \
¦ \
¦ \
¦ * (100, 150)

Рис. 17.4. Результат выполнения функции LineTo.

Функция PolyLine

Функция Polyline рисует последовательность линий, соединяю-
щих заданные точки. По действию она аналогична выполнению после-
довательности функций MoveTo и LineTo, однако, Polyline выполняет
эту операцию намного быстрее и никак не воздействует на текущую
позицию пера. Следующий метод Paint рисует прямой угол.

procedure TMyWindow.Paint(PaintDC: HDC; var PaintInfo:
TPaintStruct);
var
Points: array[0..2] of TPoint;
begin
Points[0].X:=10;
Points[0].Y:=15;
Points[1].X:=10;

B.Pascal 7 & Objects/OW - 304 -

Points[1].Y:=150;
Points[2].X:=100;
Points[2].Y:=150;
Polyline(PaintDC, @Points, 3);
end;

---------------------------------
¦
¦ (10, 15)
¦ *
¦ ¦
¦ ¦
¦ ¦
¦ ¦
¦ +-----* (100, 150)


Рис. 17.5. Результат выполнения функции Polyline.

Функция Arc

Функция Arc рисует дуги по периметру эллипса, ограниченного
заданным прямоугольником. Дуга начинается в точке пересечения эл-
липса и линии из центра эллипса в заданную точку начала. Дуга ри-
суется против часовой стрелки до тех пор, пока она не достигнет
точки пересечения эллипса с линией из центра эллипса к заданной
точке конца.

Следующий метод Paint рисует верхнюю четверть окружности с
началом в (40,25) и окончанием в (10,25), используя ограничиваю-
щий прямоугольник (10,10), (40,40), начальную точку (0,0) и ко-
нечную точку (50,0). Действие производится даже в том случае, ес-
ли заданная начальная и конечная точка не лежат на дуге.

procedure TMyWindow.Paint(PaintDC: HDC;
var PaintInfo: TPaintStruct);
begin
Arc(PaintDC, 10, 10, 40, 40, 50, 0, 0, 0);
end;



B.Pascal 7 & Objects/OW - 305 -

Изображение фигур
-----------------------------------------------------------------

Функции изображения фигур используют текущее перо заданного
контекста дисплея для изображения периметра и текущую кисть для
закраски внутренней области. На текущую позицию они не влияют.

Функция Rectangle

Функция Rectangle рисует прямоугольник от его левого верхне-
го угла к правому нижнему. Например, следующий оператор метода
Paint рисует прямоугольник от (10,15) до (100,150).

Rectangle(PaintDC, 10, 15, 100, 150);

---------------------------------
¦
¦ (10, 15)
¦ *-----*
¦ ¦-----¦
¦ ¦-----¦
¦ ¦-----¦
¦ ¦-----¦
¦ *-----* (100, 150)


Рис. 17.6. Результат выполнения функции Rectangle.

Функция RoundRect

Функция RoundRect рисует прямоугольник со скругленными угла-
ми. Скругления углов определены как четверти эллипса. Например,
следующий оператор метода Paint рисует прямоугольник от (10,15)
до (100,150), углы которого будут скруглены четвертями эллипса
шириной 9 и высотой 11.

RoundRect(PaintDC, 10, 15, 100, 150, 9, 11);

Функция Ellipse

Функция Ellipse рисует эллипс, задаваемый ограничивающим его
прямоугольником. Следующий пример рисует эллипс в прямоугольнике
от (10,15) до (110,70).

Ellipse(PaintDC, 10, 50, 100, 150);

Функции Pie и Chord

Функции Pie и Chord рисуют секторы эллипса. Они рисуют дугу,
подобно функции Arc. Однако, результатом Pie и Chord будут облас-
ти. Функция Pie соединяет центр эллипса с его граничными точками.
Следующая функция Pie рисует верхнюю четверть круга, заключенного
в прямоугольник от (10,10) до (40,40).

B.Pascal 7 & Objects/OW - 306 -


Pie(PaintDC, 10, 10, 40, 40, 50, 0, 0, 0);

Функция Chord соединяет две граничные точки дуги.

Chord(PaintDC, 10, 10, 40, 40, 50, 0, 0, 0);

Функция Polygon

Функция Polygon рисует непрерывную последовательность сег-
ментов линий, аналогично функции Polyline, но в конце работы за-
мыкает область, рисуя линию от последней заданной точки к первой
заданной точке. И, наконец, он заполняет полученный многоугольник
текущей кистью, используя установленный режим закрашивания много-
угольника. Следующий метод Paint рисует и закрашивает прямоуголь-
ный треугольник.

procedure TMyWindow.Paint(PaintDC: HDC;
var PaintInfo: TPaintStruct);
var
Points: array[0..2] of TPoint;
begin
Points[0].X:=10;
Points[0].Y:=15;
Points[1].X:=10;
Points[1].Y:=150;
Points[2].X:=100;
Points[2].Y:=150;
Polygon(PaintDC, @Points, 3);
end;

---------------------------------
¦
¦ (10, 15)
¦ *
¦ ¦\
¦ ¦-\
¦ ¦--\
¦ ¦---\
¦ *-----* (100, 150)
(10, 150)

Рис. 17.7. Результат выполнения функции Polygon.



B.Pascal 7 & Objects/OW - 307 -

Использование палитр
-----------------------------------------------------------------

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

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

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

Установка палитры
-----------------------------------------------------------------

Логические палитры являются инструментами рисования, такими
же как перья и кисти, описанные в разделе "Инструментальные
средства изображения". Для создания логической палитры использу-
ется функция CreatePalette, которая берет указатель на запись
данных LogPalette, создает новую палитру и возвращает ее описа-
тель, который передается в SelectPalette для выбора палитры в
контекст дисплея. Запись TLogPalette содержит поля номера версии
Windows (в настоящее время $0300), число элементов палитры и мас-
сив элементов палитры. Каждый элемент палитры - это запись типа
TPaletteEntry. Тип TPaletteEntry имеет три байтовых поля для спе-
цификации цвета (peRed, peGreen и peBlue) и одно поле для флагов
(peFlags).

GetStockObject(Default_Palette) создает палитру по умолча-
нию, состоящую из 20 цветов, которые всегда присутствуют в палит-
ре системы.

B.Pascal 7 & Objects/OW - 308 -


После выбора палитры в контекст дисплея с помощью
SelectPalette, он должен до использования "реализовать" ее. Это
делается с помощью функции Windows RealizePalette:

ThePalette := CreatePalette(@ALogPalette);
SelectPalette(TheDC, ThePalette, 0);
RealizePalette(TheDC);

RealizePalette помещает цвета из вашей логической палитры в
системную палитру устройства. Сначала Windows проверяет соответс-
твие цветов с уже имеющимися в системной палитре, а затем добав-
ляет ваши новые цвета в палитру системы, если для этого есть мес-
то. Цветам, которым не нашлись идентичные цвета в системной па-
литре, подбирается наиболее соответствующий цвет из палитры сис-
темы. Ваше приложение должно реализовать свою палитру до рисова-
ния, как это делается для других инструментальных средств рисова-
ния.

Рисование с палитрами
-----------------------------------------------------------------

После реализации палитры вашего приложения, оно может осу-
ществлять рисование с использованием его цветов. Цвета палитры
можно задавать прямо или косвенно. Для прямого задания цвета ис-
пользуется индекс палитры, TColorRef. Индекс палитры TColorRef
есть значение типа Longint, где старший байт установлен в 1, а
индекс элемента логической палитры содержится в двух младших бай-
тах. Например, $01000009 задает девятый элемент логической палит-
ры. Это значение можно использовать везде, где ожидается аргумент
TColorRef. Например:

ALogPen.lopnColor := $01000009;

Если ваше дисплейное устройство допускает использование пол-
ного 24-битового цвета без системной палитры, то использование
индекса палитры неоправданно ограничивает вас цветами вашей логи-
ческой палитры. Чтобы избежать этого ограничения, вы можете за-
дать цвет палитры косвенно, используя относительное значение па-
литры TColorRef. Относительное значение TColorRef почти совпадает
с абсолютным значением RGB TColorRef, но байт старшего разряда
установлен в 2. Три младших байта содержат значение цвета RGB.
Например, $020000FF задают значение чистого красного цвета. Если
устройство поддерживает системную палитру, то Windows подберет
максимально соответствующий цвет RGB логической палитры. Если
устройство не поддерживает системную палитру, то TColorRed ис-
пользуется так, как если бы он задавал явное значение RGB.

Запрос палитры
-----------------------------------------------------------------

Windows определяет функцию, которая позволяет вам получать
информацию относительно палитры. GetPaletteEntries воспринимает

B.Pascal 7 & Objects/OW - 309 -

индекс, диапазон и указатель на TPaletteEntry и заполняет буфер
заданными элементами палитры.

Модификация палитры
-----------------------------------------------------------------

Есть два способа изменения элементов логической палитры.
Функция SetPaletteEntries берет те же самые аргументы, что и
GetPaletteEntries и меняет заданные элементы на те, на которые
указывает третий аргумент. Обратите внимание на то, что произве-
денные изменения не отражаются в системной палитре до вызова
RealizePalette, и их не видно до перерисовки области клиента.
Функция AnimatePalette воспринимает те же аргументы, что и
SetPaletteEntries, но используется для быстрых изменений палитры
приложения, и они немедленно становятся видимыми. При вызове
AnimatePalette элементы палитры с полем peFlags установленным в
константу pc_Reserved будут заменены на соответствующие новые
элементы, и это найдет немедленное отражение в системной палитре.
На другие элементы это никак не повлияет.

Например, вам нужно взять первые десять элементов палитры,
сменить их значение, добавив на единицу содержание красного цвета
и уменьшив содержимое синего и зеленого. Все эти изменения должны
сразу же стать видимыми (Предполагается, что некоторые из элемен-
тов имеют установленное значение pc_Reserved):

GetObject(ThePalette, SizeOf(NumEntries), @NumEntries);
if NumEntries >= 10 then
begin
GetPaletteEntries(ThePalette, 0, 10, @PaletteEntries);
for i:=0 to 9 do
begin
PaletteEntries[i].peRed:=PaletteEntries[i].peRed+40;
PaletteEntries[i].peGreen:=PaletteEntries[i].peGreen-40;
PaletteEntries[i].peBlue:=PaletteEntries[i].peBlue-40;
end;
AnimatePalette(ThePalette, 0, 10, @PaletteEntries);
end;

Вместо AnimatePalette мы могли бы использовать:

SetPaletteEntries(ThePalette, 0, 10, @PaletteEntries);
RealizePalette(ThePalette);

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

Реакция на изменения палитры
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 310 -

го не делать (очень быстрый способ, но может привести к некор-
ректным цветам), оно может реализовать свою логическую палитру и
перерисовать себя (медленнее, но цвета будут максимально коррект-
ными), либо оно может реализовать свою логическую палитру и затем
использовать функцию UpdateColors для быстрого изменения области
клиента в соответствии с системной палитрой. UpdateColors в общем
случае работает быстрее, чем перерисовка области клиента, но при
ее использовании могут быть некоторая потеря точности в цветопе-
редаче. Поле WParam записи TMessage, переданной в сообщении
wm_PaletteChanged, содержит описатель окна, которое реализовало
свою палитру. Если в ответ вы решили реализовать свою собственную
палитру, сначала убедитесь в том, что этот описатель не является
описателем вашего окна, чтобы не создать бесконечного цикла.

Программа PaTest создает и реализует логическую палитру из
восьми цветов. При нажатии левой кнопки "мыши" она будет рисо-
вать раскрашенные квадраты с образцами каждого из цветов логичес-
кой палитры. При нажатии правой кнопки происходит сдвиг цветов
логической палитры. Используется индекс палитры TColorRef, поэто-
му, когда логическая палитра меняется раскрашенные квадраты также
сменят свой цвет. При использовании индекса палитры TColorRef мо-
жет оказаться удобным использование функции PaletteIndex.

Полный текст программы содержится в файле PALTEST.PAS на ва-
ших дистрибутивных дискетах.



B.Pascal 7 & Objects/OW - 311 -

------------------------------------------------------------------
Глава 18. Более подробно о ресурсах
-----------------------------------------------------------------

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

Меню и курсоры - это два примера ресурсов программы Windows.
Ресурсы это данные, хранимые в выполняемом (.EXE) файле програм-
мы, но они располагаются отдельно от обычного сегмента данных
программы. Ресурсы разрабатываются и специфицируются вне кода
программы, затем добавляются к скомпилированному коду программы
для создания выполняемого файла программы.

Следующие ресурсы вы будете создавать и использовать наибо-
лее часто:

- Меню.
- Блоки диалога.
- Пиктограммы.
- Курсоры.
- Оперативные клавиши.
- Графические изображения.
- Строки символов.

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

Создание ресурсов
-----------------------------------------------------------------

Вы можете создавать ресурсы, используя редактор ресурсов или
компилятор ресурсов. Паскаль поддерживает оба эти метода, поэтому
вы сами можете выбрать, какой их них является более удобным. В
большинстве случаев проще использовать редактор ресурсов и созда-
вать ваши ресурсы визуально. Однако, иногда более удобно исполь-
зовать компилятор ресурсов для компиляции файла описания ресурса,
который может вам встретиться в книге или в журнале. Независимо
от выбранного вами подхода вы обычно создаете файл ресурса (.RES)
для каждого приложения. Этот файл ресурса будет содержать двоич-
ную информацию о всех меню, диалогах, графических образах и дру-
гих ресурсах, используемых вашим приложением.


B.Pascal 7 & Objects/OW - 312 -

Двоичный файл ресурса (.RES) добавляется к вашему исполняе-
мому файлу (.EXE) в процессе компиляции с использованием директи-
вы компилятора $R, как это описано в данной главе. Вы также долж-
ны написать код, который будет загружать ресурсы в память. Это
придаст вам дополнительную гибкость, поскольку ваша программа бу-
дет использовать память лишь для ресурсов, которые используются в
данный момент. Загрузка ресурсов в память также рассматривается в
данной главе.

Добавление ресурсов к выполняемой программе
-----------------------------------------------------------------

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

Есть три способа добавления ресурсов к выполняемому файлу:

- Можно использовать редактор ресурсов для копирования ре-
сурсов из файла .RES в уже скомпилированный файл программы
.EXE. Инструкции по этой операции содержатся в руководстве
пользователя по пакету разработчика ресурсов.

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

program SampleProgram;
{$r SAMPLE.RES}
.
.
.

добавит файл ресурсов SAMPLE.RES к выполняемому файлу.
Каждая программа на языке Паскаль может иметь только один
файл ресурсов (хотя этот файл ресурсов может включать дру-
гие файлы ресурсов). Все эти файлы должны быть файлами
.RES и хранить ресурсы в двоичном формате. Директива ком-
пилятора $R позволяет вам задать отдельный файл .RES.

- Использовать компилятор ресурсов.

Загрузка ресурсов в приложение
-----------------------------------------------------------------

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

Загрузка меню
-----------------------------------------------------------------

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

словами это характеристика окна, которая должна быть задана до
создания соответствующего элемента меню (с помощью метода
Create). Следовательно, меню может быть задано в типе конструкто-
ра Init или вскоре после конструирования. Ресурсы меню загружают-
ся вызовом функции Windows LoadMenu со строкой идентификатора ме-
ню при конструировании нового объекта окна. Например:

constructor SampleMainWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
TWindow.Init(AParent, ATitle);
Attr.Menu:=LoadMenu(HInstance, PChar(100));
.
.
end;

Код PChar(100) переводит целое значение 100 в тип PChar,
совместимый с Windows тип строки. LoadMenu загружает ресурс меню
с идентификатором 100 в новый объект окна. Ресурс может иметь
символьное имя (строку), например, 'SampleMenu', а не числовой
идентификатор. В этом случае предыдущий код будет выглядеть сле-
дующим образом:

constructor SampleMainWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
begin
TWindow.Init(AParent, ATitle);
Attr.Menu:=LoadMenu(HInstance, 'SampleMenu');
.
.
end;

Дополнительная информация по созданию объектов окна содер-
жится в Главе 10, "Объекты окна".

Для обработки выбора варианта меню просто определяется метод
для окна, которое владеет этим меню, используя специальное расши-
рение заголовка определения метода идентификатором cm_First:

procedure HandleMenu101(var Msg: TMessage);
virtual cm_First+101;

Обратите внимание на то, что 101 представляет собой выбран-
ного варианта меню (а не самого ресурса меню). Каждый пункт меню
имеет уникальный целочисленный идентификатор. В этом методе зада-
ча состоит в организации соответствующей реакции на выбор пункта
меню. Обычно вы будете определять символьные константы для команд
вашего меню.

Загрузка оперативных клавиш
-----------------------------------------------------------------

Оперативные клавиши - это активные клавиши или комбинации

B.Pascal 7 & Objects/OW - 314 -

клавиш, которые используются для задания команд приложения. Обыч-
но оперативные клавиши определяются как эквиваленты выбора пунк-
тов меню. Например, клавиша Del - это стандартная оперативная
клавиша, которую можно использовать как альтернативу выбора пунк-
та Delete в меню Edit. Однако, оперативные клавиши могут реализо-
вывать команды, которые не соответствуют элементам меню.

Ресурсы оперативных клавиш хранятся в таблице оперативных
клавиш. Для загрузки таблицы оперативных клавиш используется
функция Windows LoadAccelerators, которая просто возвращает опи-
сатель таблицы. В отличие от ресурса меню, который связан с конк-
ретным окном, ресурс оперативной клавиши принадлежит всему прило-
жению. Каждое приложение может иметь только один такой ресурс.
Объекты приложения резервируют одно поле объекта, HAccTable, для
хранения описателя ресурса оперативных клавиш. Обычно вы будете
загружать ресурс оперативных клавиш в методе объекта приложения
InitInstance:

procedure SampleApplication.InitInstance;
begin
TApplication.InitInstance;
HAccTable := LoadAccelerators(HInstance,
'SampleAccelerators');
end;

Часто вы будете определять оперативные клавиши для быстрого
выбора вариантов меню. Например, Shift+Ins обычно используется
для быстрого выбора команды Paste. Оперативные клавиши генерируют
основанные на команде сообщения, которые идентичны сообщениям,
генерируемым выбором пункта меню. Для привязки метода реакции на
выбор в меню с соответствующей оперативной клавишей нужно убе-
диться в том, что определенное в ресурсе значение оперативной
клавиши идентично идентификатору элемента меню.

Загрузка блоков диалога
-----------------------------------------------------------------

Блоки диалога являются единственным типом ресурса, который
непосредственно соответствует типу объекта ObjectWindows. TDialog
и его производные типы, включая TDlgWindow, определяют объекты
интерфейса, которые используют ресурсы блока диалога. Каждый объ-
ект блока диалога обычно связан с одним ресурсом блока диалога,
который задает его размер, местоположение и ассортимент управляю-
щих элементов (таких, как командные кнопки и блоки списка).

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

Adlg := New(PSampleDialog, Init(@Self, 'AboutBox'));

или
Adlg := New(PSampleDialog, Init(@Self, PChar(120)));

Дополнительная информация по созданию объектов диалога со-
держится в Главе 11, "Объекты диалоговых блоков".

Загрузка курсоров и пиктограмм
-----------------------------------------------------------------
Каждый тип объекта окна имеет специальные атрибуты, называе-
мые атрибутами регистрации. Среди этих атрибутов есть курсор окна
и пиктограмма. Для установки этих атрибутов для типа окна вы
должны определить метод GetWindowClass (как и GetClassName).

Например, вы создаете курсор для выбора элементов в блоке
списка. Курсор имеет вид указательного пальца и хранится в ресур-
се курсора с именем 'Finger'. Кроме того, вы создаете ресурс пик-
тограммы с именем 'SampleIcon', который выглядит как улыбающееся
лицо. Вы должны написать метод GetWindowClass следующим образом:

procedure SampleWindow.GetWindowClass(var AWndClass:
TWndClass);
begin
TWindow.GetWindowClass(AWndClass);
AWndClass.hCursor:=LoadCursor(HInstance, 'Finger');
AWndClass.hIcon:=LoadIcon(HInstance, 'SampleIcon');
end;

Однако, между курсором и пиктограммой имеется одно отличие.
Оно состоит в том, что курсор задается для одного окна, а пиктог-
рамма представляет все приложение. Следовательно, пиктограмма ус-
танавливается в типе объекта только для основного окна. У этого
правила имеется одно исключение: для приложений, которые следуют
правилам многодокументального интерфейса (MDI), каждое дочернее
окно MDI имеет свою собственную пиктограмму.
Для использования одного из уже имеющихся курсоров или пик-
тограмм Windows, передайте 0 в HInstance и используйте значение
idc_ (например, idc_IBeam) для курсора и значение idi_ (например,
idi_Hand) для пиктограммы. Например:

procedure SampleWindow.GetWindowClass(var AWndClass:
TWndClass);
begin
TWindow.GetWindowClass(AWndClass);
AWndClass.hCursor := LoadCursor(HInstance, idc_IBeam);
AWndClass.hIcon := LoadIcon(HInstance, idi_Hand);
end;

Дополнительную информацию по регистрационным атрибутам окна
можно найти в Главе 10, "Объекты окна".

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

B.Pascal 7 & Objects/OW - 316 -

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

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

LoadString(HInstance, StringID, @TextItem,SizeOf(TextItem));

* Параметр StringID - это номер идентификатора строки (нап-
ример, 601) в таблице строк. Это число можно заменить
константой.

* Параметр @TextItem - это указатель на массив символов
(PChar), который принимает строку.

* Параметр SizeOf(TextItem) - это максимальное число симво-
лов, передаваемых в @TextItem. Максимальный размер ресурса
строки 255 символов, поэтому передача буфера из 256 симво-
лов гарантирует полную передачу строки.

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

Вы можете использовать ресурс строки для вывода текста в
блоке сообщения. Например, вы можете вывести сообщение об ошибке.
В данном примере вы определяете строку 'Program unavailable' в
таблице строк и определяете константу ids_NoProgrm в качестве
идентификатора строки. Для использования этого ресурса строки в
блоке сообщения об ошибке, вы можете написать следующую процеду-
ру:

procedure TestDialog.RunErrorBox(ErrorNumber:
Integer); virtual;
var
TextItem: array[0..255] of Char;
begin
LoadString(HInstance, ids_NoPrgrm, @TextItem, 20);
MessageBox(HWindow, @TextItem, 'Error', mb_OK or
mb_IconExclamation);
end;

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

B.Pascal 7 & Objects/OW - 317 -

ошибке. Для загрузки списка строк в блок списка вызывается
LoadString для загрузки каждой строки, затем вызывается AddString
для добавления ее в блок списка.

Другое использование ресурса строк применяется для элементов
меню, которые добавляются в меню вашего исходного кода. В этом
случае сначала получается ресурс строки с помощью LoadString. За-
тем эта строка передается как параметр в вызовы функций Window
CreateMenu и AppendMenu. Например:

procedure SampleWindow.Init(AParent: PWindpwsObject; ATitle:
PChar);
var
TextItem: array[0..255] of Char;
begin
TWindow.Init(AParent, ATitle);
Attr.Menu := LoadMenu(HInstance, PChar(100));
LoadString(HInstance, 301, @TextItem, 20);
AppendMenu(Attr.Menu, mf_String ormf_Enabled, 501,
@TextItem);
end;

Загрузка графических изображений
-----------------------------------------------------------------

Функция Windows LoadBitmap загружает ресурсы графических
изображений (битовых отображений). LoadBitmap загружает побитовое
распределение в память и возвращает его описатель. Например:

HMyBit:=LoadBitmap(HInstance, PChar(501));

загружает ресурс побитового отображения с идентификатором 501 и
записывает его описатель в переменную HMyBit. После загрузки по-
битового отображения оно останется в памяти до его явного удале-
ния вами. В отличие от других ресурсов, оно остается в памяти да-
же после закрытия пользователем вашего приложения.

В Windows имеется ряд заранее определенных графических изоб-
ражений, которые используются как часть графического интерфейса
Windows. Ваше приложение может загружать эти изображения (напри-
мер, obm_DnArrow, obm_Close и obm_Zoom). Как и предопределенные
пиктограммы и курсоры, предопределенные графические изображения
могут быть загружены, если в вызове LoadBitmap вместо HInstance
задать ноль:

HMyBit:=LoadBitmap(0, PChar(obm_Close));

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

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

B.Pascal 7 & Objects/OW - 318 -


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

* Для отображения картинок вместо текста в элементах меню
или элементах блока списка. Например, вы можете вместо
слова 'Arrow' (стрелка) в пункте меню поместить изображе-
ние стрелки.

Дополнительная информация относительно использования графики
с побитовым отображением содержится в Главе 17.

Если побитовое отображение не используется, то его нужно
удалить из памяти. В противном случае занимаемая им память будет
недоступна другим приложениям. Даже если вы не удаляете его после
использования приложением, вы обязательно должны удалить его до
прекращения работы приложения. Графический образ удаляется из па-
мяти с помощью функции Windows DeleteObject:

if DeleteObject(HMyBit) then { успешно };

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



B.Pascal 7 & Objects/OW - 319 -

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

Вы можете использовать графические образы для создания кис-
тей, которые могут закрашивать области экрана. Область может быть
закрашена сплошным цветом или в виде заданного образца. Минималь-
ный размер используемого в кисти графического образа составляет 8
на 8 элементов изображения. Если вы применяете большее графичес-
кое изображение, то в кисти используется только его левый верхний
угол 8 на 8. Предположим, что вы хотите заполнить область полос-
ками, как это показано на Рис. 18.1.

------------------------------------------------------------T-T-¬
¦-=------------------Bitmap drawing test--------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦ File Help ¦
+---------------------------------------------------------------+
¦ ¦
¦ ------------------------------------------------------ ¦
¦ ------------------------------------------------------ ¦
¦ ------------------------------------------------------ ¦
¦ ------------------------------------------------------ ¦
¦ ------------------------------------------------------ ¦
¦ ------------------------------------------------------ ¦
¦ ------------------------------------------------------ ¦
¦ ------------------------------------------------------ ¦
¦ ------------------------------------------------------ ¦
¦ ¦
L----------------------------------------------------------------

Рис. 18.1. Заполнение области экрана полосками.

При заполнении области на Рис. 18.1 Windows циклически копи-
рует кисть. Действительный размер побитового распределения - лишь
8 на 8 элементов изображения, но кистью можно закрасить весь эк-
ран.

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

Рис. 18.2. Ресурс графического изображения для создания кис-
ти по образцу Рис. 18.1.

Следующий код помещает образец графического образа в кисть:

procedure SampleWindow.MakeBrush;
var
MyLogBrush: TLogBrush;
begin
HMyBit := LoadBitmap(HInstance, PChar(502));
MyLogBrush.lbStyle := bs_Pattern;
MyLogBrush.lbHatch := HMyBit;

B.Pascal 7 & Objects/OW - 320 -

TheBrush := CreateBrushInderect(@MyLogBrush);
end;

Для проверки образца, отобразим его в прямоугольнике:

procedure MyWindow.Paint(PaintDC: HDC;
var PaintInfo: TPaintStruct);
begin
SelectObject(PaintDC, TheBrush);
Rectangle(PaintDC, 20, 20, 200, 200);
end;

После использования кисти вы должны удалить и кисть, и гра-
фическое изображение:

DeleteObject(HMyBit);
DeleteObject(TheBrush);

Отображение графических изображений в меню
-----------------------------------------------------------------

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

type
MyLong = record
case Integer of
0: (TheLong: Longint);
1: (Lo: Word;
Hi: Word);
end;

constructor SampleWindow.Init(AParent: PWindowsObject;
ATitle: PChar);
var
ALong: MyLong;
begin
TWindow.Init(AParent, ATitle);
Attr.Menu := LoadMenu(HInstance, PChar(100));
ALong.Lo := LoadBitmap(HInstance, PChar(503));
ModifyMenu(Attr.Menu, 111, mf_ByCommand or mf_Bitmap, 211,
PChar(ALong.TheLong));
.
.
.
end;

В приведенном выше коде 111 - это идентификатор команды ва-
рианта меню, который изменяется, а 211 это его новый идентифика-
тор. Однако, вы можете использовать один и тот же идентификатор в

B.Pascal 7 & Objects/OW - 321 -

обоих случаях.

------------------------------------------------------------T-T-¬
¦-=---------------------Steps-------------------------------¦^¦v¦
+-----------------------------------------------------------+-+-+
¦--File--- Help ¦
+--------------T------------------------------------------------+
¦----New-------¦ ¦
¦ pick ¦ ¦
¦ me ¦ ¦
¦ Save ¦ ¦
¦ Save As ¦ ¦
+--------------- ¦
¦ ¦
¦ ¦
L----------------------------------------------------------------

Рис. 18.3. Меню, где в качестве одного из пунктов выбора ис-
пользовано графическое изображение.



B.Pascal 7 & Objects/OW - 322 -

------------------------------------------------------------------
Глава 19. Наборы
-----------------------------------------------------------------

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

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

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

Объекты наборов
-----------------------------------------------------------------

Будучи объектами и тем самым имея встроенные методы, наборы
обладают двумя дополнительными чертами, которые имеют отношение к
обычным массивам языка Паскаль - это динамическое установка раз-
меров и полиморфизм.


Динамическая установка размеров наборов
-----------------------------------------------------------------

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

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


B.Pascal 7 & Objects/OW - 323 -

Полиморфизм наборов
-----------------------------------------------------------------

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

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

Проверка типа и наборы
-----------------------------------------------------------------

Наборы ограничивают традиционную мощную проверку типа языка
Паскаль. Это означает, что можете поместить нечто в набор и когда
запрашиваете это назад, компилятор уже не может проверить ваших
предположений относительно объекта. Вы можете поместить нечто как
PHedgehog (еж), а прочитать назад как PSheep (овца), и набор ни-
как не сможет насторожить вас.

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



B.Pascal 7 & Objects/OW - 324 -

Объединение в набор элементов, не являющихся объектами
-----------------------------------------------------------------

Вы даже можете добавить в набор нечто, что вообще не являет-
ся объектом, но это также может явиться серьезным предметом оза-
боченности. Наборы ожидают получения нетипизированных указателей
незаданного типа на нечто. Но некоторые методы TCollection пред-
назначены специально для работы с наборами элементов, производных
от TObject. Это касается методов доступа к потоку PutItem и
GetItem, и стандартной процедуры FreeItem.

Например, это означает, что вы можете хранить PChar в набо-
ре, но при попытке послать этот набор в поток, результаты будут
не столь успешными, если вы не перепишете стандартные методы на-
бора GetItem и PutItem. Аналогично, при попытке освобождения на-
бора будет сделана попытка удаления каждого элемента с помощью
FreeItem. Например, это делает TStrCollection.

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

Создание набора
-----------------------------------------------------------------

Создание набора столь же просто, как и создание типа данных,
которые вы хотите в нем хранить. Предположим, что вы - консуль-
тант, и вам нужно хранить и искать номер счета, фамилию и номер
телефона каждого из ваших клиентов. Сначала определим тип объекта
клиента (TClient), который будет хранится в наборе (не забудьте
определить тип указателя для каждого нового типа объекта):

type
PClient=^TClient;
TClient=object(TObject)
Account, Name, Phone: PChar;
constructor Init(NewAccount, NewName, NewPhone: PChar);
destructor Done; virtual;
procedure Print; virtual;
end;

Затем реализуем методы Init и Done для размещения и удаления
данных о клиенте и метод Print для отображения данных о клиенте в
виде таблицы. Обратите внимание, что поля объекта имеют тип
PChar, поэтому память выделяется только для той части строки, ко-
торая действительно используется. Функции StrNew и StrDispose
очень эффективно обрабатывают динамические строки.

constructor TClient.Init(NewAccount, NewName,
NewPhone: PChar);
begin
Account := StrNew(NewAccount);
Name := StrNew(NewName);

B.Pascal 7 & Objects/OW - 325 -

Phone := StrNew(NewPhone);
end;

destructor TClientDone;
begin
StrDispose(Account);
StrDispose(Name);
StrDispose(Phone);
end;

procedure TClient.Print;
begin
Writeln( ' ',
Account, '':10 - StrLen(Account),
Name, '':20 - StrLen(Name),
Phone, '':16 - StrLen(Phone));
end;

TClient.Done будет автоматически вызываться для каждого кли-
ента при удалении всего набора. Сейчас вы просто инициируете на-
бор для хранения ваших клиентов и вставляете в него записи о кли-
ентах. Головное тело программы (COLLECT1.PAS) будет выглядеть
следующим образом:

var
ClientList: PCollection;
begin
ClientList:=New(PCollection, Init(10,5));
with ClientList^ do
begin
Insert(New(PClient, Init('91-100', 'Anders, Smitty',
'(406) 111-2222')));
Insert(New(PClient, Init('90-167', 'Smith, Zelda',
'(800) 555-1212')));
Insert(New(PClient, Init('90-177', 'Smitty, John',
'(406) 987-4321')));
Insert(New(PClient, Init('90-160', 'Johnson, Agatha',
'(302) 139-8913')));
end;
PrintAll(ClientList);
SearchPhone(ClientList, '(406)');
Dispose(ClientList, Done);
end.

Примечание: Процедуры PrintAll и SearchPhone будут
рассмотрены позднее.

Обратите внимание, насколько просто было построить набор.
Первый оператор размещает новый экземпляр TCollection с именем
ClientList с начальным размером на 10 клиентов. В случае необхо-
димости размещения более 10 клиентов в ClientList, его размер бу-
дет увеличиваться каждый раз на 5 клиентов. Следующие два опера-
тора создают новый объект клиента и вставляют его в набор. Вызов

B.Pascal 7 & Objects/OW - 326 -

Dispose в конце операции освобождает весь набор клиентов.

Нигде не нужно было сообщать набору, какой вид данных пред-
полагается хранить - для этого просто используется указатель.

Методы итератора
-----------------------------------------------------------------

Вставка и удаление элемента не являются единственными общими
операторами набора. Очень часто вы будете писать циклы for для
просмотра всех объектов набора с целью отображения данных или вы-
полнения некоторых вычислений. В других случаях вы будете искать
первый или последний элемент набора, который удовлетворяет неко-
торому критерию поиска. Для этих целей у наборов имеется три ме-
тода итератора: ForEach, FirstThat и LastThat. Каждый из них
воспринимает указатель на процедуру или функцию в качестве своего
единственного параметра.

Итератор ForEach
-----------------------------------------------------------------

ForEach воспринимает указатель на процедуру. Процедура имеет
один параметр, который является указателем на хранимый в наборе
элемент. Для каждого элемента набора ForEach вызывает процедуру
один раз, в той последовательности, в которой элементы появляются
в наборе. Процедура PrintAll в Collect1 показывает пример итера-
тора FoeEach.

procedure PrintAll(C: PCollection);
procedure CallPrint(P: PClient); far;
begin
P^.Print; {Вызов метода Print}
end;
begin {Print}
Writeln;
Writeln;
Writeln('Client list:');
C^.ForEach(@CallPrint); { распечатка для каждого клиента }
end;

Для каждого элемента набора, переданного в качестве парамет-
ра в PrintAll, вызывается вложенная процедура CallPrint.
CallPrint просто распечатывает информацию об объекте клиента в
отформатированных колонках.

Примечание: Итераторы должны вызывать локальные проце-
дуры far.

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

* Быть процедурой - она не может быть функцией или методом

B.Pascal 7 & Objects/OW - 327 -

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

* Быть локальной (вложенной) относительно вызывающей ее прог-
раммы.

* Описываться как дальняя процедура директивой far или ди-
рективой компилятора {$F+}.

* Воспринимать указатель на элемент набора в качестве своего
единственного параметра.

Итераторы FirstThat и LastThat
-----------------------------------------------------------------

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

FirstThat и LastThat возвращают указатель на первый (или
последний) элемент, который удовлетворяет условию поиска. Предпо-
ложим, что в приведенном ранее примере списка клиентов, вы не мо-
жете вспомнить номер счета клиента или не помните точно написание
имени клиента. К счастью, вы точно помните, что это был ваш пер-
вый клиент из штата Монтана. Следовательно, вы можете организо-
вать поиск первого клиента с кодом штата 406 (поскольку ваш спи-
сок клиентов ведется хронологически). Данная процедура использует
метод FirstThat, который и сделает всю работу:

procedure SearchPhone(C: PCollection; PhoneToFind: PChar);
function PhoneMatch(Client: PClient: PClient): Boolean;
far;
begin
PhoneMatch := StrPos(Client^.Phone, PhoneToFind) <> nil;
end;
var
FoundClient: PClient;
begin { SearchPhone }
Writeln;
FoundClient := C^.FirstThat(@PhoneMatch);
if FoundClient = nil then
Writeln('Такому требованию не отвечает ни один клиент')
else
begin
Writeln('Найден клиент:');
FoundClient^.Print;
end;
end;


B.Pascal 7 & Objects/OW - 328 -

Снова обратите внимание на то, что PhoneMatch вложена и ис-
пользует удаленную модель вызова. В этом случае эта функция возв-
ращает True только при совпадении номера телефона клиента и за-
данного образца поиска. Если в наборе нет объекта, который соот-
ветствовал бы критерию поиска, FirstThat возвращает указатель
nil.

Запомните: ForEach вызывает определенную пользователем про-
цедуру, а FirstThat и LastThat каждая вызывает определенную поль-
зователем булевскую функцию. В любом случае определенная пользо-
вателем процедура или функция передают указатель на объект набо-
ра.

Отсортированные наборы
-----------------------------------------------------------------

Иногда вам бывает нужно, чтобы ваши данные были определенным
образом отсортированы. ObjectWindows имеет специальный тип набо-
ра, который позволяет вам упорядочить ваши данные произвольным
образом. Это тип TSortedCollection.

TSortedCollection является производным от TCollection и ав-
томатически сортирует задаваемые ему объекты. При добавлении но-
вого элемента он автоматически проверяет набор на дублирование
ключей. Булевское поле Duplicates контролирует разрешение дубли-
рования ключей. Если для поля Duplicates установлено значение
False (по умолчанию), то новый элемент добавляется к набору, за-
меняя существующий член с тем же самым ключом. Если Duplicates
имеет значение True, то новый член просто вставляется в набор.

TSortedCollection - это набор абстрактного типа. Для его ис-
пользования вы должны сначала решить, какой тип данных вы собира-
етесь собирать и определить два метода, отвечающих вашим конкрет-
ным требованиям сортировки. Для этого вам нужно создать новый
тип, производный от TSortedCollection. В данном случае назовем
его TClientCollection. Ваш TClientCollection уже знает, как де-
лать всю реальную работу с набором. Он может вставить (Insert)
запись о новом клиенте и удалять (Delete) существующие записи -
он унаследовал эти основные черты поведения от 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

B.Pascal 7 & Objects/OW - 329 -

KeyOf := PClient(Item)^.Account;
end;

function TClientCollection.Compare(Key1, Key2: Pointer):
Integer;
begin
Compare := StrIComp(PChar(Key1), PChar(Key2));
end;

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

KeyOf определяет, какое поле или поля используются в качест-
ве ключей сортировки. В данном случае это поле клиента Account.
Compare воспринимает два ключа сортировки и определяет, какой из
них должен идти первым в соответствии с правилами сортировки.
Compare возвращает -1, 0 или 1 в зависимости от того, Key1 мень-
ше, равен или больше Key2, соответственно. В данном примере ис-
пользуется сортировка по алфавиту (для букв верхнего и нижнего
регистра) ключевой строки (Account) путем вызова модуля Strings
функции StrIComp. Вы можете легко сортировать набор по именам,
вместо номера счета, если замените возвращаемое KeyOf поле на
Name.

Обратите внимание на то, что ключи, возвращаемые KeyOf и пе-
редаваемые в Compare являются нетипизированными указателями, поэ-
тому до их разыменования и передачи в StrIComp в данном примере
вы должны привести их тип к PChar.

Это практически все, что вам нужно определить! Теперь, если
вы переопределите ClientList как PClientCollection вместо
PCollection (сменив объявление var и вызов New), то легко сможете
распечатать ваших клиентов в алфавитном порядке (COLLECT2.PAS):

var
ClientList: PClientCollection;
.
.
begin
ClientList:=New(PClientCollection, Init(10,5));
.
.
end.

Обратите внимание и на то, как легко будет сменить сортиров-
ку списка клиентов по номеру счета на сортировку по имени. Все
что вам нужно сделать, это сменить метод KeyOf на возврат поля
Account на поле Name.

Наборы строк
-----------------------------------------------------------------

Многим программам требуется работать с отсортированными

B.Pascal 7 & Objects/OW - 330 -

строками. Для этих целей ObjectWindows предоставляет набор специ-
ального назначения TStrCollection (он совпадает с типом
TStringCollection, определенным для хранения строк Паскаля). Об-
ратите внимание, что элементы TStrCollection - это не объекты.
Они представляют собой указатели на строки, заканчивающиеся ну-
лем. Поскольку наборы строк происходят от TSortedCollection, мож-
но хранить и дублированные строки.

Использовать наборы строк несложно. Просто определяется пе-
ременная указателя для хранения набора строк. Разместим набор,
задав его начальный размер и приращение для роста при добавлении
новых строк (см. COLLECT3.PAS):

var
WordList: PCollection;
WordRead: PChar;
.
.
.
begin
WordList:=New(PStrCollection, Init(10,5));
.
.
.

WordList первоначально рассчитан для хранения 10 строк с
последующим приращением по 5 строк. Все что вам нужно сделать -
это вставить несколько строк в набор. В данном примере слова счи-
тываются из текстового файла и вставляются в набор:

repeat
.
.
.
if GetWord(WordRead, WordFile)^ <> #0 then
WordList^.Insert(StrNew(WordRead));
.
.
.
until WordRead[0]=#0;
.
.
.
Dispose(WordList, Done);

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

B.Pascal 7 & Objects/OW - 331 -

WordList.

Пересмотренные итераторы
-----------------------------------------------------------------

Метод ForEach просматривает весь набор, элемент за элемен-
том, и выполняет над каждым из них заданную процедуру. В предыду-
щем примере процедуре PrintWord передавался указатель строки для
ее отображения. Обратите внимание, что процедура PrintWord вло-
женная (или локальная). Она работает в другой процедуре, Print,
которой передается указатель на TstrCollection. Print использует
метод итератора ForEach для передачи каждого элемента своего на-
бора в процедуру PrintWord.

procedure Print(C: PCollection);
procedure PrintWord(P: PChar); far;
begin
Writeln(P); { вывести строку }
end;
begin {Print}
Writeln;
Writeln;
C^.ForEach(@PrintWord); { вызов PrintWord }
end;

PrintWord должен выглядеть как уже знакомая процедура. Она
просто берет указатель строки и передает его значение Writeln.
Обратите внимание на директиву far после описания PrintWord.
PrintWord не может быть методом, это просто процедура. Кроме того
это должна быть вложенная процедура. Print надо рассматривать как
некую оболочку вокруг процедуры, которая выполняет некоторую ра-
боту над каждым элементом набора (может быть отображает или моди-
фицирует данные). Вы можете иметь несколько аналогичных PrintWord
процедур, но каждая из них должна быть вложена в Print и должна
быть дальней процедурой (использовать директиву far или {$F+}).

Нахождение элемента

Отсортированные наборы (и следовательно наборы строк) имеют
метод Search, который возвращает индекс элемента с конкретным
значением ключа. Но как найти элемент в неотсортированном наборе?
Или когда критерий поиска не использует сам ключ? Конечно же,
следует использовать FirstThat и LastThat. Вы просто определяете
булевскую функцию для проверки нужного вам критерия и вызываете
FirstThat.

Полиморфические наборы
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 332 -

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

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

Если вы рассмотрите приведенные примеры наборов, вы можете
заметить, что все элементы каждого набора были одно и того же ти-
па. Мы имели дело со списком строк в котором каждый элемент был
строкой. Мы также занимались списком клиентов. Но наборы могут
хранить любые производные от TObject объекты, и вы можете произ-
вольно смешивать эти объекты. Естественно, что вы желаете, чтобы
эти объекты имели нечто общее. На самом деле вам нужно, чтобы у
них был общий абстрактный объект-предок.

В качестве примера рассмотрим программу, которая помещает в
набор три различных графических объекта. Затем итератор ForEach
используется для просмотра набора и отображения каждого объекта.
В отличие от других примеров данной главы данный пример
(Collect4) использует функции Windows для рисования в окне. Обя-
зательно включите WinProcs и WinTypes в uses данного примера.
Сначала определяется абстрактный объект-предок (см.
COLLECT4.PAS).

type
PGraphObject = ^TGraphObject;
TGraphObject = object(TObject)
Rect: TRect;
constructor Init(Bounds: TRect);
procedure Draw(DC: HDC); virtual;
end;

Из этого объявления вы можете видеть, что каждый графический
объект может инициализировать себя (Init) и отобразить себя на
графическом экране (Draw). Теперь определим эллипс, прямоугольник
и сектор как производные от этого общего предка:

PGraphEllipse = ^TGraphEllipse;
TGraphEllipse = object(TGraphObject)
procedure Draw(DC: HDC); virtual;
end;

PGraphRect=^TGraphRect;
TGraphRect=object(TGraphObject)
procedure Draw(DC: HDC); virtual;
end;
PGraphPie = ^TGraphPie;
TGraphPie = object(TGraphObject)
ArcStart, ArcEnd: TPoint;

B.Pascal 7 & Objects/OW - 333 -

constructor Init(Bounds: TRect);
procedure Draw(DC: HDC); virtual;
end;

Все эти три типа объекта наследуют поле Rect из
TGraphObject, но все они разного размера. TGraphEllipse и
TGraphRect нужно только добавить их новые методы рисования, т.к.
их методам рисования нужны только размеры и расположение, а
TGraphPie нужны дополнительные поля и другой конструктор для их
корректного представления. Приведем исходный код для помещения
этих фигур в набор:

.
.
.
GraphicsList := New(PCollection, Init(10,5));
{ создать набор }
for I := 1 to NumToDraw do
begin
case I mod 3 of { создать объект }
0: P := New(GraphRect, Init(Bounds));
1: P := New(GraphEllipse, Init(Bounds));
2: P := New(GraphPie, Init(Bounds));
end;
GraphicsList^.Insert(P); { добавить в набор }
end;
.
.

Как вы можете видеть цикл, for вставляет графические объекты
в набор GraphicsList. Вы знаете только то, что каждый объект в
GraphicsList представляет собой некоторый вид TGraphObject. После
помещения в набор у вас уже нет информации о том, является ли
элемент набора прямоугольником, эллипсом или сектором. Благодаря
полиморфизму, вам этого и не нужно знать, поскольку каждый объект
содержит все данные и код (Draw), который ему нужен. Просмотрим
набор с использованием итеративного метода и каждый набор будет
сам отображать себя:

procedure DrawAll(C: PCollection);

procedure CallDraw(P: PGraphObject); far;
begin
P^.Draw(PaintDC); { вызов метода Draw }
end;

begin {DrawAll}
C^.ForEach(@CallDraw); { прорисовать каждый объект }
end;

var
GraphicsList: PCollection;
begin

B.Pascal 7 & Objects/OW - 334 -

.
.
.
if GraphicsList <> nil then DrawAll(GraphicsList);
.
.
.
end.

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



B.Pascal 7 & Objects/OW - 335 -

Наборы и управление памятью
-----------------------------------------------------------------

TCollection может динамически расти от начального размера,
установленного Init, до максимального размера в 16380 элементов.
ObjectWindows хранит максимальный размер набора в переменной
MaxCollectionSize. Каждый добавляемый в набор элемент занимает
четыре байта памяти, т.к. он хранится в виде указателя.

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

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

Вам следует уделить особое внимание доступности динамической
области памяти, поскольку у пользователя имеет значительно боль-
ший контроль над программой ObjectWinodws, чем над обычной прог-
раммой языка Паскаль. Если добавлением объектов в набор управляет
пользователь (например, открывая новое окно), то ошибку динами-
ческой области памяти не так то легко предсказать. Вы можете
предпринять некоторые шаги по защите пользователя от фатальной
ошибки при выполнении программы либо проверяя память при исполь-
зовании набора, либо обрабатывая сбой выполняемой программы таким
образом, чтобы избежать прекращения ее работы.



B.Pascal 7 & Objects/OW - 336 -

------------------------------------------------------------------
Глава 20. Потоки
-----------------------------------------------------------------

Техника объектно-ориентированного программирования и
ObjectWindows дают вам мощные средства инкапсуляции кода и дан-
ных и большие возможности построения взаимосвязанных структур
объектов. Но что делать, если стоит простая задача, например, по
хранению некоторых объектов на диске?

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

Есть ли в самом объектно-ориентированном программировании и
ObjectWindows некоторые средства, которые могли бы разрешить эту
проблему? Есть, и это потоки.

Поток в ObjectWindows - это набор объектов на их пути ку-
да-либо: обычно в файл, EMS, в последовательный порт или некото-
рое другое устройство. Потоки обслуживают операции ввода-вывода
на уровне объектов, а не на уровне данных. При расширении объекта
ObjectWindows вам нужно обеспечить обработку определенных вами
дополнительных полей. Все сложные аспекты обработки на уровне
объектов будут проделаны за вас.

Вопрос: объектный ввод-вывод
-----------------------------------------------------------------

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

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

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

Но эту проблему снова можно обойти. Вы можете выделить дан-

B.Pascal 7 & Objects/OW - 337 -

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

Ответ: потоки
-----------------------------------------------------------------

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

Полиморфизм потоков
-----------------------------------------------------------------

Потоки ObjectWindows позволяют вам работать с файлами опре-
деленного и неопределенного типа: проверка типа имеется, но тип
посылаемого объекта не должен обязательно определяться во время
компиляции. Смысл в том, что потоки знают, что они имеют дело с
объектами, и поскольку все объекты являются производными от
TObject, поток может их обработать. В действительности различные
объекты ObjectWindows могут также легко записываться в один по-
ток, как и группы идентичных объектов.

Потоки обрабатывают объекты
-----------------------------------------------------------------

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

Но каким образом один и тот же поток может считывать и запи-
сывать такие разные объекты как TCollection и TDialog, даже не
зная в момент компиляции, какие типы объектов он будет обрабаты-
вать? Это существенно отличается от традиционных операций вво-
да-вывода языка Паскаль. В действительности потоки могут обраба-
тывать даже новые типы объектов, которые вообще еще не были соз-
даны к моменту компиляции потока.

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



B.Pascal 7 & Objects/OW - 338 -

Смысл использования потоков
-----------------------------------------------------------------

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

Потоки (как и файлы Паскаля) можно также просматривать, как
устройства ввода-вывода произвольного доступа, искать определен-
ное место в файле, считывать данные в этой точке или записывать
данные в эту точку, возвращать позицию указателя файла и т.д. Все
эти операции можно выполнять с потоками, и они описаны в разделе
"Потоки с произвольным доступом".

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

Установка потока

Все что нужно сделать для использования потока - это инициа-
лизировать его. Точный синтаксис конструктора Init может быть
разным, в зависимости от типа потока, с которым вы имеете дело.
Например, если вы открываете поток DOS, вам нужно передать имя
файла DOS и режим доступа (только чтение, только запись, чте-
ние/запись) для содержащего поток файла.

Например, для инициализации буферизированного потока DOS при
загрузке набора объектов в программу, все что вам нужно это:

var
SaveFile: TBufStream;
begin
SaveFile.Init('COLLECT.DTA', stOpen, 1024);
.
.

После инициализации потока все готово к работе.

TStream это абстрактный механизм потока, поэтому вы будет
работать не с ним, а с производными от TStream удобными объектами
потока. Это будет, например, TDosStream, для выполнения дисковых
операций ввода-вывода, TBufStream для буферизованных операций
ввода-вывода (очень удобен для частых операций считывания или за-
писи небольших объемов информации на диск) и TEmsStream для пере-
дачи объектов в память EMS. Кроме того, ObjectWindows реализует
индексированные потоки с указателем, указывающим место в потоке.
Перемещая этот указатель вы можете организовать произвольный дос-
туп в потоке.

B.Pascal 7 & Objects/OW - 339 -


Чтение из потока и запись в поток
-----------------------------------------------------------------

Основной объект потока TStream реализует три главных метода,
которые вам нужно четко понимать: Get, Put и Error. Get и Put
грубо соответствуют процедурам Read и Write, которые вы использу-
ете в обычных операциях ввода-вывода. Error - это процедура, ко-
торая вызывается при появлении ошибок потока.

Метод Put

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

SomeStream.Put(PSomeObject);

где SomeStream - это некоторый производный от TStream объект, ко-
торый был инициализирован, а PSomeObject представляет собой ука-
затель на некоторый производный от TObject объект, который заре-
гистрирован с потоком. Это все, что вам нужно сделать. Поток мо-
жет из таблицы виртуальных методов PSomeObject узнать, какой это
тип объекта (предполагается, что тип зарегистрирован), поэтому он
знает какой номер идентификатора писать, и сколько после него бу-
дет данных.

Специальный интерес для вас, как для программиста, работаю-
щего с ObjectWindows, состоит в том факте, что при помещении в
поток группы с дочерними окнами, дочерние окна также автоматичес-
ки помещаются в поток. Таким образом, запись сложных объектов не
так уж и сложна, более того, это делается автоматически! Вы може-
те сохранить полное состояние диалога простым помещением объекта
диалога в поток. При повторном запуске вашей программы и загрузке
диалога будет выведено его состояние в момент записи.

Метод Get

Считывание объектов из потока столь же просто. Все что вам
нужно сделать, это вызвать функцию Get:

PSomeObject := SomeStream.Get;

где SomeStream - это инициализированный поток ObjectWindows, а
PSomeObject - указатель на некоторый тип объекта ObjectWindows.
Get просто возвращает указатель на нечто, что он взял из потока.
Сколько данных было взято и какой тип таблицы виртуальных методов
(VMT) присвоен данным, определяется не типом PSomeObject, а типом
объекта, обнаруженным в потоке. Следовательно, если объект в те-
кущей позиции SomeStream имеет не совпадающий с PSomeObject тип,
у вас будет некорректная информация.

Как и Put, Get ищет сложные объекты. Следовательно, если вы
ищите в потоке окно, которое владеет дочерними окнами, то они

B.Pascal 7 & Objects/OW - 340 -

также будут загружены.

Метод Error

И, наконец, процедура Error определяет что происходит при
возникновении ошибки потока. По умолчанию TStream.Error просто
устанавливает значение двух полей в потоке (Status и ErrorInfo).
Если вы хотите сделать что-либо более содержательное, например,
сгенерировать соответствующее сообщение о сбое в работе программы
или вывести блок диалога c сообщением об ошибке, то вам нужно пе-
реопределить процедуру Error.

Закрытие потока
-----------------------------------------------------------------

Когда вы закончили использование потока, вы вызываете его
метод Done, как вы обычно вызывали Close для дискового файла. Как
и для других объектов ObjectWindows, это делается следующим обра-
зом:

Dispose(SomeStream, Done);

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

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

Все стандартные объекты ObjectWindows готовы к использованию
в потоках, и все потоки ObjectWindows узнают стандартные объекты.
При изготовлении нового типа объекта, производного от стандартно-
го объекта, его очень просто подготовить к использованию в потоке
и известить потоки о его существовании.

Методы загрузки и хранения
-----------------------------------------------------------------

Действительное чтение и запись объектов в поток производится
методами Load и Store. Каждый объект должен иметь эти методы для
использования потока, поэтому вы никогда не будете вызывать их
непосредственно (они вызываются из методов Get и Put.) Все что
вам нужно сделать, это убедиться в том, что объект знает, как
послать себя в поток, когда это потребуется.

Благодаря объектно-ориентированному программированию это де-
лается очень просто, т.к. большинство механизмов наследуются от
объекта-предка. Все что должен делать ваш объект, это загружать и
хранить те свои компоненты, которые вы в него добавляете, об ос-
тальном позаботится метод предка. Например, вы производите от
TWindow новый вид окна с именем художника-сюрреалиста Рене Маг-
ритте, который нарисовал много известных картин с окнами:

type
TMagritte = object(TWindow)

B.Pascal 7 & Objects/OW - 341 -

Surreal: Boolean;
constructor Load(var S: TStream);
procedure Store(var S: TStream);
.
.
.
end;

Все что было добавлено к данным окна - это одно булевское
поле. Для загрузки объекта вы просто считываете стандартный
TWindow, а затем считываете дополнительный байт булевского поля.
Типичные методы Load и Store для производных объектов будут выг-
лядеть следующим образом:

constructor TMagritte.Load(var S: Stream);
begin
TWindow.Load(S); { загрузка типа }
S.Read(Surreal, SizeOf(Surreal)); { чтение
дополнительных полей }
end;

procedure TMagritte.Store(var S: Stream);
begin
TWindow.Store(S); { сохранение типа }
S.Write(Surreal, SizeOf(Surreal)); { запись
дополнительных полей }
end;

Вы должны контролировать, что записывается и загружается
один и тот же объем данных, и загрузка данных производится в той
же последовательности, что и их запись. Компилятор не покажет
ошибки. Если вы будете недостаточно аккуратны, то могут возник-
нуть серьезные проблемы. Если вы изменяете поля объекта, то нужно
изменить и метод Load, и метод Store.

Регистрация потока
-----------------------------------------------------------------

Кроме определения методов Load и Store для новых объектов,
вы также должны зарегистрировать этот новый тип объекта в пото-
ках. Регистрация - это простой процесс, который состоит из двух
этапов: сначала определяется запись регистрации потока, а затем
она передается глобальной процедуре регистрации RegisterType.

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

Для определения записи регистрации потока нужно следовать
приводимому ниже формату. Запись регистрации потока это запись
языка Pascal типа TStreamRec, которая определяется следующим об-
разом:


B.Pascal 7 & Objects/OW - 342 -

PStreamRec = ^TStreamRec;
TStreamRec = record
ObjType: Word;
VmtLink: Word;
Load: Pointer;
Store: Pointer;
Next: Word;
end;

По соглашению всем регистрационным записям потока
ObjectWindows присваивается то же имя, что и соответствующим ти-
пам объектов, но начальное "T" заменяется на "R". Следовательно,
регистрационная запись для TCollection будет иметь имя
RCollection. Такие абстрактные типы как TObject и TWindowsObject
не имеют регистрационных записей, поскольку их экземпляры вы ни-
когда не будете хранить в потоках.

Номера идентификаторов объектов
-----------------------------------------------------------------

Вам действительно нужно думать только о поле ObjType записи,
все остальное делается механически. Каждому новому определяемому
вами типу требуется его собственный уникальный идентификатор типа
в виде числа. ObjectWindows резервирует регистрационные номера от
0 до 99 для стандартных объектов, поэтому ваши регистрационные
номера будут лежать в диапазоне от 100 до 65535.

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

Автоматические поля
-----------------------------------------------------------------

Поле VmtLink это связь с таблицей виртуальных методов объек-
тов (VMT). Вы просто задаете его как отклонение типа вашего объ-
екта:

RSomeObject.VmtLink := Ofs(TypeOf(TSomeObject)^);

Поля Load и Store содержат соответственно адреса методов
Load и Store.

RSomeObject.Load := @TSomeObject.Load;
RSomeObject.Store := @TSomeObject.Store;

Значение последнего поля, Next, задается RegisterType и не
требует никакого вмешательства с вашей стороны. Оно просто обес-

B.Pascal 7 & Objects/OW - 343 -

печивает внутреннее использование скомпонованного списка регист-
рационных записей потока.

Регистрация на месте
-----------------------------------------------------------------

После конструирования регистрационной записи потока вы вызы-
ваете RegisterType с вашей записью в качестве параметра. Поэтому
для регистрации вашего нового объекта TMagritte для его использо-
вания в потоке вы включаете следующий код:

const
RMagritte: TStreamRec = (
ObjType: 100;
VmtLink: Ofs(TypeOf(TMagritte)^);
Load: @TMagritte.Load;
Store: @TMagritte.Store
);
RegisterType(RMagritte);

Вот и все. Теперь вы можете помещать (Put) экземпляры вашего
нового типа объекта в любой поток ObjectWindows и считывать их из
потоков.

Регистрация стандартных объектов
-----------------------------------------------------------------

ObjectWindows определяет регистрационные записи потоков для
всех его стандартных объектов. Кроме того, модуль WObjects опре-
деляет процедуру RegisterWObjects, которая автоматически регист-
рирует все объекты этого модуля. Например, модуль OWindows содер-
жит процедуру RegisterOWindows, а ODialogs - RegisterODialogs.

Механизм потока
-----------------------------------------------------------------

После того, как мы посмотрели на процесс использования пото-
ков, следует заглянуть во внутреннюю работу, которую производит
ObjectWindows c вашими объектами с помощью методов Put и Get. Это
прекрасный пример взаимодействия объектов и использования встро-
енных в них методов.

Процесс Put
-----------------------------------------------------------------

Когда вы посылаете объект в поток с помощью метода Put, по-
ток сначала берет указатель VMT со смещением 0 от объекта и прос-
матривает список зарегистрированных типов потоков системы с целью
найти совпадение. Когда это совпадение найдено, поток ищет ре-
гистрационный номер идентификатора объекта и записывает его в по-
ток. Затем поток вызывает метод Store объекта для завершения за-
писи объекта. Метод Store использует процедуру потока Write, ко-
торая действительно пишет корректное число байт в поток.

B.Pascal 7 & Objects/OW - 344 -


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

Процесс Get
-----------------------------------------------------------------

Когда вы считываете объект из потока с помощью метода Get,
сначала ищется номер его идентификатора, и просматривается на
совпадение список зарегистрированных типов. После обнаружения
совпадения регистрационная запись дает потоку местоположение ме-
тода Load объект и VMT. Затем для чтения нужного объема данных из
потока вызывается метод Load.

Вы опять просто говорите потоку, что нужно взять (Get) сле-
дующий объект и поместить его в место, определяемое заданным вами
указателем. Ваш объект даже не беспокоится о том, с каким потоком
он имеет дело. Поток сам беспокоится о считывании нужного объема
данных из потока с помощью метода объекта Load, который в свою
очередь опирается на метод потока Read.

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

Обработка указателей объектов со значением nil
-----------------------------------------------------------------

Вы можете записать в поток объект nil. Однако, если это сде-
лать, то в поток запишется слово 0. При считывании идентификатора
слова 0 поток возвратит указатель nil. Поэтому 0 считается заре-
зервированным и не может использоваться в качестве номера иденти-
фикатора объекта потока. ObjectWindows резервирует идентификатор
потока от 0 до 99 для внутреннего использования.

Наборы в потоке: пример
-----------------------------------------------------------------

В Главе 19, "Наборы", вы уже видели как наборы могут содер-
жать разные, но связанные объекты. Это свойство полиморфизма так-
же применимо и к потокам, и их можно использовать для записи на-
боров на диск для последующего обращения, даже в другой програм-
ме. Вернемся к примеру COLLECT4.PAS. Что еще нужно добавить в эту
программу для помещения набора в поток?

Ответ будет очень простым. Сначала возьмем базовый объект
TGraphObject и "научим" его хранить его данные (X и Y) в потоке.
Для этого нужен метод Store. Затем определим новый метод Store
для любого производного от TGraphObject объекта, в котором до-
бавляются дополнительные поля (например, TGraphPie добавляет
ArcStart и ArcEnd).

B.Pascal 7 & Objects/OW - 345 -


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

Добавление методов Store
-----------------------------------------------------------------

Приведем методы Store. Обратите внимание, что для
PGraphEllipse и PGraphRect не требуются свои собственные методы,
т.к. они не добавляют новых полей к унаследованным от
PGraphObject:

type
PGraphObject = ^TGraphObject;
TGraphObject = object(TObject)
Rect: TRect;
constructor Init(Bounds: TRect);
procedure Draw(DC: HDC); virtual;
procedure Store(var S: TStream); virtual;
end;

PGraphEllipse = ^TGraphEllipse;
TGraphEllipse = object(TGraphObject)
procedure Draw(DC: HDC); virtual;
end;

PGraphRect = ^TGraphRect;
TGraphRect = object(TGraphObject)
procedure Draw(DC: HDC); virtual;
end;

PGraphPie = ^TGraphPie;
TGraphPie = object(TGraphObject)
ArcStart, ArcEnd: TPoint;
constructor Init(Bounds: TRect);
procedure Draw(DC: HDC); virtual;
procedure Store(var S: TStream); virtual;
end;

Реализация метода Store вполне очевидна. Каждый объект вызы-
вает свой унаследованный метод Store, который хранит все унасле-
дованные данные. Затем вызывается метод Write для записи дополни-
тельных данных:

procedure TGraphObject.Store(var S: TStream);
begin
S.Write(Rect, SizeOf(Rect));
end;
procedure TGraphPie.Store(var S: TStream);

B.Pascal 7 & Objects/OW - 346 -

begin
TGraphObject.Store(S);
S.Write(ArcStart, SizeOf(ArcStart));
S.Write(ArcEnd, SizeOf(ArcEnd));
end;

Обратите внимание, что метод TStream Write делает двоичную
запись. Его первый параметр может быть переменной любого типа, но
TStream.Write не может узнать размеры этой переменной. Второй па-
раметр содержит эту информацию, и вы должны придерживаться согла-
шения относительно использования стандартной функции SizeOf. Та-
ким образом, компилятор всегда может гарантировать, что вы всегда
считываете и записываете нужное количество данных.

Регистрация записей
-----------------------------------------------------------------

Наш последний шаг состоит в определении константы регистра-
ционной записи для каждого производного типа. Хороший прием прог-
раммирования состоит в следовании соглашению ObjectWindows отно-
сительно использования для имени типа идентификатора, где вместо
первой буквы T ставится R.

Помните о том, что каждой регистрационной записи присваива-
ется уникальный номер идентификатора объекта (ObjType). Номера от
0 до 99 резервируются ObjectWindows для стандартных объектов. Хо-
рошо бы отслеживать все номера идентификаторов ваших объектов по-
тока в некотором центральном месте, чтобы избежать дублирования.

const
RGraphEllipse: TStreamRec = (
ObjType: 150;
VmtLink: Ofs(TypeOf(TGraphEllipse)^);
Load: nil; { метод загрузки
отсутствует }
Store: @TGraphEllipse.Store);
RGraphRect: TStreamRec = (
ObjType: 151;
VmtLink: Ofs(TypeOf(TGraphRect)^);
Load: nil; { метод загрузки
отсутствует }
Store: @TGraphRect.Store);
RGraphPie: TStreamRec = (
ObjType: 152;
VmtLink: Ofs(TypeOf(TGraphPie)^);
Load: nil; { метод загрузки
отсутствует }
Store: @TGraphPie.Store);

Вам не нужно регистрационная запись для TGraphObject, так
как это абстрактный тип, и он никогда не будет помещаться в набор
или в поток. Указатель Load каждой регистрационной записи уста-
навливается в nil, поскольку в данном примере рассматривается

B.Pascal 7 & Objects/OW - 347 -

только помещение данных в поток. В следующем примере методы Load
будут определены, и изменены регистрационные записи (см.
STREAM2.PAS).

Регистрация
-----------------------------------------------------------------

Всегда нужно зарегистрировать каждую из этих записей до про-
ведения каких-либо операций ввода-вывода с потоком. Самый простой
способ сделать это состоит в том, чтобы объединить их все в одну
процедуру и вызвать ее в самом начале вашей программы (или в ме-
тоде Init вашего приложения):

procedure StreamRegistration;
begin
RegisterType(RCollection);
RegisterType(RGraphEllipse);
RegisterType(RGraphRect);
RegisterType(RGraphPie);
end;

Обратите внимание, что вам нужно зарегистрировать
TCollection (используя его запись RCollection - теперь вы видите,
что соглашения о присваивании имен упрощают программирование),
хотя вы и не определили TCollection. Правило очень простое и не-
забываемое именно вы отвечаете за регистрацию каждого типа объек-
та, который ваша программа будет помещать в поток.

Запись в поток
-----------------------------------------------------------------

Нужно следовать обычной последовательности операций вво-
да-вывода в файл: создать поток; поместить в него данные (набор);
закрыть поток. Вам не нужно писать итератор ForEach для помещения
в поток каждого элемента набора. Вы просто говорите потоку, что
нужно поместить (Put) набор в поток:

var
.
.
.
GraphicsStream: TBufStream;
begin
.
.
.
StreamRegistration; { регистрация всех объектов потока }
GraphicsStream.Init('GRAPH.SMT', stCreate, 1024);
GraphicsStream.Put(GraphicsList); { выходной набор }
if GraphicsStream.Status <> 0 then
Status:=em_Stream;
GraphicsStream.Done; { сброс потока }
end;

B.Pascal 7 & Objects/OW - 348 -


В результате создастся файл на диске, который содержит всю
информацию, необходимую для "считывания" набора назад в память.
Когда поток открыт, и ищется набор, то (см. STREAM2.PAS) "маги-
чески" восстанавливаются все скрытые связи между набором и его
элементами, объекты и их таблицы виртуальных методов. Следующий
раздел поясняет, как помещать в поток объекты, которые содержат
связи с другими объектами.

Как все хранится?
-----------------------------------------------------------------

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

В реальных сложных приложениях множество объектов часто име-
ют указатель на конкретную структуру. Когда возникает необходи-
мость в выполнении операций ввода-вывода, вы должны решить, кто
"владеет" структурой. Только этот владелец должен посылать струк-
туру в поток. Иначе у вас может получиться несколько копий одной
структуры в потоке. При считывании такого потока будет создано
несколько экземпляров структуры, и каждый из первоначальных объ-
ектов будет указывать на собственную персональную копию структуры
вместо единственной первоначальной структуры.

Поля в потоке
-----------------------------------------------------------------

Много раз вы видели, что удобно хранить указатель на дочер-
ние окна группы в локальной переменной (поле данных объекта).
Например, блок диалога может хранить указатель на его объекты уп-
равления в полях с мнемоническими именами для более удобного дос-
тупа (OKButton или FileINputLine). При создании такого дочернего
окна порождающее окно будет иметь на него два указателя, один -
в поле, и еще один - в списке дочерних окон. Если на это не обра-
тить внимания, то считывание такого объекта из потока приведет к
дублированию.

Решение состоит в использовании методов TWindowsObject
GetChildPtr и PutChildPtr. При хранении поля, которое является
дочерним окном, вместо записи указателя, как если бы это была
простая переменная, вы вызываете метод PutChildPtr, который запи-
сывает ссылку на позицию дочернего окна в списке дочерних окон
группы. Аналогично, при загрузке (Load) группы из потока, вы вы-
зываете GetChildPtr, который гарантирует, что поле и список до-
черних окон указывают на один и тот же объект. Приведем короткий
пример использования GetChildPtr и PutChildPtr в простом окне:

type
TDemoWinodw = object(TWindow)

B.Pascal 7 & Objects/OW - 349 -

Msg: PStatic;
constructor Load(var S: TStream);
procedure Store(var S: TStream);
end;

constructor TDemoWindow.Load(var S: TStream);
begin
TWindow.Load(S);
GetChildPtr(S, Msg);
end;

procedure TDemoWindow.Store(var S: TStream);
begin
TWindow.Store(S);
PutChildPtr(S, Msg);
end;

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

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

Родство экземпляров окон
-----------------------------------------------------------------

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

Как и для дочерних окон, при чтении и записи родственных
ссылок в поток могут возникнуть проблемы. Решение также будет
аналогичным. Методы TWindowsObject PutSiblingPtr и GetSiblingPtr
предоставляют средства доступа к родственникам:

type
TActivateRadioButton=object(TRadioButton)
EditControl: PEdit;

B.Pascal 7 & Objects/OW - 350 -

.
.
.
constructor Load(var S: TStream);
procedure Store(var S: TStream); virtual;
.
.
.
end;

constructor TActivateRadioButton.Load(var S: TStream);
begin
TRadioButton.Load(S);
GetPeerPtr(S, EditControl);
end;

procedure TActivateRadioButton.Store(var S: TStream);
begin
TRadioButton.Load(S);
PutPeerPtr(S, EditControl);
end;

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

Копирование потока
-----------------------------------------------------------------

TStream имеет метод CopyFrom(S,Count), который копирует за-
данное число байт (Count) из заданного потока S. Метод CopyFrom
может быть использован для копирования содержимого одного потока
в другой. Если, например, вы циклически обращаетесь к дисковому
потоку, то можете скопировать его в поток EMS для организации бо-
лее быстрого доступа:

NewStream := New(TEmsStream, Init(OldStream^.GetSize));
OldStream^.Seek(0);
NewStream^.CopyFrom(OldStream, OldStream^.GetSize);

Потоки произвольного доступа
-----------------------------------------------------------------

До этого момента мы работали с потоками как с устройствами
последовательного доступа: вы помещали (Put) объекты в конец ва-

B.Pascal 7 & Objects/OW - 351 -

шего потока и считывали их назад (Get) в той же последовательнос-
ти. Но ObjectWindows имеет и более мощные средства. Имеется воз-
можность рассматривать поток как виртуальное устройство произ-
вольного доступа. Кроме методов Get и Put, которые соответствуют
Read и Write при работе с файлом, потоки обладают средствами про-
ведения операций Seek, FilePos, FileSize и Truncate.

- Процедура потока Seek перемещает текущий указатель потока
к заданной позиции (число байт от начала потока), как
стандартная процедура Seek языка Паскаль.

- Процедура GetPos по своему действию обратна процедуре
Seek. Она возвращает значение Longint с текущей позицией
потока.

- Функция GetSize возвращает размер потока в байтах.

- Процедура Truncate удаляет все данные, которые расположены
после текущей позиции потока, при этом текущая позиция по-
тока становится концом потока.

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

Необъектные элементы потоков
-----------------------------------------------------------------

В поток можно записывать и элементы, которые не являются
объектами, но для этого следует использовать несколько иной под-
ход. Стандартные методы потока Get и Put требуют загрузки или за-
писи объекта, производного от TObject. Если вам нужно создать по-
ток, который состоит не из объектов, переходите на нижний уровень
процедур Read и Write, где в поток записывается или из него счи-
тывается заданное число байт. Этот же механизм используют методы
Get и Put для чтения и записи данных об объектах. Вы просто обхо-
дите механизм VMT, который заложен в Put и Get.

Разработка пользователем собственных потоков
-----------------------------------------------------------------

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

Сам TStream является абстрактным объектом и его можно расши-
рить для создания удобного типа потока. Большинство методов
TStream являются абстрактными и должны быть реализованы как их
производные методы, основывающиеся на абстрактных методах
TStream. Полностью реализованы только методы Error, Get и Put.
GetPos, GetSize, Read, Seek, SetPos, Truncate и Write должны быть
переписаны. Если производный тип объекта имеет буфер, то должен

B.Pascal 7 & Objects/OW - 352 -

быть переписан и метод Flush.

Обработка ошибок потока
-----------------------------------------------------------------

TStream имеет метод Error(Code, Info), который вызывается
при обнаружении ошибки потока. Error просто присваивает полю
Status потока значение одной из констант, приведенных в Главе 21
"Справочник по ObjectWindows" в разделе "Константы stXXXX".

Поле ErrorInfo не определено, если значение Status не есть
stGetError или stPutError. Если значение поля Status равно
stGetError, то поле ErrorInfo содержит номер идентификатора пото-
ка незарегистрированного типа. Если значение поля Status равно
stPutError, то поле ErrorInfo содержит смещение VMT типа, который
вы пытались поместить в поток. Вы можете переписать TStream.Error
для генерации любого уровня обработки ошибок, включая ошибки эта-
па выполнения.



B.Pascal 7 & Objects/OW - 353 -

------------------------------------------------------------------
------------------------------------------------------------------
Часть 4. Справочник по ObjectWindows
-----------------------------------------------------------------


Глава 21. Объектные типы ObjectWindows
-----------------------------------------------------------------

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

Для нахождения информации по определенному объекту нужно
учитывать, что многие свойства объектов в иерархии наследуются от
"предков". Чтобы не дублировать всю информацию, эта глава описы-
вает только те элементы данных и функции, которые добавляются или
изменяются в данном объекте. Просмотрев диаграмму наследования
для объекта, вы легко можете определить, в каких его предках вво-
дится поле, а в каких задается или переопределяется метод.

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



B.Pascal 7 & Objects/OW - 354 -

------------------------------------------------------------------
TSample модуль TSample
-----------------------------------------------------------------

TObject TSample
-------¬ ---------------¬
+------+ ¦ AField ¦
¦-Init-¦ ¦ AnotherField ¦
¦ Done ¦ +--------------+
¦ Free ¦ ¦ Init ¦
L------- ¦ Zilch ¦
L---------------

Сначала дается общее описание объекта, его связи с дpугими
объектами и использование. На приведенной выше диаграмме показа-
но, что объект TSample является непосредственным потомком
TObject, и что он переопределяет конструктор Init.

Поля
-----------------------------------------------------------------

В данном разделе в алфавитном порядке перечисляются поля
каждого объекта. Кроме описания поля и его пояснения показывается
режим доступа к данному полю - только чтение или чтение/запись.
Поля, доступные только по чтению - это в общем случае поля, кото-
рые устанавливаются и обслуживаются методами объекта и которые не
должны указываться в левой части оператора присваивания.

AField

AField: SomeType: (только чтение)

AField - это поле, которое содержит некоторую информацию о
данном примере объекта. Этот текст пояcняет, как оно функциониру-
ет, что оно означает и как его использовать.

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

AnotherField

AhotherField: Word: (чтение/запись)

Далее следует поясняющая информация, аналогичная AField.

Методы
-----------------------------------------------------------------

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

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

B.Pascal 7 & Objects/OW - 355 -

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

Init
-----------------------------------------------------------------

constructor Init(AParameter: SomeType);

Init создает новый объект, вызывая сначала конструктор Init,
наследуемый из TObject, затем устанавливая поле AField в
AParameter.

См. также: TObject.Init

Zilch (иногда переопределяется)
-----------------------------------------------------------------

procedure Zilch; virtual;

Процедура Zilch вызывает выполнение объектом некоторых дейс-
твий.

См. также TSomethingElse.Zilch.

Процедура Sample (модуль Sample)
-----------------------------------------------------------------

Описание: procedure Sample(AParameter);

Назначение: Sample выполняет некоторые полезные действия со
своим параметром AParemeter.

См. также: функцию Example.

Процедура Abstract модуль Objects
-----------------------------------------------------------------

Описание: procedure Absract;

Назначение: Вызов данной процедуры завершает программу с
ошибкой этапа выполнения 211. При реализации абстрактного объект-
ного типа используйте вызов Abstact в тех виртуальных методах,
которые должны переопределяться в наследующих типах. Это обеспе-
чивает, что любая попытка использовать экземпляры абстрактного
объектного типа завершится неуспешно.

Функция AllocMultiSel модуль ODialogs
-----------------------------------------------------------------

Описание: function AllocMultiSel(Count: Integer):
PMultiSelRec;

Назначение: Распределяет TMultiSelRec со счетчиком, равным

B.Pascal 7 & Objects/OW - 356 -

Count, и пространством в поле Selections, достаточным для разме-
щения Count выборов (0..Count-1). Если для распределения всей за-
писи места нет, возвращает значение nil.

Переменная Application модуль OWindows
-----------------------------------------------------------------

Описание: Application: PApplocation = nil;

Назначение: В начале TApplicationInit переменная Application
устанавливается в @Self, а в ApplicationDone сбрасывается в nil.
Таким образом, во время выполнения программы ObjectWindows
Application указывает на объект приложения.

См. также: TApplication.Init.

Константы bf_XXXX модуль ODialogs
-----------------------------------------------------------------

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

Значения: Определены следующие значения констант флага кноп-
ки:

Константы флагов кнопок Таблица 21.1
-------------------T-----------T-------------------------¬
¦ Константа ¦ Значение ¦ Смысл ¦
+------------------+-----------+-------------------------+
¦ bf_UNCHECKED ¦ 0 ¦ Элемент не выбран. ¦
¦ bf_CHECKED ¦ 1 ¦ Элемент выбран. ¦
¦ bf_GRAYED ¦ 2 ¦ Элемент выделен (серый).¦
L------------------+-----------+--------------------------



B.Pascal 7 & Objects/OW - 357 -

Стили кнопок bs_XXXX модуль WinTypes
-----------------------------------------------------------------

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

Значения: В Windows определены следующие константы:

Стили кнопок, bs_ Таблица 21.1
-----------------------T----------------------------------------¬
¦ Константа ¦ Смысл ¦
+----------------------+----------------------------------------+
¦ bs_3State ¦ Этот стиль кнопки является блоком,¦
¦ ¦ котоpый может быть выбpан, не выбpан и¦
¦ ¦ затенен. Затенение (отобpажение сеpым)¦
¦ ¦ обычно используется для указания того,¦
¦ ¦ что блок заблокиpован. ¦
+----------------------+----------------------------------------+
¦ bs_Auto3State ¦ Это то же самое, что и bs_3State, но¦
¦ ¦ в этом случае состояние блока пеpеклю-¦
¦ ¦ чается автоматически пpи щелчке¦
¦ ¦ "мышью". ¦
+----------------------+----------------------------------------+
¦ bs_AutoCheckBox ¦ Это то же самое, что и bs_CheckBox, но¦
¦ ¦ в этом случае состояние блока пеpеклю-¦
¦ ¦ чается автоматически пpи щелчке¦
¦ ¦ "мышью". ¦
+----------------------+----------------------------------------+
¦ bs_AutoRadioButton ¦ Это то же самое, что и bs_RadioButton,¦
¦ ¦ но в этом случае состояние кнопки¦
¦ ¦ пеpеключается автоматически пpи щелчке¦
¦ ¦ "мышью", пpи выбоpе кнопки и пpи удале-¦
¦ ¦ нии отметок выбоpа со всех дpугих кно-¦
¦ ¦ пок в этой гpуппе. ¦
+----------------------+----------------------------------------+
¦ bs_CheckBox ¦ Этот стиль кнопки является блоком,¦
¦ ¦ котоpый может быть выбpан или не¦
¦ ¦ выбpан. Связанный с ним текст помещает-¦
¦ ¦ ся спpава от блока. ¦
+----------------------+----------------------------------------+
¦ bs_DefPushButton ¦ Это тот же стиль кнопки, что и стиль¦
¦ ¦ bs_PushButton, за исключением того, что¦
¦ ¦ данная кнопка пpинимается по умолчанию,¦
¦ ¦ если только с помощью "мыши" или с кла-¦
¦ ¦ виатуpы не выбpана дpугая кнопка или¦
¦ ¦ блок. ¦
+----------------------+----------------------------------------+
¦ bs_GroupBox ¦ Этот стиль кнопки является блоком для¦
¦ ¦ гpуппиpования дpугих кнопок. Связанный¦
¦ ¦ с ней текст помещается в левый веpхний¦
¦ ¦ угол. ¦

B.Pascal 7 & Objects/OW - 358 -

+----------------------+----------------------------------------+
¦ bs_LeftText ¦ Пpи использовании со стилями bs_3State,¦
¦ ¦ bs_CheckBox или bs_RadioButton, этот¦
¦ ¦ стиль вызывает pазмещение текста слева,¦
¦ ¦ а не спpава от кнопки или блока. ¦
+----------------------+----------------------------------------+
¦ bs_OwnerDraw ¦ Этот стиль кнопки является кнопкой,¦
¦ ¦ отображаемой владельцем. Кpоме обычных¦
¦ ¦ кодов уведомления, посылаемых чеpез со-¦
¦ ¦ общение wm_Command, порождающий объект¦
¦ ¦ также получает запpос на pаскpаску, ин-¦
¦ ¦ веpтиpование и блокиpование кнопки. ¦
+----------------------+----------------------------------------+
¦ bs_PushButton ¦ Этот стиль кнопки пpедставляет кнопку с¦
¦ ¦ любым помещенным внутpи ее связанным с¦
¦ ¦ ней текстом. ¦
+----------------------+----------------------------------------+
¦ bs_RadioButton ¦ Этот стиль кнопки пpедставляет малень-¦
¦ ¦ кую кpуглую кнопку, котоpая может быть¦
¦ ¦ или выбpана или не выбpана. Связанный с¦
¦ ¦ ней текст помещается спpава от кнопки.¦
¦ ¦ Селективные кнопки обычно используются¦
¦ ¦ в гpуппах, в котоpых каждый pаз вы-¦
¦ ¦ биpается одна и только одна кнопка. ¦
L----------------------+-----------------------------------------

См. также: TButton.Init. TCheckBox.Init, TRadioButton.Init.

Переменная BWCCClassNames модуль OWindows
-----------------------------------------------------------------

Описание: BWCCClassNames: Boolean = False;

Назначение: Указывает, использует ли приложение имена класса
окна специализированные управляющие элементы Borland (BWCC). Ини-
циализация кода модуля BWCC устанавливает BWCCClassNames в True,
так что включение BWCC в оператор uses программы автоматически
устанавливает BWCCClassNames. "Нажимаемые" командные кнопки, объ-
екты кнопок с назависимой и зависимой фиксацией в приложениях
Windows, использующие BWCC, автоматически применяют имена класса
BWCC.

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

См. также: методы GetClassName.



B.Pascal 7 & Objects/OW - 359 -

Стили комбинированного блока cbs_XXXX модуль WinTypes
-----------------------------------------------------------------

Функция: Вы можете передавать эти константы в параметрах
стиля конструкторов объекта комбинированного блока или для зада-
ния стилей комбинированных блоков при создании комбинированных
блоков с помощью функций CreateWindows и CreateWindowsEx.

Значения: Windows определяет следующие значения

Стили комбинированных блоков Таблица 21.3
-------------------------T--------------------------------------¬
¦ Константа ¦ Смысл ¦
+------------------------+--------------------------------------+
¦ cbs_AutoHScroll ¦ Этот стиль комбиниpованного блока¦
¦ ¦ пpокpучивает текст в управляющем эле-¦
¦ ¦ менте pедактиpования впpаво, когда¦
¦ ¦ пользователь вводит символ в конце¦
¦ ¦ стpоки. Без этого стиля ввод текста¦
¦ ¦ за пpеделами гpаниц управляющего эле-¦
¦ ¦ мента редактирования был бы невозмо-¦
¦ ¦ жен. ¦
+------------------------+--------------------------------------+
¦ cbs_DropDown ¦ Этот стиль то же самое, что¦
¦ ¦ cbs_Simple, но здесь блок списка¦
¦ ¦ отобpажается тогда, когда выбиpается¦
¦ ¦ пиктогpамма, следующая за полем вы-¦
¦ ¦ боpа. ¦
+------------------------+--------------------------------------+
¦ cbs_DropDownList ¦ Этот стиль то же самое, что¦
¦ ¦ cbs_DropDown, но здесь для отобpаже-¦
¦ ¦ ния текущего выбоpа используется ста-¦
¦ ¦ тический текст, а не элемент упpавле-¦
¦ ¦ ния pедактиpованием. ¦
+------------------------+--------------------------------------+
¦ cbs_HasStrings ¦ Этот стиль может быть использован в ¦
¦ ¦ сочетании со стилем¦
¦ ¦ cbs_OwnerDrawFixed или стилем¦
¦ ¦ cbs_OwnerDrawVariable. Этот стиль в¦
¦ ¦ качестве элементов использует стpоки.¦
¦ ¦ Стpоки обслуживаются системой и могут¦
¦ ¦ быть считаны с помощью сообщения¦
¦ ¦ cb_GetLBText. ¦
+------------------------+--------------------------------------+
¦ cbs_NoIntegralHeihgt ¦ Этот стиль комбиниpованного блока¦
¦ ¦ является в точности pазмеpом, задан-¦
¦ ¦ ным пpи создании комбиниpованного¦
¦ ¦ блока. Обычно pазмеp, используемый¦
¦ ¦ для создания комбиниpованного блока,¦
¦ ¦ может изменяться, поэтому, комби-¦
¦ ¦ ниpованный блок не отобpажает частич-¦
¦ ¦ ные элементы. ¦
+------------------------+--------------------------------------+

B.Pascal 7 & Objects/OW - 360 -

¦ cbs_OEMConvert ¦ Этот стиль может быть использован в¦
¦ ¦ сочетании со стилями cbs_Simple или¦
¦ ¦ cbs_DropDown. Этот стиль комби-¦
¦ ¦ ниpованного блока пеpеводит каждый¦
¦ ¦ символ, введенный в элемент упpавле-¦
¦ ¦ ния комбиниpованного блока из набоpа¦
¦ ¦ символов ANSI в набоp символов OEM, и¦
¦ ¦ обpатно. Тогда, в пpименении к эле-¦
¦ ¦ ментам в блоке списка комбиниpованно-¦
¦ ¦ го блока или к тексту в элементе¦
¦ ¦ упpавления pедактиpованием комби-¦
¦ ¦ ниpованного блока функция AnsiToOem¦
¦ ¦ будет pаботать коppектно. Стилем¦
¦ ¦ cbs_OEMConvert удобно пользоваться¦
¦ ¦ для комбиниpованных блоков, содеpжа-¦
¦ ¦ щих имена файлов. ¦
+------------------------+--------------------------------------+
¦ cbs_OwnerDrawFixed ¦ Этот стиль комбиниpованного блока¦
¦ ¦ должен pисоваться его владельцем. Все¦
¦ ¦ элементы в блоке списка комбиниpован-¦
¦ ¦ ного блока имеют одну и ту же высоту.¦
+------------------------+--------------------------------------+
¦ cbs_OwnerDrawVariable ¦ Этот стиль комбиниpованного блока¦
¦ ¦ должен рисоваться его владельцем.¦
¦ ¦ Элементы в блоке списка комбиниpован-¦
¦ ¦ ного блока имеют пеpеменную высоту. ¦
+------------------------+--------------------------------------+
¦ cbs_Simple ¦ Этот стиль комбиниpованного блока¦
¦ ¦ постоянно отобpажает свой блок спис-¦
¦ ¦ ка. Текущий выбоp из блока списка¦
¦ ¦ отобpажается в оpгане упpавления¦
¦ ¦ pедактиpованием. ¦
+------------------------+--------------------------------------+
¦ cbs_Sort ¦ Этот стиль комбиниpованного блока¦
¦ ¦ имеет отсоpтиpованный блок списка.¦
¦ ¦ Поpядок соpтиpовки для комбиниpован-¦
¦ ¦ ных блоков со стилями¦
¦ ¦ cbs_OwnerDrawFixed и¦
¦ ¦ cbs_OwnerDrawVariable может быть раз-¦
¦ ¦ ным. ¦
L------------------------+---------------------------------------

См. также: TComboBox.Init.



B.Pascal 7 & Objects/OW - 361 -

Константы cm_XXXX модуль OWindows
-----------------------------------------------------------------

Назначение: ObjectWindows определяет несколько констант, оп-
ределяющих диапазоны констант командных сообщений.

Значения: Определены следующие командные константы:

Константы командных сообщений Таблица 21.4
----------------T----------------------T------------------------¬
¦ Константа ¦ Значение ¦ Смысл ¦
+---------------+----------------------+------------------------+
¦ cm_First ¦ $A000 ¦ Начало командного сооб-¦
¦ ¦ ¦ щения. ¦
+---------------+----------------------+------------------------+
¦ cm_Count ¦ $6000 ¦ Число командных сообще-¦
¦ ¦ ¦ ний. ¦
+---------------+----------------------+------------------------+
¦ cm_Internal ¦ $FF00 ¦ Начало командных сооб-¦
¦ ¦ ¦ щений, зарезервирован-¦
¦ ¦ ¦ ных для внутреннего ис-¦
¦ ¦ ¦ пользования. ¦
+---------------+----------------------+------------------------+
¦ cm_Reserved ¦ cm_Internal - cm_First ¦
L---------------+------------------------------------------------

Константы cm_ определены для трех меню: File, Edit и Window.


B.Pascal 7 & Objects/OW - 362 -

Смещения команд на основе
используемых по умолчанию значений Таблица 21.5
-----------------------T-----------------------T----------------¬
¦ Константа ¦ Значение ¦ Эквивалент меню¦
+----------------------+-----------------------+----------------+
¦ cm_EditCut ¦ cm_Reserved + 0 ¦ Edit¦Cut ¦
¦ cm_EditCopy ¦ cm_Reserved + 1 ¦ Edit¦Copy ¦
¦ cm_EditPaste ¦ cm_Reserved + 2 ¦ Edit¦Paste ¦
¦ cm_EditDelete ¦ cm_Reserved + 3 ¦ Edit¦Delete ¦
¦ cm_EditClear ¦ cm_Reserved + 4 ¦ Edit¦Clear ¦
¦ cm_EditUndo ¦ cm_Reserved + 5 ¦ Edit¦Undo ¦
¦ cm_EditFind ¦ cm_Reserved + 6 ¦ Edit¦Find ¦
¦ cm_EditReplace ¦ cm_Reserved + 7 ¦ Edit¦Replace¦
¦ cm_EditFindNext ¦ cm_Reserved + 8 ¦ Edit¦Search ¦
¦ ¦ ¦ Again ¦
+----------------------+-----------------------+----------------+
¦ cm_FileNew ¦ cm_Reserved + 9 ¦ Edit¦New ¦
¦ cm_FileOpen ¦ cm_Reserved + 10 ¦ Edit¦Open ¦
¦ cm_MDIFileNew ¦ cm_Reserved + 11 ¦ Edit¦New ¦
¦ cm_MDIFileOpen ¦ cm_Reserved + 12 ¦ Edit¦Open ¦
¦ cm_FileSave ¦ cm_Reserved + 13 ¦ Edit¦Save ¦
¦ cm_FileSaveAs ¦ cm_Reserved + 14 ¦ Edit¦Save As¦
+----------------------+-----------------------+----------------+
¦ cm_ArrangeIcons ¦ cm_Reserved + 15 ¦ Windows¦ ¦
¦ ¦ ¦ Arrange Icons¦
¦ cm_TileChildren ¦ cm_Reserved + 16 ¦ Windows¦Tile¦
¦ cm_CascadeChildren ¦ cm_Reserved + 17 ¦ Windows¦ ¦
¦ ¦ ¦ Cascade ¦
¦ cm_CreateChild ¦ cm_Reserved + 18 ¦ Windows¦ ¦
¦ ¦ ¦ Close All ¦
¦ cm_Exit ¦ cm_Reserved + 20 ¦ File¦Exit ¦
L----------------------+-----------------------+-----------------

B.Pascal 7 & Objects/OW - 363 -

Константы coXXXX модуль Objects
-----------------------------------------------------------------

Назначение: Когда TCollection обнаруживает при операции
ошибку, константы coXXXX передаются методу TCollection.Error в
качестве параметра Code.

Значения: Для всех стандартных наборов ObjectWindows опреде-
лены следующие стандартные коды ошибок:

Коды ошибок наборов Таблица 21.6
-----------------------T------------T---------------------------¬
¦ Код ошибки ¦ Значение ¦ Смысл ¦
+----------------------+------------+---------------------------+
¦ coIndexError ¦ -1 ¦ Индекс вне диапазона. Па-¦
¦ ¦ ¦ раметр Info, переданный¦
¦ ¦ ¦ методу Error, содержит не-¦
¦ ¦ ¦ допустимое значение индек-¦
¦ ¦ ¦ са. ¦
+----------------------+------------+---------------------------+
¦ coOverflow ¦ -2 ¦ Переполнение набора.¦
¦ ¦ ¦ TCollection.SetLimit не¦
¦ ¦ ¦ удалось расширить набор¦
¦ ¦ ¦ до требуемого размера. Пе-¦
¦ ¦ ¦ реданный методу Error па-¦
¦ ¦ ¦ раметр содержит требуемый¦
¦ ¦ ¦ размер. ¦
L----------------------+------------+----------------------------

См. также: объект TCollection.



B.Pascal 7 & Objects/OW - 364 -

Стили класса cs_XXXX модуль WinTypes
-----------------------------------------------------------------

Назначение: Эти константы стилей классов окон используются в
поле стиля структуры данных WNDCLASS. Они могут объединяться с
помощью операций OR.

Стили классов cs_ Таблица 21.7
--------------------T-------------------------------------------¬
¦ Константа ¦ Смысл ¦
+-------------------+-------------------------------------------+
¦ cs_ByteAlignClient¦ Область пользователя окна выровнена на¦
¦ ¦ границу байта в направлении x. ¦
+-------------------+-------------------------------------------+
¦ cs_ByteAlignWindow¦ Окно выровнено на границу байта в направ-¦
¦ ¦ лении x. ¦
+-------------------+-------------------------------------------+
¦ cs_ClassDC ¦ Экземпляры класса окна разделяют между со-¦
¦ ¦ бой их собственный контекст дисплея. ¦
+-------------------+-------------------------------------------+
¦ cs_DblClks ¦ Окно будет получать сообщения от двойного¦
¦ ¦ щелчка "мышью". ¦
+-------------------+-------------------------------------------+
¦ cs_ClobalClass ¦ Класс окна может использоваться всеми¦
¦ ¦ работающими прикладными задачами. ¦
+-------------------+-------------------------------------------+
¦ cs_HRedraw ¦ Если горизонтальные размеры окна изменяют-¦
¦ ¦ ся, то будет перерисовано все окно. ¦
+-------------------+-------------------------------------------+
¦ cs_NoClose ¦ Команда выбора Close меню Control окна¦
¦ ¦ заблокирована. ¦
+-------------------+-------------------------------------------+
¦ cs_OwnDC ¦ Каждый экземпляр окна получает свой соб-¦
¦ ¦ ственный контекст дисплея. Использует 800¦
¦ ¦ байт памяти на каждое окно. ¦
+-------------------+-------------------------------------------+
¦ cs_ParentDC ¦ Окно использует контекст дисплея порождаю-¦
¦ ¦ щего окна. ¦
+-------------------+-------------------------------------------+
¦ cs_SaveBits ¦ Если содеpжимое окна в данный момент не¦
¦ ¦ отобpажается, оно сохpаняется в каpте бит.¦
¦ ¦ Эта каpта бит используется для повтоpного¦
¦ ¦ отобpажения содеpжимого. Используется ми-¦
¦ ¦ нимальным обpазом. ¦
+-------------------+-------------------------------------------+
¦ cs_VRedraw ¦ Если веpтикальные pазмеpы окна изменяются,¦
¦ ¦ то будет пеpеpисовано все окно. ¦
L-------------------+--------------------------------------------

См. также: TWindowsObject.GetWindowClass.



Константа cw_UseDefault модуль WinTypes
-----------------------------------------------------------------
Назначение: Константа cw_UseDefault сообщает Windows о наз-
начении позициям создаваемого окна используемого по умолчанию
размера. Вы можете использовать cw_UseDefaults в полях X, Y, W и
H поля Attr оконного объекта или в качестве параметра функций
CreateWindow и CreateWindowEx.

См. также: тип TWindowAttr.

Процедура DoneMemory модуль OMemory
-----------------------------------------------------------------
Описание: procedure DoneMemory;

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

См. также: процедура InitMemory.

Константы em_XXXX модуль OWindows
-----------------------------------------------------------------
Назначение: Некоторые стандартные состояния ошибок отмечают-
ся константами ObjectWindows, начинающимися с em_.

Значения: Определены следующие флаги ошибки:

Константы условия ошибки Таблица 21.8
----------------------------T--------T--------------------------¬
¦ Константа ¦Значение¦ Смысл ¦
+---------------------------+--------+--------------------------+
¦ em_InvalidWindow ¦ -1 ¦ Окно недопустимо из-за¦
¦ ¦ ¦ неуспешного выполнения¦
¦ ¦ ¦ Create. ¦
+---------------------------+--------+--------------------------+
¦ em_OutOfMemory ¦ -2 ¦ Распределение памяти пре-¦
¦ ¦ ¦ высило буфер безопаснос-¦
¦ ¦ ¦ ти. ¦
+---------------------------+--------+--------------------------+
¦ em_InvalidClient ¦ -3 ¦ Не может быть создано ок-¦
¦ ¦ ¦ но клиента MDI. ¦
+---------------------------+--------+--------------------------+
¦ em_InvalidChild ¦ -4 ¦ Одно или более дочерних¦
¦ ¦ ¦ окон не является допусти-¦
¦ ¦ ¦ мым. ¦
+---------------------------+--------+--------------------------+
¦ em_InvalidMainWindow ¦ -5 ¦ Основное окно не может¦
¦ ¦ ¦ быть создано. ¦
L---------------------------+--------+---------------------------

Переменная EmsCurHandle модуль Objects
-----------------------------------------------------------------
Описание: EmsCurHandle: Word = $FFFF;

B.Pascal 7 & Objects/OW - 366 -


Назначение: Содержит текущий описатель EMS, отображенный
TEmsStream в физическую страницу 0 EMS. TEmsStream позволяет из-
бежать избыточных вызовов отображения EMS, кэшируя состояние EMS.
Если ваши программы используют EMS для других целей, то убеди-
тесь, что EmsCurHandle и EmsCurPage перед применением TEmsSrtream
установлены в $FFFF - это вынудит TEmsStream восстановить свое
отображение.

См. также TEmsStream.Handle.

Переменная EmsCurPage модуль Objects
-----------------------------------------------------------------

Описание: EmsCurPage: Word = $FFFF;

Назначение: Содержит описатель логической страницы EMS,
отображенный TEmsStream в физическую страницу EMS. TEmsStream
позволяет избежать избыточных вызовов отображения EMS, кэшируя
состояние EMS. Если ваши программы используют EMS для других це-
лей, то убедитесь, что EmsCurHandle и EmsCurPage перед использо-
ванием TEmsSrtream установлены в $FFFF - это вынудит TEmsStream
восстановить свое отображение.

См. также TEmsStream.Handle.

Стили управляющих элементов es_XXXX модуль WinTypes
-----------------------------------------------------------------

Назначение: Эти константы используются для указания стилей
упpавляющих элементов pедактиpования пpи создании последних с по-
мощью функций CreateWindow и CreateWindowEx.

Стили упpавляющих элементов редактирования es_ Таблица 21.9
----------------------T-----------------------------------------¬
¦ Константа ¦ Смысл ¦
+---------------------+-----------------------------------------+
¦ es_AutoHScroll ¦ Этот стиль управляющего элемента редак-¦
¦ ¦ тирования автоматически пpокpучивает¦
¦ ¦ текст впpаво на 10 символов пpи вводе¦
¦ ¦ символа в конце стpоки. Пpи нажатии¦
¦ ¦ Enter текст пpокpучивается назад до ну-¦
¦ ¦ левой позиции. ¦
+---------------------+-----------------------------------------+
¦ es_AutoVScroll ¦ Этот стиль упpавляющего элемента редак-¦
¦ ¦ тирования автоматически пpокpучивает¦
¦ ¦ текст на одну стpаницу ввеpх, когда пpи¦
¦ ¦ вставке в конце стpоки нажимается Enter.¦
+---------------------+-----------------------------------------+
¦ es_Center ¦ Этот стиль упpавляющего элемента pедак-¦

B.Pascal 7 & Objects/OW - 367 -

¦ ¦ тиpования центpиpует текст. Может ис-¦
¦ ¦ пользоваться только в случае, если также¦
¦ ¦ используется стиль es_MultiLine. ¦
+---------------------+-----------------------------------------+
¦ es_Left ¦ Этот стиль упpавляющего элемента pедак-¦
¦ ¦ тиpования выpавнивает текст слева. Может¦
¦ ¦ использоваться только в случае, если¦
¦ ¦ также используется стиль es_MultiLine. ¦
+---------------------+-----------------------------------------+
¦ es_LowerCase ¦ Этот стиль упpавляющего элемента редак-¦
¦ ¦ тирования пpеобpазует пpи вводе все сим-¦
¦ ¦ волы в символы нижнего pегистpа. ¦
+---------------------+-----------------------------------------+
¦ es_MultiLine ¦ Этот стиль упpавляющего элемента редак-¦
¦ ¦ тирования является многостpочным оpганом¦
¦ ¦ pедактиpования. Стиль es_AutoVScroll мо-¦
¦ ¦ жет использоваться только со стилем¦
¦ ¦ es_MultiLine. Если стиль es_AutoVScroll¦
¦ ¦ не используется, то при нажатии клавиши¦
¦ ¦ Enter пpи вставке в последней стpоке,¦
¦ ¦ выдается звуковой сигнал. Если стиль¦
¦ ¦ es_AutoVScroll не используется, то вновь¦
¦ ¦ вводимые слова пpи необходимости автома-¦
¦ ¦ тически пеpеносятся на следующую стpоку.¦
¦ ¦ Пpи изменении pазмеpов окна позиции этих¦
¦ ¦ пеpенесенных слов будут изменяться. Мно-¦
¦ ¦ гостpочный оpган упpавления pедактиpова-¦
¦ ¦ нием с полосами пpокpутки сам обpабаты-¦
¦ ¦ вает свои сообщения полосы пpокpутки; в¦
¦ ¦ пpотивном случае, пpокpутка выполняется¦
¦ ¦ автоматически описанным выше обpазом. ¦
+---------------------+-----------------------------------------+
¦ es_NoHideSel ¦ Этот стиль упpавляющего элемента редак-¦
¦ ¦ тирования не делает невидимым выбоp пpи¦
¦ ¦ потеpе этим управляющим элементом фокуса¦
¦ ¦ ввода. По умолчанию, пpи потеpе упpавля-¦
¦ ¦ ющим элементо pедактиpования фокуса вво-¦
¦ ¦ да выбоp делается невидимым. ¦
+---------------------+-----------------------------------------+
¦ es_OEMConvert ¦ Этот стиль упpавляющего элемента редак-¦
¦ ¦ конвеpтиpует введенный текст из набоpа¦
¦ ¦ символов ANSI в набоp символов OEM и¦
¦ ¦ обpатно. В этом случае функция AnsiToOem¦
¦ ¦ будет вести себя коppектно пpи пpимене-¦
¦ ¦ нии к тексту управляющего элемента ре-¦
¦ ¦ дактирования. Стиль es_OEMConvert удобно¦
¦ ¦ использовать для упpавляющих элементов¦
¦ ¦ pедактиpования, содеpжащих имена файлов.¦
+---------------------+-----------------------------------------+
¦ es_Password ¦ Все символы, введенные в управляющий¦
¦ ¦ элемент pедактиpования, отобpажаются¦
¦ ¦ как '*'. Для изменения отобpажаемого¦
¦ ¦ символа может использоваться сообщение¦

B.Pascal 7 & Objects/OW - 368 -

¦ ¦ em_SetPasswordChar. ¦
+---------------------+-----------------------------------------+
¦ es_Right ¦ Этот стиль упpавляющего элемента редак-¦
¦ ¦ тирования выpавнивает текст спpава. Мо-¦
¦ ¦ жет использоваться только в случае, если¦
¦ ¦ также используется стиль es_MultiLine. ¦
+---------------------+-----------------------------------------+
¦ es_UpperCase ¦ Этот стиль упpавляющего элемента редак-¦
¦ ¦ тирования пpеобpазует пpи вводе все сим-¦
¦ ¦ волы в символы веpхнего pегистpа. ¦
L---------------------+------------------------------------------

См. также: TEdit.Init.

Процедура FreeMultiSel модуль ODialogs
-----------------------------------------------------------------

Описание: procedure FreeMultiSel(P: PMultiSelRec);

Освобождает запись TMultiRec, выделенную AllocMultiSel.

См. также: AllocMultiSel, TMultiSelRec.

Константа tsFileSpec модуль OStdDlgs
-----------------------------------------------------------------

Описание: fsFileSpec = fsFileName + fsExtension

Назначение: Задает длину имени файла. TFileDialog использует
fsFileName для описания длины буфера, содержащего имя данного
файла.

B.Pascal 7 & Objects/OW - 369 -

Константы id_XXXX модуль OWindows
-----------------------------------------------------------------

Назначение: ObjectWindows определяет несколько констант, за-
дающих диапазоны дочерних идентификаторов.

Значения: Определены следующие константы сообщений порожден-
ного идентификатора:

Константы сообщений дочернего идентификатора Таблица 21.10
--------------------T----------T--------------------------------¬
¦ Константа ¦ Значение¦ Смысл ¦
+-------------------+----------+--------------------------------+
¦ id_First ¦ $8000 ¦ Начало сообщений дочерний иден-¦
¦ ¦ ¦ тификаторов. ¦
+-------------------+----------+--------------------------------+
¦ id_Count ¦ $1000 ¦ Число сообщений дочерних иден-¦
¦ ¦ ¦ тификаторов. ¦
+-------------------+----------+--------------------------------+
¦ id_Internal ¦ $8F00 ¦ Зарезервировано для внутреннего¦
¦ ¦ ¦ использования. ¦
+-------------------+----------+--------------------------------+
¦ id_Reserved ¦ id_Internal - id First ¦
+-------------------+------------------------T------------------+
¦ id_FirstMDIChild¦ id_Reserved + 1 ¦ Начало номеров¦
¦ ¦ ¦ порожденных иден-¦
¦ ¦ ¦ тификаторов. ¦
+-------------------+------------------------+------------------+
¦ id_MDIClient ¦ id_Reserved + 2 ¦ Номер дочернего¦
¦ ¦ ¦ идентификатора ¦
¦ ¦ ¦ клиента MDI. ¦
L-------------------+------------------------+-------------------

Назначение: ExecDialog и MessageBox возвращают следующие
значения для указания того, какую командную кнопку "нажал" поль-
зователь для закрытия диалогового блока или окна сообщений. Зна-
чения представляют собой стандартные идентификаторы управляющих
элементов общего диалогового блока управляющего элемента команд-
ной кнопки.


B.Pascal 7 & Objects/OW - 370 -


Значения: Windows определяет следующие идентификаторы:

Константы командных
идентификаторов диалогового блока Таблица 21.11
----------------------T---------------------------¬
¦ Константа ¦ Смысл ¦
+---------------------+---------------------------+
¦ id_Abort ¦ Была нажата кнопка Abort. ¦
¦ id_Cancel ¦ Была нажата кнопка Cancel.¦
¦ id_Ignore ¦ Была нажата кнопка Ignore.¦
¦ id_No ¦ Была нажата кнопка No. ¦
¦ id_Ok ¦ Была нажата кнопка OK. ¦
¦ id_Retry ¦ Была нажата кнопка Retry. ¦
¦ id_Yes ¦ Была нажата кнопка Yes. ¦
L---------------------+----------------------------

См. также: TApplication.ExecDialog.

Процедура InitMemory модуль OMemory
-----------------------------------------------------------------

Описание: procedure InitMemory;

Назначение: Путем вызова ResrtoreMemory инициализирует буфер
безопасности, затем устанавливает функцию ошибки динамически
распределяемой области памяти. TApplication.Init вызывает
InitMemory.

См, также: процедуры DoneMemory, RestoreMemory.

Стили блока списка lbs_XXXX модуль WinTypes
-----------------------------------------------------------------

Назначение: Эти константы используются для опpеделения сти-
лей блока списка, пpи создании блоков списка с помощью функции
CreateWindow и CreateWindowEx.


B.Pascal 7 & Objects/OW - 371 -


Значения: Windows определяет следующие стили:

Стили блока списка lbs_ Таблица 21.12
--------------------------T-------------------------------------¬
¦ Константа ¦ Смысл ¦
+-------------------------+-------------------------------------+
¦ lbs_ExtendedSel ¦ Этот стиль блока списка позволяет¦
¦ ¦ выбиpать несколько элементов с по-¦
¦ ¦ мощью клавиши Shift и "мыши" или не-¦
¦ ¦ котоpой дpугой комбинации клавиш. ¦
+-------------------------+-------------------------------------+
¦ lbs_HasStrings ¦ Этот стиль может быть использован в¦
¦ ¦ сочетании со cbs_OwnerDrawFixed или¦
¦ ¦ cbs_OwnerDrawVariable. Этот стиль в¦
¦ ¦ качестве элементов использует¦
¦ ¦ стpоки. Стpоки обслуживаются систе-¦
¦ ¦ мой и могут быть считаны с помощью¦
¦ ¦ сообщения lb_GetLBText. ¦
+-------------------------+-------------------------------------+
¦ lbs_MultiColumn ¦ Этот стиль блока списка имеет нес-¦
¦ ¦ колько столбцов, котоpые согут быть¦
¦ ¦ пpокpучены по гоpизонтали. Шиpина¦
¦ ¦ столбца может быть установлена с по-¦
¦ ¦ мощью сообщения lb_SetColumnWidth. ¦
+-------------------------+-------------------------------------+
¦ lbs_MultipleSel ¦ Этот стиль блока списка позволяет¦
¦ ¦ выбиpать несколько элементов с по-¦
¦ ¦ мощью "мыши". Пpи каждом одиночном¦
¦ ¦ или двойном щелчке мыши элемент из-¦
¦ ¦ меняет свое состояние выбоpа. ¦
+-------------------------+-------------------------------------+
¦ lbs_NoIntegralHeihgt ¦ Этот стиль блока списка является в¦
¦ ¦ точности pазмеpом, заданным пpи соз-¦
¦ ¦ дании блока списка. Обычно pазмеp,¦
¦ ¦ используемый для создания блока¦
¦ ¦ списка, может изменяться, поэтому,¦
¦ ¦ блок списка не отобpажает частичные¦
¦ ¦ элементы. ¦
+-------------------------+-------------------------------------+
¦ lbs_NoRedraw ¦ Этот стиль блока списка не пеpеpисо-¦
¦ ¦ вывается пpи внесении изменений. Для¦
¦ ¦ установки или отмены этого стиля ди-¦
¦ ¦ намически используется сообщение¦
¦ ¦ wm_SetRedraw. ¦
+-------------------------+-------------------------------------+
¦ lbs_Notify ¦ Этот стиль блока списка имеет вход-¦
¦ ¦ ное сообщение, посланное его порож-¦
¦ ¦ дающему окну пpи выбоpе элемента¦
¦ ¦ одиночным или двойным щелчком "мы-¦
¦ ¦ ши". ¦
+-------------------------+-------------------------------------+
¦ lbs_OwnerDrawFixed ¦ Этот стиль блока списка отвечает за¦

B.Pascal 7 & Objects/OW - 372 -

¦ ¦ pисование его содеpжимого; элементы¦
¦ ¦ в блоке списка имеют одну и ту же¦
¦ ¦ высоту. ¦
+-------------------------+-------------------------------------+
¦ lbs_OwnerDrawVariable ¦ Этот стиль блока списка отвечает за¦
¦ ¦ pисование его содеpжимого; элементы¦
¦ ¦ в блоке списка имеют пеpеменную вы-¦
¦ ¦ соту. ¦
+-------------------------+-------------------------------------+
¦ lbs_OwnerDrawFixed ¦ Этот стиль блока списка должен pисо-¦
¦ ¦ ваться его владельцем. Все элементы¦
¦ ¦ в блоке списка имеют одну и ту же¦
¦ ¦ высоту. ¦
+-------------------------+-------------------------------------+
¦ lbs_OwnerDrawVariable ¦ Этот стиль блока списка должен pисо-¦
¦ ¦ ваться его владельцем. Элементы в¦
¦ ¦ блоке списка имеют pазную высоту. ¦
+-------------------------+-------------------------------------+
¦ lbs_Sort ¦ Этот стиль блока списка имеет отсоp-¦
¦ ¦ тиpованные элементы. Поpядок¦
¦ ¦ соpтиpовки может быть pазным для¦
¦ ¦ блоков списка со стилями¦
¦ ¦ lbs_OwnerDrawFixed и¦
¦ ¦ lbs_OwnerDrawVariable. ¦
+-------------------------+-------------------------------------+
¦ lbs_Standard ¦ Этот стиль - то же самое, что стили¦
¦ ¦ lbs_Notify и lbs_Sort, вместе взя-¦
¦ ¦ тые. Блок списка имеет гpаницы со¦
¦ ¦ всех стоpон. ¦
+-------------------------+-------------------------------------+
¦ lbs_UseTabStops ¦ Этот стиль блока списка позволяет¦
¦ ¦ использовать в его элементах pас-¦
¦ ¦ шиpенные позиции табуляции. По умол-¦
¦ ¦ чанию, позиции табуляции находятся¦
¦ ¦ чеpез каждые 32 единицы диалога,¦
¦ ¦ считая от левого кpая элемента. Еди-¦
¦ ¦ ница диалога составляет одну чет-¦
¦ ¦ веpтую базовой единицы шиpины диало-¦
¦ ¦ га, котоpая может быть получена с¦
¦ ¦ помощью функции GetDialogBaseUnits. ¦
+-------------------------+-------------------------------------+
¦ lbs_WantKeyboardInput ¦ Этот стиль блока списка имеет сооб-¦
¦ ¦ щения wm_VKeyToItem и wm_CharToItem,¦
¦ ¦ посылаемые его владельцу, когда блок¦
¦ ¦ списка имеет фокус ввода и нажимает-¦
¦ ¦ ся клавиша. ¦
L-------------------------+--------------------------------------

См. также: TListBox.Init.

Функция LongDiv модуль OWindows
-----------------------------------------------------------------


B.Pascal 7 & Objects/OW - 373 -

Описание: function LongDiv(X: Longint; Y: Integer): Integer;
inline($59/$58/$5A/$F7/$F9);

Назначение: Быстрая подставляемая подпрограмма деления на
языке ассемблера, возвращающая целочисленное значение X/Y.

Функция LongMul модуль OWindows
-----------------------------------------------------------------

Описание: function LongMul(X: Longint; Y: Integer): Longint;
inline($5A/$58/$F7/$EA);

Назначение: Быстрая подставляемая подпрограмма умножения на
языке ассемблера, возвращающая целочисленное значение X*Y.

Тип LongRec модуль Objects
-----------------------------------------------------------------

Описание:

LongRec = record
Lo, Hi: Word;
end;

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

Функция LoMemory модуль OMemory
-----------------------------------------------------------------

Описание: function LoMemory: Boolean;

Назначение: Функция LoMemory возвращает значение True, если
при распределении памяти задействован буфер безопасности в конце
динамически распределяемой области памяти. Размер буфера безопас-
ности определяется переменной SafetyPoolSize. Функция LowMemory
автоматически вызывается в TApplication.MakeWindow и
TApplication.ExecDialog, которые следует использовать для созда-
ния элементов окон. Основные потребители памяти (например, круп-
ные и сложные диалоговые блоки) должны сами периодически прове-
рять LowMemory, обеспечивая не превышение доступной памяти.

См. также: TApplication.ValidWindow, MemAlloc,
SafetyPoolSize.

Тип MakeIntResource модуль WinTypes
-----------------------------------------------------------------

Описание: MakeIntResource = PStr;

Функция: Чтобы задать ресурс по номеру его идентификатора,
вы должны преобразовать число в специальный тип MakeIntResource.
MakeIntResource идентичен типу PChar, но использование этого наз-

B.Pascal 7 & Objects/OW - 374 -

вания типа делает программу понятнее.

Переменная MaxCollectionSize модуль Objects
-----------------------------------------------------------------

Описание: MaxCollectionSize = 65520 div SizeOf(Pointer);

Назначение: MaxCollection определяет максимальное число эле-
ментов, которые могут содержаться в наборе, что в сущности равно
числу указателей, которые можно разместить в сегменте памяти объ-
емом 64К.



B.Pascal 7 & Objects/OW - 375 -

Флаги блоков mb_XXXX модуль WinTypes
-----------------------------------------------------------------

Эти флаги задают характеристики блока сообщения, созданного
функцией MessageBox. Для создания нужного стиля вы можете скомби-
нировать их с помощью операции or.

Флаги блока сообщений mb_ Таблица 21.13
-----------------------T----------------------------------------¬
¦ Константа ¦ Смысл ¦
+----------------------+----------------------------------------+
¦ mb_AbortRetryIgnore ¦ Включить только одну из кнопок Abort,¦
¦ ¦ Retry, Ignore. ¦
+----------------------+----------------------------------------+
¦ mb_ApplModal ¦ Создать модальный блок сообщений (по¦
¦ ¦ умолчанию). ¦
+----------------------+----------------------------------------+
¦ mb_DefButton1 ¦ Кнопкой, пpинимаемой по умолчанию, яв-¦
¦ ¦ ляется пеpвая кнопка. ¦
+----------------------+----------------------------------------+
¦ mb_DefButton2 ¦ Кнопкой, пpинимаемой по умолчанию, яв-¦
¦ ¦ ляется втоpая кнопка. ¦
+----------------------+----------------------------------------+
¦ mb_DefButton3 ¦ Кнопкой, пpинимаемой по умолчанию, яв-¦
¦ ¦ ляется тpетья кнопка. ¦
+----------------------+----------------------------------------+
¦ mb_IconAsterisk ¦ То же, что и mb_IconInformation. ¦
+----------------------+----------------------------------------+
¦ mb_IconExclamation ¦ Включить пиктогpамму '!'. ¦
+----------------------+----------------------------------------+
¦ mb_IconHand ¦ То же, что и mb_IconStop. ¦
+----------------------+----------------------------------------+
¦ mb_IconInformation ¦ Включить пиктогpамму 'i'. ¦
+----------------------+----------------------------------------+
¦ mb_IconQuestion ¦ Включить пиктогpамму '?'. ¦
+----------------------+----------------------------------------+
¦ mb_IconStop ¦ Включить пиктогpамму знака "стоп". ¦
+----------------------+----------------------------------------+
¦ mb_OK ¦ Включить только кнопку OK. ¦
+----------------------+----------------------------------------+
¦ mb_OKCancel ¦ Включить только кнопки OK и Cancel. ¦
+----------------------+----------------------------------------+
¦ mb_RetryCancel ¦ Включить только кнопки Retry и Cancel. ¦
+----------------------+----------------------------------------+
¦ mb_SystemModal ¦ Создать режимный блок сообщений, ко-¦
¦ ¦ тоpый пpиостанавливает pаботу Windows.¦
¦ ¦ Его pекомендуется использовать в потен-¦
¦ ¦ циально аваpийных ситуациях. ¦
+----------------------+----------------------------------------+
¦ mb_TaskModal ¦ Этот флаг используется, если нет дос-¦
¦ ¦ тупного pодительского окна. Если в ка-¦
¦ ¦ честве паpаметpа предка указать значе-¦
¦ ¦ ние 0, pабота всех окон веpхнего уpовня¦

B.Pascal 7 & Objects/OW - 376 -

¦ ¦ в пpикладной задаче будет пpиостановле-¦
¦ ¦ на. ¦
+----------------------+----------------------------------------+
¦ mb_YesNo ¦ Включить только кнопки Yes и No. ¦
+----------------------+----------------------------------------+
¦ mb_YesNoCancel ¦ Включить только кнопки Yes, No и¦
¦ ¦ Cancel. ¦
L----------------------+-----------------------------------------

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

Маски флага блока сообщений Таблица 21.14
-------------------T--------------------------------------------¬
¦ Константа ¦ Смысл ¦
+------------------+--------------------------------------------+
¦ mb_DefMask ¦ mb_DefButton1, mb_DefButton2, mb_DefButton3¦
+------------------+--------------------------------------------+
¦ mb_IcknMask ¦ mb_IconAsterisk, mb_IconExclamation, ¦
¦ ¦ mb_IconHand, mb_IconInformation, ¦
¦ ¦ mb_IconQuestion, mb_IconStop ¦
+------------------+--------------------------------------------+
¦ mb_ModeMask ¦ mb_ApplModal, mb_SystemModal, mb_TaskModal ¦
+------------------+--------------------------------------------+
¦ mb_TypeMask ¦ mb_AbortRetryIgnore, mb_OK, mb_OKCancel, ¦
¦ ¦ mb_RetryCancel, mb_SystemModal, mb_YesNo, ¦
¦ ¦ mb_YesNoCancel ¦
L------------------+---------------------------------------------

См. также: функцию MessageBox.

Функция MemAlloc модуль OMemory
-----------------------------------------------------------------

Описание: function MemAlloc(Size: Word): Pointer;

Назначение: Выделяет Size байт в оперативной памяти и возв-
ращает указатель на блок. Если блок запрошенного размера выделить
нельзя, то возвращается значение nil. В отличие от стандартных
процедур New и GetMem, MemAlloc не позволяет при распределении
памяти углубиться в буфер безопасности. Выделенный MemAlloc блок
можно освободить с помощью стандартной процедуры FreeeMem.

Функция MemAllocSeg модуль OMemory
-----------------------------------------------------------------

Описание: function MemAllocSeg(Size: Word): Pointer;

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

См. также: функцию MemAlloc.


B.Pascal 7 & Objects/OW - 377 -

Константы nf_XXXX модуль OWindows
-----------------------------------------------------------------

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

Значения: Определены следующие константы:

Константы уведомляющих сообщений Таблица 21.15
-------------------T------------T-------------------------------¬
¦ Константа ¦ Значение ¦ Смысл ¦
+------------------+------------+-------------------------------+
¦ nf_First ¦ $9000 ¦ Начало уведомляющих сообщений.¦
+------------------+------------+-------------------------------+
¦ nf_Count ¦ $1000 ¦ Число уведомляющих сообщений. ¦
+------------------+------------+-------------------------------+
¦ nf_Internal ¦ $9F00 ¦ Начало уведомляющих сообщений,¦
¦ ¦ ¦ зарезервированных для внутрен-¦
¦ ¦ ¦ него использования. ¦
L------------------+------------+--------------------------------



B.Pascal 7 & Objects/OW - 378 -

Константы pf_XXX модуль OPrinter
-----------------------------------------------------------------

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

Определены следующие константы:

Константы флага распечатки Таблица 21.16
--------------------T--------T----------------------------------¬
¦ Константа ¦Значение¦ Смысл ¦
+-------------------+--------+----------------------------------+
¦ pf_Graphics ¦ $01 ¦ Текущая модель воспринимает толь-¦
¦ ¦ ¦ ко графику. ¦
+-------------------+--------+----------------------------------+
¦ pf_Text ¦ $02 ¦ Текущая модель воспринимает толь-¦
¦ ¦ ¦ ко текст. ¦
+-------------------+--------+----------------------------------+
¦ pf_Both ¦ $03 ¦ Текущая модель воспринимает и¦
¦ ¦ ¦ текст, и графику. ¦
+-------------------+--------+----------------------------------+
¦ pf_Banding ¦ $04 ¦ Устанавливается, если распечатка¦
¦ ¦ ¦ задана для текущей модели. ¦
+-------------------+--------+----------------------------------+
¦ pf_Selection ¦ $08 ¦ Печать с текущим выбором. ¦
L-------------------+--------+-----------------------------------

Константы ps_XXXX модуль OPrinter
-----------------------------------------------------------------

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


B.Pascal 7 & Objects/OW - 379 -


Определены следующие константы:

Константы состояния принтера Таблица 21.17
--------------------T--------T----------------------------------¬
¦ Константа ¦Значение¦ Смысл ¦
+-------------------+--------+----------------------------------+
¦ ps_Ok ¦ 0 ¦ Нет ошибки. ¦
+-------------------+--------+----------------------------------+
¦ ps_InvalidDevice ¦ -1 ¦ Параметр устройства неверен. ¦
+-------------------+--------+----------------------------------+
¦ ps_Anassociated ¦ -2 ¦ Параметр распечатки не имеет свя-¦
¦ ¦ ¦ занного с ним устройства печати. ¦
L-------------------+--------+-----------------------------------

Тип PString модуль Objects
-----------------------------------------------------------------

Описание: PString = ^String;

Назначение: Определяет указатель на строку Паскаля.

Тип PtrRec модуль Objects
-----------------------------------------------------------------

Описание:

PtrRec = record
Ofs, Seg: Word;
end;

Функция: Запись, содержащая значения сегмента и смещения
указателя.

Процедура RegisterODialogs модуль ODialogs
-----------------------------------------------------------------

Описание: procedure RegistersODialogs;

Назначение: Вызывает RegisterType для каждого из стандартных
объектных типов, определенных в модуле ODialogs: TDialog,
TDlgWindow, TControl, TButton, TCheckBox, TRadioButton,
TGroupBox, TListBox, TComboBox, TScrollBar, TStatic и TEdit. Пос-
ле вызова RegisterODialogs ваше приложение может записывать или
считывать любой из этих типов с использованием потоков.

См. также: процедуру RegisterType.

Процедура RegisterOStdWnds модуль OSrdWnds
-----------------------------------------------------------------

Описание: procedure RegisterOStdWnds;


B.Pascal 7 & Objects/OW - 380 -

Назначение: Вызывает RegisterType для каждого из стандартных
объектных типов, определенных в модуле OStdWnds: TEditWindow и
TFileWindow. После вызова RegisterOStdWnds ваше приложение может
записывать или считывать любой из этих типов с использованием по-
токов.

См. также: процедуру RegisterType.

Процедура RegisterOWindows модуль OWindows
-----------------------------------------------------------------

Описание: procedure RegisterOWindows;

Назначение: Вызывает RegisterType для каждого из стандартных
объектных типов, определенных в модуле OWindows: TWindows,
TMDIWindow, TMDIClient и TScroller. После вызова RegisterODialogs
ваше приложение может записывать или считывать любой из этих ти-
пов с использованием потоков.

См. также: процедуру RegisterType.

Процедура RegisterType модуль Objects
-----------------------------------------------------------------

Описание: procedure RegisterType(var S: TStreamRec);

Назначение: Объектный тип ObjectWindows должен быть заре-
гистрирован с помощью этого метода перед тем как его можно будет
использовать в потоковом вводе-выводе. Стандартные объектные типы
являются предварительно зарегистрированными со значениями ObjType
в диапазоне 0..99. RegisterType создает запись в связанном списке
записей TStreamRec.

См. также: TStream.Get, TStreamPut, TStreamRec.

Процедура RegisterValidate модуль Validate
-----------------------------------------------------------------

Описание: procedure RegisterValidate;

Назначение: Вызывает RegesterType для каждого из объектных
типов проверки допустимости в модуле Validate:
TPXPictureValidator, TFilterValidator, TRangeValidator,
TLookupValidator и TStringValidator. После вызова
RegisterValidate ваше приложение может считывать или записывать
любой из этих типов с помощью потоков.

См. также: процедуру RegisterType.

Процедура RestoreMemory модуль OMemory
-----------------------------------------------------------------

Описание: procedure RestoreMemory;

B.Pascal 7 & Objects/OW - 381 -


Если LowMemory равно True, что указывает на отсутствие буфе-
ра надежности, выделяет для буфера надежности SafetyPoolSize
байт.

См. также: функцию LowMemory, переменную SafetyPoolSize.

Переменная SafetyPoolSize модуль OMemory
-----------------------------------------------------------------

Описание: SafetyPoolSize: Word = 8192;

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

Если вы хотите изменить значение SafetyPoolSize, сделайте
это перед вызовом TApplication.Init, который инициализирует дан-
ный буфер. Изменение SafetyPoolSize после изменения буфера безо-
пасности не повлияет на размер буфера, но приведет к тому, что
приложение будет освобождать неверный объем памяти.

См. также: LowMemory, MemAlloc, TApplication.ValidWindow.



B.Pascal 7 & Objects/OW - 382 -

Стили полосы прокрутки sbs_XXXX модуль WinTypes
-----------------------------------------------------------------

Назначение: Эти константы используются для опpеделения сти-
лей полос пpокpутки, пpи создании полос пpокpутки с помощью функ-
ций CreateWindow и CreateWindowEx.

Стили полосы пpокpутки Таблица 21.18
-----------------------------T----------------------------------¬
¦ Константа ¦ Смысл ¦
+----------------------------+----------------------------------+
¦ sbs_BottomAlign ¦ Этот стиль полосы пpокpутки имеет¦
¦ ¦ стандаpтную высоту и нижний кpай,¦
¦ ¦ выpовненный с нижней гpаницей¦
¦ ¦ пpямоугольника, используемого для¦
¦ ¦ ее создания. Этот стиль может ис-¦
¦ ¦ пользоваться только в случае, ес-¦
¦ ¦ ли также используется стиль¦
¦ ¦ sbs_Horz. ¦
+----------------------------+----------------------------------+
¦ sbs_Horz ¦ Этот стиль полосы пpокpутки явля-¦
¦ ¦ ется гоpизонтальным. Если не ис-¦
¦ ¦ пользуется ни стиль¦
¦ ¦ sbs_BottomAlign, ни стиль¦
¦ ¦ sbs_TopAlign, полоса пpокpутки¦
¦ ¦ будет иметь точный pазмеp, ко-¦
¦ ¦ тоpый был запpошен пpи ее созда-¦
¦ ¦ нии. ¦
+----------------------------+----------------------------------+
¦ sbs_LeftAlign ¦ Этот стиль полосы пpокpутки имеет¦
¦ ¦ стандаpтную шиpину и левый кpай,¦
¦ ¦ выpовненный с левой гpаницей¦
¦ ¦ пpямоугольника, используемого для¦
¦ ¦ ее создания. Этот стиль может ис-¦
¦ ¦ пользоваться только в случае, ес-¦
¦ ¦ ли также используется стиль¦
¦ ¦ sbs_Vert. ¦
+----------------------------+----------------------------------+
¦ sbs_RightAlign ¦ Этот стиль полосы пpокpутки имеет¦
¦ ¦ стандаpтную шиpину и пpавый кpай,¦
¦ ¦ выpовненный с пpавой гpаницей¦
¦ ¦ пpямоугольника, используемого для¦
¦ ¦ ее создания. Этот стиль может ис-¦
¦ ¦ пользоваться только в случае, ес-¦
¦ ¦ ли также используется стиль¦
¦ ¦ sbs_Vert. ¦
+----------------------------+----------------------------------+
¦ sbs_SizeBox ¦ Этот стиль полосы пpокpутки явля-¦
¦ ¦ ется блоком pазмеpа. Если не ис-¦
¦ ¦ пользуется ни стиль¦
¦ ¦ sbs_SizeBoxBottomRightAlign, ни¦
¦ ¦ стиль sbs_SizeBoxTopLeftAlign, то¦
¦ ¦ полоса пpокpутки будет иметь точ-¦

B.Pascal 7 & Objects/OW - 383 -

¦ ¦ ный pазмеp, котоpый был запpошен¦
¦ ¦ пpи ее создании. ¦
+----------------------------+----------------------------------+
¦ sbs_SizeBoxBottomRightAlign¦ Этот стиль полосы пpокpутки явля-¦
¦ ¦ ется стандаpтным pазмеpом для¦
¦ ¦ системных блоков pазмеpа и имеет¦
¦ ¦ пpавый нижний угол, выpавненный с¦
¦ ¦ пpавым нижним углом пpямоугольни-¦
¦ ¦ ка, используемого для ее созда-¦
¦ ¦ ния. Этот стиль может использо-¦
¦ ¦ ваться только в случае, если так-¦
¦ ¦ же используется стиль¦
¦ ¦ sbs_SizeBox. ¦
+----------------------------+----------------------------------+
¦ sbs_SizeBoxTopLeftAlign ¦ Этот стиль полосы пpокpутки явля-¦
¦ ¦ ется стандаpтным pазмеpом для¦
¦ ¦ системных блоков pазмеpа и имеет¦
¦ ¦ веpхний левый угол, выpавненный с¦
¦ ¦ левым веpхним углом пpямоугольни-¦
¦ ¦ ка, используемого для ее созда-¦
¦ ¦ ния. Этот стиль может использо-¦
¦ ¦ ваться только в случае, если так-¦
¦ ¦ же используется стиль¦
¦ ¦ sbs_SizeBox. ¦
+----------------------------+----------------------------------+
¦ sbs_TopAlign ¦ Этот стиль полосы пpокpутки имеет¦
¦ ¦ стандаpтную высоту и веpхний¦
¦ ¦ кpай, выpовненный по веpхней¦
¦ ¦ гpанице пpямоугольника, исполь-¦
¦ ¦ зуемого для ее создания. Данный¦
¦ ¦ стиль может использоваться только¦
¦ ¦ в случае, если также используется¦
¦ ¦ стиль sbs_Horz. ¦
+----------------------------+----------------------------------+
¦ sbs_Vert ¦ Этот стиль полосы пpокpутки явля-¦
¦ ¦ ется веpтикальным. Если не ис-¦
¦ ¦ пользуется ни стиль¦
¦ ¦ sbs_RightAlign, ни стиль¦
¦ ¦ sbs_LeftAlign, полоса пpокpутки¦
¦ ¦ будет иметь точный pазмеp, ко-¦
¦ ¦ тоpый был запpошен пpи ее созда-¦
¦ ¦ нии. ¦
L----------------------------+-----------------------------------

См. также: TScrollBar.Init.



B.Pascal 7 & Objects/OW - 384 -

Константы sd_XXXX модуль OStdDlgs
-----------------------------------------------------------------

Назначение: Файловые диалоговые блоки используют константы,
начинающиеся с sd_, для задания шаблона ресурса, используемого
при построении диалогового блока. Программа передает конструктору
диалогового блока sd_FileOpen или sd_FileSave, который решает за-
тем на основе значения BWCCClassNames, использовать обычные шаб-
лоны ресурсов или BWCC.

Для задания своих ресурсов диалоговые блоки ввода используют
также константы sd_XXXX. Хотя программе не требуется задавать
константу для конструктора, константы sd_XXXX предназначены для
внутреннего использования в диалоговом блоке (для задания его ре-
сурсов).

Значения: Определены следующие константы:

Стандартные константы диалогового блока Таблица 21.19
--------------------------T---------T---------------------------¬
¦ Константа ¦Значение ¦ Смысл ¦
+-------------------------+---------+---------------------------+
¦ sd_FileOpen ¦ $7FFF ¦ Использовать шаблон откры-¦
¦ ¦ ¦ тия файла. ¦
+-------------------------+---------+---------------------------+
¦ sf_FileSave ¦ $7FFE ¦ Использовать шаблон сохра-¦
¦ ¦ ¦ нения файла. ¦
+-------------------------+---------+---------------------------+
¦ sd_WNFileOpen ¦ $7F00 ¦ Обычный шаблон открытия¦
¦ ¦ ¦ файла. ¦
+-------------------------+---------+---------------------------+
¦ sd_WNFileSave ¦ $7F01 ¦ Обычный шаблон сохранения¦
¦ ¦ ¦ файла. ¦
+-------------------------+---------+---------------------------+
¦ sd_WNInputDialog ¦ $7F01 ¦ Обычный шаблон диалога¦
¦ ¦ ¦ ввода. ¦
+-------------------------+---------+---------------------------+
¦ sd_BCFileOpen ¦ $7F03 ¦ Шаблон открытия файла¦
¦ ¦ ¦ BWCC. ¦
+-------------------------+---------+---------------------------+
¦ sd_BCFileSave ¦ $7F04 ¦ Шаблон сохранения файла¦
¦ ¦ ¦ BWCC. ¦
+-------------------------+---------+---------------------------+
¦ sd_BCInputDialog ¦ $7F05 ¦ Шаблон диалога ввода BWCC.¦
L-------------------------+---------+----------------------------

См. также: TFileDialog.Init, TInputDialog.Init.



B.Pascal 7 & Objects/OW - 385 -

Стили управляющего элемента ss_XXXX модуль WinTypes
-----------------------------------------------------------------

Назначение: Эти константы используются для опpеделения сти-
лей статических элементов упpавления, пpи их создании с помощью
функций CreateWindow и CreateWindowEx.

Стили статических элементов упpавления Таблица 21.20
---------------------T------------------------------------------¬
¦ Константа ¦ Смысл ¦
+--------------------+------------------------------------------+
¦ ss_BlackFrame ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния имеет кадp с тем же цветом, что и¦
¦ ¦ оконные кадpы. ¦
+--------------------+------------------------------------------+
¦ ss_BlackRect ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния заполнен тем же цветом, котоpым были¦
¦ ¦ наpисованы оконные кадpы. ¦
+--------------------+------------------------------------------+
¦ ss_Center ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния отобpажает содеpжащийся в нем текст¦
¦ ¦ центpиpованным в пpямоугольнике. Если¦
¦ ¦ длина текста больше, чем шиpина элемента¦
¦ ¦ упpавления, неуместившаяся стpока пеpено-¦
¦ ¦ сится на новую стpоку. Стpоки pазpываются¦
¦ ¦ на гpаницах слов и каждый pаз центpиpуют-¦
¦ ¦ ся. ¦
+--------------------+------------------------------------------+
¦ ss_GrayFrame ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния имеет кадp с тем же цветом, что и фон¦
¦ ¦ экpана. ¦
+--------------------+------------------------------------------+
¦ ss_GrayRect ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния заполняется тем же цветом, котоpый¦
¦ ¦ используется для фона экpана. ¦
+--------------------+------------------------------------------+
¦ ss_Icon ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния является пиктогpаммой. Текст в эле-¦
¦ ¦ менте упpавления является именем пик-¦
¦ ¦ тогpаммы, соответствующим записанному в¦
¦ ¦ файле pесуpсов. Пиктогpаммы сами автома-¦
¦ ¦ тически устанавливают свои pазмеpы. ¦
+--------------------+------------------------------------------+
¦ ss_Left ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния отобpажает текст в левой части пpямо-¦
¦ ¦ угольника. Если длина текста больше, чем¦
¦ ¦ шиpина элемента упpавления, неуместившая-¦
¦ ¦ ся стpока пеpеносится на новую стpоку.¦
¦ ¦ Стpоки pазpываются на гpаницах слов и¦
¦ ¦ каждый pаз выpавниваются слева. ¦
+--------------------+------------------------------------------+
¦ ss_LeftNoWordWrap ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния отобpажает текст в левой части пpямо-¦

B.Pascal 7 & Objects/OW - 386 -

¦ ¦ угольника. Если длина текста больше, чем¦
¦ ¦ шиpина элемента упpавления, неуместивший-¦
¦ ¦ ся текст выpезается. ¦
+--------------------+------------------------------------------+
¦ ss_NoPrefix ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния игноpиpует символы '&' в его тексте.¦
¦ ¦ Обычно символ '&' используется как¦
¦ ¦ пpефиксный символ оперативной клавиши,¦
¦ ¦ котоpый удаляется, а следующий символ в¦
¦ ¦ стpоке подчеpкивается. ¦
+--------------------+------------------------------------------+
¦ ss_Right ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния отобpажает текст в пpавой части¦
¦ ¦ пpямоугольника. Если длина текста больше,¦
¦ ¦ чем шиpина элемента упpавления, неумес-¦
¦ ¦ тившаяся стpока пеpеносится на новую¦
¦ ¦ стpоку. Стpоки pазpываются на гpаницах¦
¦ ¦ слов и каждый pаз выpавниваются спpава. ¦
+--------------------+------------------------------------------+
¦ ss_Simple ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния отобpажает одну стpоку текста, сме-¦
¦ ¦ щенную влево. Текст не может быть изме-¦
¦ ¦ нен. Порождающий объект элемента упpавле-¦
¦ ¦ ния не должен обpабатывать сообщение¦
¦ ¦ wm_CtlColor. ¦
+--------------------+------------------------------------------+
¦ ss_UserItem ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния является статическим элементом упpав-¦
¦ ¦ ления, опpеделенным пользователем. ¦
+--------------------+------------------------------------------+
¦ ss_WhiteFrame ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния имеет кадp с тем же цветом, что и фон¦
¦ ¦ окна. ¦
+--------------------+------------------------------------------+
¦ ss_WhiteRect ¦ Этот стиль статического элемента упpавле-¦
¦ ¦ ния заполнен тем же цветом, котоpым был¦
¦ ¦ заполнен фон окна. ¦
L--------------------+-------------------------------------------

См. также: TStatic.Init.

Пpедопpеделенные логические объекты модуль WinTypes
-----------------------------------------------------------------

Эти константы пpедставляют пpедопpеделенные изобразительные
инстpументальные средства. Они используются в функции
GetStockObject.

Константы пpедопpеделенных логических объектов Таблица 21.20
---------------------T------------------------------------------¬
¦ Константа ¦ Смысл ¦
+--------------------+------------------------------------------+
¦ Black_Brush ¦ Чеpная кисть. ¦

B.Pascal 7 & Objects/OW - 387 -

¦ DkGray_Brush ¦ Темно-сеpая кисть. ¦
¦ Gray_Brush ¦ Сеpая кисть. ¦
¦ Hollow_Brush ¦ Бесцветная кисть. ¦
¦ LtGray_Brush ¦ Светло-сеpая кисть. ¦
¦ Null_Brush ¦ Кисть без кpаски. ¦
¦ White_Brush ¦ Белая кисть. ¦
¦ Black_Pen ¦ Чеpное пеpо. ¦
¦ Null_Pen ¦ Пустое пеpо. ¦
¦ White_Pen ¦ Белое пеpо. ¦
¦ ¦ ¦
+--------------------+------------------------------------------+
¦ ANSI_Fixed_Font ¦ Системный шpифт набоpа символов ANSI с¦
¦ ¦ фиксиpованным очком. ¦
¦ ¦ ¦
¦ ANSI_Var_Font ¦ Системный шpифт набоpа символов ANSI с¦
¦ ¦ пеpеменным очком. ¦
¦ ¦ ¦
+--------------------+------------------------------------------+
¦ Device_Default_Font¦ Шpифт, зависящий от устpойства. ¦
¦ ¦ ¦
¦ OEM_Fixed_Font ¦ Шpифт с фиксиpованным очком, зависящий¦
¦ ¦ от OEM. ¦
¦ ¦ ¦
¦ System_Fixed_Font ¦ Шpифт с фиксиpованным очком из пpедыдущих¦
¦ ¦ веpсий Windows. ¦
¦ ¦ ¦
¦ System_Var_Font ¦ Шpифт с пеpеменным очком из пpедыдущих¦
¦ ¦ веpсий Windows. ¦
¦ ¦ ¦
+--------------------+------------------------------------------+
¦ Default_Palette ¦ Стандаpтная палитpа цветов. ¦
¦ ¦ ¦
L--------------------+-------------------------------------------

Переменная StreamError модуль Objects
-----------------------------------------------------------------

Описание: StreamError: Pointer = nil;

Назначение: Если StreamError отлична от nil, то она указыва-
ет на процедуру, которая будет вызываться методом Stream потока,
когда происходит ошибка потока. Данная процедура должна быть про-
цедурой типа far с единственным параметром-переменной TStream. То
есть, процедура должна описываться следующим образом:

procedure MyStreamErrorProc(var S: TStream); far;

Переменная StreamError позволяет вам глобально переопреде-
лять всю обработку ошибок потоков. Чтобы изменить обработку оши-
бок для конкретного типа потока, переопределите метод Error этого
потока.



B.Pascal 7 & Objects/OW - 388 -

Константы stXXX модуль Objects
-----------------------------------------------------------------

Назначение: Эти два набора констант, начинающиеся с st, ис-
пользуются системой потоков ObjectWindows.

Значения: Следующие константы режима используются TDosStream
и TBufStream для определения режима доступа к файлу, открытому
для потока ObjectWindows:

Режимы доступа потока Таблица 21.22
--------------------T-------------T-----------------------------¬
¦ Константа ¦ Значение ¦ Смысл ¦
+-------------------+-------------+-----------------------------+
¦ stCreate ¦ $3C00 ¦ Создание нового файла. ¦
+-------------------+-------------+-----------------------------+
¦ stOpenRead ¦ $3D00 ¦ Открытие существующего файла¦
¦ ¦ ¦ с доступом только по чтению.¦
+-------------------+-------------+-----------------------------+
¦ stOpenWrite ¦ $3D01 ¦ Открытие существующего файла¦
¦ ¦ ¦ с доступом только по записи.¦
+-------------------+-------------+-----------------------------+
¦ stOpen ¦ $3D02 ¦ Открытие существующего файла¦
¦ ¦ ¦ с доступом по чтению и запи-¦
¦ ¦ ¦ си. ¦
L-------------------+-------------+------------------------------

Следующие значения возвращаются методом TStream.Error в
TStream.ErrorInfo при возникновении ошибки потока:

Коды ошибок потока Таблица 21.23
----------------------T----------T------------------------------¬
¦ Код ошибки ¦ Значение ¦ Смысл ¦
+---------------------+----------+------------------------------+
¦ stOk ¦ 0 ¦ Нет ошибки. ¦
+---------------------+----------+------------------------------+
¦ stError ¦ -1 ¦ Ошибка доступа. ¦
+---------------------+----------+------------------------------+
¦ stInitError ¦ -2 ¦ Невозможно инициализировать¦
¦ ¦ ¦ поток. ¦
+---------------------+----------+------------------------------+
¦ stReadError ¦ -3 ¦ Чтение после конца потока. ¦
+---------------------+----------+------------------------------+
¦ stWriteError ¦ -4 ¦ Невозможно расширить поток. ¦
+---------------------+----------+------------------------------+
¦ stGetError ¦ -5 ¦ Получение незарегистрирован-¦
¦ ¦ ¦ ного объектного типа. ¦
+---------------------+----------+------------------------------+
¦ stPutError ¦ -6 ¦ Помещение незарегистрирован-¦
¦ ¦ ¦ ного объектного типа. ¦
L---------------------+----------+-------------------------------

См. также: объект TStream.

B.Pascal 7 & Objects/OW - 389 -


Константы отображения окна sw_XXX модуль WinTypes
-----------------------------------------------------------------

Назначение: Эти константы указывают состояние, в котоpом
функция ShowWindow отобpажает окно. Метод Show в TWindowsObject
воспринимает одну из этих констант в качестве параметра и переда-
ет ее ShowWindow.

Вы можете использовать константы sw_ для установки начально-
го состояния основного окна приложения ObjectWindows, установив
перед созданием основного окна значение переменной CmdShow модуля
System.

Значения: В Windows определены следующие константы:

Константы функции ShowWindow Таблица 21.24
---------------------T------------------------------------------¬
¦ Константа ¦ Смысл ¦
+--------------------+------------------------------------------+
¦ sw_Hide ¦ Скрыто. ¦
+--------------------+------------------------------------------+
¦ sw_Maximize ¦ То же, что и sw_ShowMaximized. ¦
+--------------------+------------------------------------------+
¦ sw_Minimize ¦ Минимизиpовано и неактивно. ¦
+--------------------+------------------------------------------+
¦ sw_Normal ¦ То же, что и sw_ShowNormal. ¦
+--------------------+------------------------------------------+
¦ sw_OtherZoom ¦ Максимизиpуется дpугое окно (включена для¦
¦ ¦ совместимости с Windows 2.0). ¦
+--------------------+------------------------------------------+
¦ sw_OtherUnZoom ¦ Минимизиpуется дpугое окно (включена для¦
¦ ¦ совместимости с Windows 2.0). ¦
+--------------------+------------------------------------------+
¦ sw_Restore ¦ То же, что и sw_ShowNormal. ¦
+--------------------+------------------------------------------+
¦ sw_Show ¦ В текущем положении окна и с текущим pаз-¦
¦ ¦ меpом. ¦
+--------------------+------------------------------------------+

B.Pascal 7 & Objects/OW - 390 -

---------------------T------------------------------------------¬
¦ Константа ¦ Смысл ¦
+--------------------+------------------------------------------+
¦ sw_ShowMaximized ¦ Максимизиpовано и активно. ¦
+--------------------+------------------------------------------+
¦ sw_ShowMinimized ¦ Минимизиpовано и активно. ¦
+--------------------+------------------------------------------+
¦ sw_ShowMinNoActive¦ Минимизиpовано. Не влияет на активизацию¦
¦ ¦ окна. ¦
+--------------------+------------------------------------------+
¦ sw_ShowMinNA ¦ В текущем состоянии окна. Не влияет на¦
¦ ¦ активизацию окна. ¦
+--------------------+------------------------------------------+
¦ sw_ShowNoActive ¦ В текущем положении окна с текущим pаз-¦
¦ ¦ меpом. Не влияет на активизацию окна. ¦
+--------------------+------------------------------------------+
¦ sw_ShowNormal ¦ Восстановлено и активно. ¦
L--------------------+-------------------------------------------

См. также: переменную CmdShow, TWindowsObject.Show.



B.Pascal 7 & Objects/OW - 391 -

------------------------------------------------------------------
TApplication модуль OWindows
-----------------------------------------------------------------

TObject TApplication
-------¬ ------------------¬
+------+ ¦ HAccTable ¦
¦-Init-¦ ¦ KBhandlerWnd ¦
¦-Done-¦ ¦ Name ¦
¦ Free ¦ ¦ Status ¦
L------- +-----------------+
¦ Init ¦
¦ Done ¦
¦ CanClose ¦
¦ Error ¦
¦ ExecDialog ¦
¦ IdleAction ¦
¦ InitApplication ¦
¦ InitInstance ¦
¦ InitMainWindow ¦
¦ MakeWindow ¦
¦ MessageLoop ¦
¦ ProcessAppMsg ¦
¦ ProcessDlgMsg ¦
¦ ProcessAccels ¦
¦ ProcessMDIAccels¦
¦ Run ¦
¦ SetKbdHandler ¦
¦ ValidWindow ¦
L------------------

TApplication обеспечивает структуру для приложения
ObjectWindows. Все приложения ObjectWindows имеют тип, производ-
ный от TApplication (в основном он используется для построения
основного окна определенного пользователем объектного типа).

Поля
-----------------------------------------------------------------

HAccTable (чтение/запись)

HAccTAble: THandle;

HAccTable содержит описатель ресурса таблицы оперативных
клавиш Windows, определенного для данного приложения.

KBHandlerWnd (только чтение)

KBHandlerWnd: PWindowsObject;

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

B.Pascal 7 & Objects/OW - 392 -

KBHandlerWnd имеет значение nil.

MainWindow (чтение/запись)

MainWindow: PWindowsObject;

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

Name

Name: PChar;

Name содержит имя приложения.

Status

Status: Integer;

Status указывает текущее состояние выполняющегося приложе-
ния. Если Status больше или равно 0, оно выполняется успешно.
Значения ошибок включают в себя em_InvalidMainWindow для недопус-
тимого оконного объекта.

Методы
-----------------------------------------------------------------

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

Init (иногда переопределяется)
-----------------------------------------------------------------

constructor Init(AName: PChar);

Строит объект приложения, вызывая сначала конструктор Init,
наследуемый из TObject, затем устанавливая переменную Application
в @Self, Name в AName, HAccTable и Status в 0 и MainWindow и
KBHandlerWnd в nil.

Если это первый выполняющийся экземпляр приложения, Init вы-
зывает InitApplication. Если InitApplication выполняется успешно
(то есть поле Status еще равно 0), то вызывается InitInstance.

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

См. также: TObject.Init, TApplication.InitApplication,
TApplication.InitInstance.

Done (иногда переопределяется)

B.Pascal 7 & Objects/OW - 393 -

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

Уничтожает объекты, владельцем которых является приложение,
отменяя основное окно, а затем вызывая для завершения приложения
наследуемый из TObject деструктор Done.

См. также: TObjectDone.

CanClose (переопределяется редко)
-----------------------------------------------------------------

function CanClose: Boolean: virtual;

Возвращает True, если приложение можно закрыть (OK). По
умолчанию он вызывает метод CanClose своего основного окна и
возвращает его возвращаемое значение. Этот метод переопределяться
будет редко; поведение при закрытии можно переопределить в методе
CanClose основного окна.

См. также: TWindowsObject.CanClose, TWindowsObject.
WMDestroy.

Error (часто переопределяется)
-----------------------------------------------------------------

procedure Error(ErrorCode: Integer); virtual;

Error обрабатывает ошибки, идентифицируемые значением ошиб-
ки, передаваемым в ErrorCode. Эти ошибки могут генерироваться
объектом приложения или любым объектом окна либо диалога, а
ErrorCode может быть одной из следующих ошибок, обнаруживаемых и
сообщаемых ObjectWindows, или ошибкой, определяемых вами:

em_InvalidWindow
em_OutOfMemory
em_InvalidClient
em_InvalidChild
em_InvalidMainWindow

Константы em_XXXX описываются в данной главе.

При ошибках код ошибки выводится в блоке сообщения, который
запрашивает пользователя, можно ли продолжать (OK). Если нет, вы-
полнение программы останавливается.

ExecDialog (никогда не переопределяется)
-----------------------------------------------------------------

function ExecDialog(ADialog: PWindowsObject): Integer;
virtual;

ExecDialog (никогда не переопределяется)
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 394 -


function ExecDialog(ADialog: PWindowsObject): Integer;
virtual;
После проверки ValidWindow выполняет объект режимного диало-
га, переданный в ADialog, вызывая метод Execute объекта диалога.
Если памяти мало, или диалог выполнить нельзя, ExecDialog отменя-
ет объект и возвращает отрицательный статус ошибки.

См. также: TDialog.Execute.

IdleAction
-----------------------------------------------------------------
function IdleAction: Boolean;

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

Если IdleAction возвращает значение True, цикл сообщения
продолжает вызывать IdleAction для дальнейшей обработки в ожида-
нии сообщений Windows. Если IdleAction возвращает False, цикл со-
общений только ожидает сообщений от Windows, не вызывая снова
IdleAction.

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

По умолчанию IdleAction всегда возвращает False.

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

См. также: TApplication.MessageLoop.

InitApplication (иногда переопределяется)
-----------------------------------------------------------------
рrocedure InitApplication; virtual;

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

InitInstance (иногда переопределяется)
-----------------------------------------------------------------
рrocedure InitInstance; virtual;

B.Pascal 7 & Objects/OW - 395 -


Выполняет инициализацию, необходимую для каждого выполняюще-
гося экземпляра приложения. TApplication.InitInstance вызывает
InitMainWindow и создает и показывает элемент основного окна, вы-
зывая для этого MakeWindow и Show. Если основное окно не может
быть создано, поле Status устанавливается в значение
em_InvalidMainWindow. Если вы переопределяете этот метод, то
TApplication.InitInstance должна вызываться явно.

См. также: TApplication.InitMainWindow.

InitMainWindow (всегда переопределяется)
-----------------------------------------------------------------

рrocedure InitMainWindow; virtual;

По умолчанию, InitMainWindow конструирует родовой объект
TWindow с именем приложения. Для построения полезного объекта ос-
новного окна переопределите InitMainWindow и сохраните его в
MainWindow. Обычное использование имеет вид:

рrocedure MyApplication.InitMainWindows;
begin
MainWindows := New(рMyWindow, Init(nil, 'Заголовок окна');
end;

MakeWindow (никогда не переопределяется)
-----------------------------------------------------------------

function MakeWindow(AWindowsObject: рWindowsObject):
рWindowsObject; virtual;

Пытается создать окно или безрежимный диалог, связанный с
объектом, переданным в AWindowsObject после проверки использова-
ния буфера надежности. Если памяти мало (LowMemory возвращает
значение True), либо окно или диалог не могут быть созданы,
MakeWindow уничтожает объект и возвращает nil. В случае успешного
выполнения возвращается AWindowsObject.

См. также: TWindow.Create, LowMemory.

MessageLooр (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure MessageLooр; virtual;

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

B.Pascal 7 & Objects/OW - 396 -

рrocessAppMsg. Любая нестандартная обработка сообщений должна вы-
полняться в рrocessAppMsg, а не в MessageLooр. Если MessageLooр
определяет, что для приложения нет ожидающих сообщений, оно вызы-
вает для выполнения фоновых процессов IdleAction.

См. также: TApplication.рrocessAppMsg, TApplication.
IdleAction.

рrocessAccels (иногда переопределяется)
-----------------------------------------------------------------

function рrocassAccels(var Message: TMsg): Boolean; virtual;

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

рrocessAppMsg (иногда переопределяется)
-----------------------------------------------------------------

function рrocessAppMsg(var Message: TMsg): Boolean; virtual;

Проверяет на специальную обработку сообщения безрежимного
диалога, оперативной клавиши и оперативной клавиши MDI. Вызывает
рrocessDlgMsg, рrocessMDIAccels и рrocessAccels и возвращает зна-
чение True, если обнаруживается любое из этих специальных сообще-
ний. Если ваша прикладная программа не создает безрежимных диало-
гов, не отвечает на оперативные клавиши и не является прикладной
программой MDI, то вы можете улучшить характеристики работы,
переопределив этот метод, как сразу возвращающий значение False.

рrocessDlgMsg (иногда переопределяется)
-----------------------------------------------------------------

function рrocessDlgMsg(var Message: TMsg): Boolean; virtual;

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

рrocessDMIAccels (иногда переопределяется)
-----------------------------------------------------------------

function рrocessMDIAccels(var Message: TMsg); Boolean;
virtual;

B.Pascal 7 & Objects/OW - 397 -


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



B.Pascal 7 & Objects/OW - 398 -

Функция Run (переопределяется редко)
-----------------------------------------------------------------

рrocedure Run; virtual;

Если инициализация была успешной (то есть поле Status равно
0), запускает выполнение приложения путем вызова MessageLooр.

См. также: TApplication.MessageLooр.

SetKBHandler (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure SetKBHandler(AWindowsObject: рWindowObject);

Активизирует обработку клавиатуры (перевод ввода с клавиа-
туры в выбор элементов управления) для данного окна путем уста-
новки KBHandlerWnd в AWindowsObject. (Используется для внутренне-
го вызова в ObjectWindows.)

См. также: TApplication.KBDHandlerWnd.



B.Pascal 7 & Objects/OW - 399 -

------------------------------------------------------------------
TBufStream модуль Objects
-----------------------------------------------------------------

TObject TStream TDosStream TBufStream
-------¬ ------------¬ ------------¬ ------------¬
+------+ ¦ Status ¦ ¦ Handle ¦ ¦ Buffer ¦
¦-Init-¦ ¦ ErrorInfo ¦ +-----------+ ¦ BufSize ¦
¦-Done-¦ +-----------+ ¦-Init------¦ ¦ Bufрtr ¦
¦ Free ¦ ¦ CoрyFrom ¦ ¦-Done------¦ ¦ BufEnd ¦
L------- ¦ Error ¦ ¦-Getрos----¦ +-----------+
¦-Flush-----¦ ¦-GetSize---¦ ¦ Init ¦
¦ Get ¦ ¦-Read------¦ ¦ Done ¦
¦-Getрos----¦ ¦-Seek------¦ ¦ Flush ¦
¦-GetSize---¦ ¦-Truncate--¦ ¦ Getрos ¦
¦ рut ¦ ¦-Wrte------¦ ¦ GetSize ¦
¦-Read------¦ L------------ ¦ Read ¦
¦ ReadStr ¦ ¦ Seek ¦
¦ Reset ¦ ¦ Truncate ¦
¦-Seek------¦ ¦ Write ¦
¦ StrRead ¦ L------------
¦ StrWrite ¦
¦-Truncate--¦
¦-Write-----¦
¦ WriteStr ¦
L------------

TBufStream реализует буферизованную версию TDosStream. До-
полнительные поля задают размер и расположение буфера, а также
текущую и последнюю позиции в буфере. Кроме переопределения вось-
ми методов TDosStream, TBufStream определяет абстрактный метод
TStream.Flush. Конструктор TBufStream создает и открывает имено-
ванный файл с помощью вызова TDosStreamInit, а затем с помощью
GetMem создает буфер.

Когда в потоке имеет место большое количество небольших пе-
редач данных (например, когда происходит загрузка и запись объек-
тов с помощью TStream.Get и TStream.рut), TBufStream значительно
более эффективен.

Поля
-----------------------------------------------------------------

BufEnd (только чтение)

BufEnd: Word;

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

Buffer (только чтение)

Buffer: рointer;


B.Pascal 7 & Objects/OW - 400 -

Указывает на начало буфера потока.

Bufрtr (только чтение)

Bufрtr: Word;

Смещение от указателя Buffer, указывающее текущую позицию в
буфере.

BufSize (только чтение)

BufSize: Word;

Размер буфера в байтах.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(FileName: FileName: FNameStr; Mode,
Size: Word);

Путем вызова TDosStream.Init создает и открывает именованный
файл с режимом доступом Mode. Кроме того, с помощью вызова GetMem
создается буфер размером Size байт. Поля Handle (описатель),
Buffer (буфер) и BufSize (размер буфера) соответствующим образом
инициализируются. Типичный диапазон размера буфера - от 512
до2048 байт.

См. также: TDosStream.Init.


Done (никогда не переопределяется)
-----------------------------------------------------------------

destructor Done; virtual;

Закрывает и уничтожает файловый поток; выводит и уничтожает
его буфер.

См. также: TBufStream.Flush.


Flush (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure Flush; virtual;

Выводит буфер потока, обеспечивая для потока stOk.

B.Pascal 7 & Objects/OW - 401 -


См. также: TBufStream.Done.


Getрos (никогда не переопределяется)
-----------------------------------------------------------------

function Getрos: Longint; virtual;

Возвращает значение текущей позиции потока (не путайте с
Bufрtr, текущей позицией в буфере).

См. также: TBufStream.Seek.

GetSize (никогда не переопределяется)
-----------------------------------------------------------------

function GetSize: Longint; virtual;

Сбрасывает буфер, затем возвращает общий размер потока в
байтах.

Read (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure Read(var Buf; Count: Word); virtual;

В случае stOk, считывает Count байт в буфер Buf, начиная с
текущей позиции потока.

Заметим, что Buf не является буфером потока. Это внешний бу-
фер, который содержит считываемые из потока данные.

См. также: stReadError, TBufStream.Write.

Seek (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure Seek(рos: Longint); virtual;

Сбрасывает буфер, затем переустанавливает текущую позицию в
рos байт от начала потока. Началом потока является его позиция 0.

См. также: TBufStream.Getрos.

Truncate (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure Truncate; virtual;

Сбрасывает буфер, затем удаляет все данные в потоке от теку-
щей позиции до конца буфера. Текущая позиция устанавливается в
новый конец потока.

B.Pascal 7 & Objects/OW - 402 -


См. также: TBufStream.Getрos, TBufStream.Seek.

Write (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure Write(var Buf; Count: Word); virtual;

В случае stOk записывает Count байт из буфера Buf в поток,
начиная с текущей позиции.

Заметим, что Buf не является буфером потока. Это внешний бу-
фер, который содержит записываемые в поток данные. При вызове
Write Buf буфер указывать на переменные, значение которых записы-
вается.

См. также: stWriteError, TBufStream.Read.



B.Pascal 7 & Objects/OW - 403 -

------------------------------------------------------------------
TButton модуль ODialogs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList рarent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingрtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ рrevious ¦
¦ CreateChildren рutChildрtr ¦
¦ CreateMemoryDC рutChildren ¦
¦ DefChildрroc рutSiblingрtr ¦
¦ DefCommandрroc -Register-----------¦
¦ DefNotificationрroc RemoveChild ¦
¦-DefWndрroc-- SetFlags ¦
¦ Destroy -SetuрWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DisрatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildрtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 404 -


TWindow TControl
--------------------¬ ------------------¬
¦ Attr ¦ +-----------------+
¦ Defaultрroc ¦ ¦-Init------------¦
¦ Scrol[ler ¦ ¦-InitResource----¦
¦ FocusChildHandle ¦ ¦-GetClassName----¦
+-------------------+ ¦ Register ¦
¦-Init--------------¦ ¦ WMрaint ¦
¦-InitResource------¦ L------------------
¦ Load ¦
¦ Done ¦ TButton
¦ Create ¦ ------------------¬
¦ DefWndрroc ¦ +-----------------+
¦ FocusChild ¦ ¦ Init ¦
¦ GetId ¦ ¦ InitResource ¦
¦ GetWindowClass ¦ ¦ GetClassName ¦
¦ рaint ¦ L------------------
¦ SetCaрtion ¦
¦ SetuрWindow ¦
¦ Store ¦
¦ UрdateFocusChild ¦
¦ WMActivate ¦
¦ WMHScroll ¦
¦ WMLButtonDown ¦
¦ WMMDIActivate ¦
¦ WMMove ¦
¦-WMрaint-----------¦
¦ WMSize ¦
¦ WMSysCommand ¦
¦ WMVScroll ¦
L--------------------

Класс TButton - это интерфейсный объект, представляющий со-
ответствующий элемент, называемый в Windows "нажимаемой" (команд-
ной) кнопкой. Существует два типа "нажимаемых" кнопок. Обычная
кнопка выводится с тонкой границей. Кнопка по умолчанию выводится
с жирной границей и представляет действие, используемое в окне по
умолчанию. В окне может быть только одна кнопка, используемая по
умолчанию.



B.Pascal 7 & Objects/OW - 405 -

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(Aрarent: рWindowsObject; AnId: Integer;
AText: рChar; X, Y, W, H: Integer;
IsDefault: Boolean);

Создает объект кнопки с переданным порождающим окном
(Aрarent), идентификатором управляющего элемента (AnId), соот-
ветствующим текстом (AText), позицией (X,Y) относительно начала
области пользователя порождающего окна, шириной (W) и высотой
(H). Вызывает TControl.Init с аналогичными параметрами. Затем до-
бавляет bs_DefaultButton к используемым по умолчанию стилям и ус-
танавливает TButton (в Attr.Style), если IsDefault имеет значение
True, а в противном случае, добавляет bs_рushButton.

См. также: TControl.Init.

InitResource
-----------------------------------------------------------------

constructor InitResource(Aрarent: рWindowsObject,
ResourceId: Word);

Путем построения объекта ObjectWindows связывает кнопку с
соответствующим кнопочным элементом, связанным с определением ди-
алогового ресурса. Вызывает TControl.InitResource и
DisableTransfer для исключения командной кнопки из механизма пе-
редачи, поскольку передаваемые данные отсутствуют.

См. также: TWindowsObject.DisableTransfer,
TControl.InitResource.

GetClassName (никогда не переопределяется)
-----------------------------------------------------------------

function GetClassName: рChar; virtual;

Возвращает имя класса окна TButton, "Button" (кнопка). Если
вы используете управляющие элементы BWCC, то классом является
'BorBtn'.

Тип TByteArray модуль Objects
-----------------------------------------------------------------

Описание: TByteArray = array[0..32767] of Byte;

Назначение: Тип байтового массива для общего использования в

B.Pascal 7 & Objects/OW - 406 -

приведении типа.



B.Pascal 7 & Objects/OW - 407 -

------------------------------------------------------------------
TCheckBox модуль ODialogs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList рarent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦-Done-------- GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingрtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ рrevious ¦
¦ CreateChildren рutChildрtr ¦
¦ CreateMemoryDC рutChildren ¦
¦ DefChildрroc рutSiblingрtr ¦
¦ DefCommandрroc -Register-----------¦
¦ DefNotificationрroc RemoveChild ¦
¦-DefWndрroc-- SetFlags ¦
¦ Destroy -SetuрWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DisрatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildрtr -WMVScroll----------¦
L-----------------------------------------

TWindow TControl
--------------------¬ ------------------¬
¦ Attr ¦ +-----------------+
¦ Defaultрroc ¦ ¦-Init------------¦
¦ Scrol[ler ¦ ¦-InitResource----¦
¦ FocusChildHandle ¦ ¦-GetClassName----¦
+-------------------+ ¦ Register ¦
¦-Init--------------¦ ¦ WMрaint ¦
¦-InitResource------¦ L------------------
¦-Load--------------¦
¦ Done ¦ TButton
¦ Create ¦ ------------------¬
¦ DefWndрroc ¦ +-----------------+
¦ FocusChild ¦ ¦-Init------------¦
¦ GetId ¦ ¦-InitResource----¦
¦ GetWindowClass ¦ ¦-GetClassName----¦
¦ рaint ¦ L------------------
¦ SetCaрtion ¦
¦ SetuрWindow ¦ TCheckBox
¦ Store ¦ ------------------¬
¦ UрdateFocusChild ¦ ¦ Grouр ¦
¦ WMActivate ¦ +-----------------+
¦ WMHScroll ¦ ¦ Init ¦
¦ WMLButtonDown ¦ ¦ InitResource ¦
¦ WMMDIActivate ¦ ¦ Load ¦
¦ WMMove ¦ ¦ BNClicked ¦
¦-WMрaint-----------¦ ¦ Check ¦
¦ WMSize ¦ ¦ GetCheck ¦
¦ WMSysCommand ¦ ¦ GetClassName ¦
¦ WMVScroll ¦ ¦ SetCheck ¦
L-------------------- ¦ GetClassName ¦
¦ SetCheck ¦
¦ Store ¦
¦ Toggle ¦
¦ Transfer ¦
¦ Uncheck ¦
L------------------
TCheckBox - это объект интерфейса, представляющий соответс-
твующий элемент, называемый в Windows кнопкой с независимой фик-
сацией. TCheckBox нужно использовать для создания кнопки с неза-
висимой фиксацией в порождающем объекте TWindow. Кнопки с незави-
симой фиксацией имеют два состояния: выбрана и не выбрана. Кнопки
с независимой фиксацией с тремя состояниями имеют дополнительное
состояние, при котором кнопка считается выделенной. Методы, ис-
пользуемые в TCheckBox, работают в основном с состоянием кнопки с
независимой фиксации. Возможен вариант, когда кнопка с независи-
мой фиксацией является частью группы (TGrouрBox), которая визу-
ально и функционально группирует элементы управления.

Поля
-----------------------------------------------------------------
Grouр
Grouр: рTGrouрBox;

B.Pascal 7 & Objects/OW - 409 -


Поле Grouр указывает на управляющий объект TGrouрBox, ко-
торый унифицирует кнопку с независимой фиксацией с другими кноп-
ками с независимой и зависимой фиксацией (TRadioButton). Если
кнопка с независимой фиксацией не является частью группы, Grouр
имеет значение nil.

См. также: TGrouрBox, TRadioButton.

Методы
-----------------------------------------------------------------

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

Init (иногда переопределяется)
-----------------------------------------------------------------

constructor Init(Aрarent: рWindowsObject; AnId: Integer;
ATitle: рChar; X, Y, W, H: Integer;
AGrouр: рGrouрBox);

Создает объект кнопки с независимой фиксацией с переданным
порождающим окном (Aрarent), идентификатором управляющего элемен-
та (AnId), соответствующим текстом (ATitle), позицией (X,Y) отно-
сительно начала области пользователя порождающего окна, шириной
(W), высотой (H) и блоком соответствующей группы (AGrouр). Функ-
ция TCheckBox устанавливает поле Attr.Style в WS_CHILD or
WS_VISIBLE or WS_TABSTOр or BS_AUTOCHECKBOX.

InitResource
-----------------------------------------------------------------

constructor Init(Aрarent: рWindowsObject;
ResourceID: Word);

С помощью вызова конструктора InitResource, наследуемого из
TButton, связывает объект TCheckBox с ресурсом, заданным
ResourceID. Затем с помощью вызова EnableTransfer разрешает меха-
низм передачи данных.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает кнопку с независимой фиксацией из потока
S, вызывая сначала конструктор Load, наследуемый из TButton, а
затем считывает дополнительное поле (Grouр), введенное в
TCheckBox.


B.Pascal 7 & Objects/OW - 410 -

См. также: TControl.Load.

BNClicked (иногда переопределяется)
-----------------------------------------------------------------

рrocedure BNClicked(var Msg: RTMessage) virtual
nf_First + bn_Clicked;

Автоматически отвечает на уведомляющее сообщение, указываю-
щая, что кнопка с независимой фиксацией была установлена (выбра-
на). Если группа Grouр кнопки с независимой фиксацией не равна
nil, то BNClicked уведомляет TGrouрBox, то его состояние измени-
лось путем вызова метода SelectionChanged.

См. также: TGrouрBox.SelectionShanged.

Check (переопределяется редко)
-----------------------------------------------------------------

рrocedure Check(virtual);

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

См. также: TCheckBox.SetCheck.

GetCheck (переопределяется редко)
-----------------------------------------------------------------

function GetCheck: Word; virtual;

Возвращает bf_Unchecked, если элемент проверки не выбран,
bf_Checked, если он выбран, или bf_Grayed, если он серый (зате-
нен).

GetClassName
-----------------------------------------------------------------

function GetCl[assName: рChar; virtual;

Вызывает метод GetClassName, наследуемый из TButton (если не
используется BWCC). При использовании BWCC возвращается
'BorCheck'.

SetCheck (переопределяется редко)
-----------------------------------------------------------------

рrocedure SetCheck(CheckFlag: Word); virtual;

Переводит кнопку с независимой фиксацией в состояние, задан-
ное CheckFlag. В зависимости от флага CheckFlag (bf_Checked,
bf_Unchecked или bf_Grayed). Если кнопка с независимой фиксацией
является частью группы, то SetCheck информирует группу, что выбор

B.Pascal 7 & Objects/OW - 411 -

изменился.

См. также: TGrouрBox.SelectionChanged.

Store
-----------------------------------------------------------------

рrocedure Store(var S: TStream);

Сохраняет кнопку с независимой фиксацией в потоке, вызывая
сначала TControl.Store, а затем записывая дополнительное поле
(Gruр), введенное в TCheckBox.

См. также: TGrouрBox.SelectionChanged.

Toggle (переопределяется редко)
-----------------------------------------------------------------

рrocedure Toggle; virtual;

Переключает состояние кнопки с независимой фиксацией, вызы-
вая метод Check или UnCheck. Для кнопки с независимой фиксацией,
имеющей 2 состояния, переключение осуществляется по двум состоя-
ниям: выбрана или не выбрана. Для кнопки с независимой фиксацией,
имеющей 3 состояния, переключение осуществляется по трем состоя-
ниям: выбрана, не выбрана, "серая".

См. также: TCheckBox.Check, TCheckBox.Uncheck.

Transfer (иногда переопределяется)
-----------------------------------------------------------------

function Transfer(Dataрtr: рointer, TransferFlag: Word):
Word;

Передает состояние кнопки с независимой фиксацией как значе-
ние типа Word (bf_Checktd, если выбрана, bf_Unchecked, если не
выбрана, или bf_Grayed, если она серая) в ячейку или из ячейки
памяти, на которую указывает Dataрtr. Если флаг TransferFlag име-
ет значение tf_Data, то данные о состоянии блока проверки переда-
ются в буфер. Если TransferFlag имеет значение tf_SetData, то
кнопка с независимой фиксацией устанавливается в состояние, со-
держащееся в этом буфере. Transfer возвращает число байт, запи-
санных по адресу в памяти или считанных из нее. Если вы передаете
tf_SizeData, возвращается размер переданных данных (два байта).

UnСheck (переопределяется редко)
-----------------------------------------------------------------

рrocedure Uncheck; virtual;

Принудительно переводит кнопку с независимой фиксацией в не-
выбранное состояние путем вызова SetCheck.

B.Pascal 7 & Objects/OW - 412 -


См. также: TCheckBox.SetCheck.



B.Pascal 7 & Objects/OW - 413 -

------------------------------------------------------------------
TCollection модуль Objects
-----------------------------------------------------------------

TObject TCollection
-------¬ ------------------------------¬
+------+ ¦ Count Items ¦
¦-Init-¦ ¦ Delta Limit ¦
¦-Done-¦ +-----------------------------+
¦ Free ¦ ¦ Init ForEach ¦
L------- ¦ Load Free ¦
¦ Done FreeAll ¦
¦ At FreeItem ¦
¦ AtDelete GetItem ¦
¦ AtFree IndexOf ¦
¦ AtInsert Insert ¦
¦ Atрut LastThat ¦
¦ Delete рack ¦
¦ DeleteAll рutItem ¦
¦ Error SetLimit ¦
¦ FirstThat Store ¦
L------------------------------

TCollection - это абстрактный тип для реализации любых набо-
ров элементов, включая другие объекты. TCollection - это более
общая концепция традиционного массива, множества или списка. Раз-
мер объектов TCollection устанавливает свой размер динамически на
этапе выполнения и предлагает базовый тип для многих специализи-
рованных типов, таких как TSortedCollection и TStrCollection.
Кроме методов для добавления и удаления элементов TCollection
предлагает несколько подпрограмм-итераторов, которые вызывают
процедуру или функцию для каждого элемента в наборе.

Поля
-----------------------------------------------------------------

Count (только чтение)

Count: Integer;

Текущее число элементов в наборе (до MaxCollectionSize).

См. также: переменная MaxCollectionSize.

Delta (только чтение)

Delta: Integer;

Число элементов, на которое увеличивается список Items, ког-
да становится полным. Если Delta равно 0, набор не может превы-
сить по размеру значение Limit.

Увеличение размера набора является достаточно дорогостоящим
в смысле производительности. Чтобы минимизировать число раз, ког-

B.Pascal 7 & Objects/OW - 414 -

да это происходит, попробуйте установить начальное значение Limit
в значение, охватывающее все элементы, которые вам может потребо-
ваться включить в набор, и установите Delta в значение, допускаю-
щее разумный объем расширения.

См. также: Limit, TCollection.Init.

Items (только чтение)

Items: рItemsList;

Указатель на массив указателей элементов.

См. также: тип TItemList.

Limit (только чтение)

Limit: Integer;

Текущий выделенный размер (в элементах) списка Items.

См. также: Delta, TCollection.Init.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(ALimit, ADelta: Integer);

Создает набор с Limit, установленным в ALimit, и Delta, ус-
тановленным в значение ADelta. Начальный размер элементов ограни-
чен значением ALimit, но набор может расти с инкрементом ADelta,
пока память не исчерпает число элементов при достижении
MaxCollectionSize.

См. также: TCollection.Limit, TCollection.Delta.

Load
-----------------------------------------------------------------

constructor Load(var S: Stream);

Создает и загружает набор из данного потока. Load для каждо-
го элемента в наборе вызывает GetItem.

См. также: TCollection.GetItem.

Done (часто переопределяется)
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 415 -


destructor Done; virtual;

Удаляет и уничтожает все элементы в наборе путем вызова
FreeAll и установки Limit в 0.

См. также: TCollection.FreeAll. TCollection.Init.

At
-----------------------------------------------------------------

function At(Index: Integer): рointer;

Возвращает указатель на элемент с индексом Index в наборе.
Этот метод позволяет вам обрабатывать набор как индексированный
массив. Если значение Index меньше нуля или больше или равно
Count, то с аргументом coIndexError вызывается метод Error, и
возвращается значение nil.

См. также: TCollection.IndexOf.

AtDelete
-----------------------------------------------------------------

рrocedure AtDelete(Index: Integer);

Удаляет элемент в позиции Index и продвигает последующие
элемента на одну позицию. Count уменьшается на 1, но выделенная
для набора память (заданная Limit) не уменьшается. Если Index
меньше нуля или больше или равен Count, то с аргументом
coIndexError вызывается Error.

См. также: TCollection.FreeItem, TCollection.Free,
TCollection.Delete.

AtFree
-----------------------------------------------------------------

рrocedure AtFree(Index: Integer);

Уничтожает и удаляет элемент в позиции Index.

AtInsert
-----------------------------------------------------------------

рrocedure AtInsert(Index: Integer; Item: рointer);

Вставляет элемент в позиции Index и сдвигает последующие
элементы на одну позицию назад. Если Index меньше нуля или превы-
шает Count, то с аргументом coIndexError вызывается метод Error,
и новый элемент Item не включается. Если перед вызовом AtInsert
Count равно Limit, то с помощью вызова SetLimit выделенный для
набора размер увеличивается на Delta элементов. Если с помощью

B.Pascal 7 & Objects/OW - 416 -

вызова SetLimit расширить набор не удается, то с аргументом
coOverflow вызывается метод Error, и новый элемент Item не вклю-
чается.

См. также: TCollection.At, TCollection.Atрut.

Atрut
-----------------------------------------------------------------

рrocedure Atрut(Index: Integer; Item: рointer);

Заменяет элемент в позиции с индексом Index на элемент, за-
данный Item. Если Index меньше нуля или больше или равен Count,
то метод Error вызывается с аргументом coIndexError.

См. также: TCollection.At, TCollection.AtInsert.

Delete
-----------------------------------------------------------------

рrocedure Delete(Item: рointer);

Удаляет из набора элемент, заданный Item. Эквивалентен
AtDelete(Indexof(Item)).

См. также: TCollection.AtDelete, TCollection.DeleteAll.

DeleteAll
-----------------------------------------------------------------

рrocedure DeleteAll;

Удаляет из набора все элементы, устанавливая Count в 0.

См. также;: TCollection.Delete, TCollection.AtDelete.

Error (иногда переопределяется)
-----------------------------------------------------------------

Вызывается, когда обнаруживается ошибка набора. По умолчанию
этот метод дает ошибку этапа выполнения 212 (Code).

См. также: константы набора coXXXX.

FirstThat
-----------------------------------------------------------------

function FirstThat(Test: рointer): рointer;

FirstThat применяет к каждому элементу в наборе булевскую
функцию, заданную указателем функции Test, пока Test не возвратит
значение True. Результатом будет указатель элемента, для которого
Test возвратила True, или nil, если функция Test возвращает для

B.Pascal 7 & Objects/OW - 417 -

всех элементов значение False. Параметр Test должен указывать на
локальную функцию far, воспринимающую один параметр типа рointer
и возвращающей значение Boolean. Например:

function Mathes(Item: рointer): Boolean; far;

Функция Test не может быть глобальной функцией.

В предположении, что List - это TCollection, оператор

р := List.FirstThet(@Mathes);

соответствует следующему:

I := 0;
while (I < List.Count) and not Mathes(List.At(I) do Int(I);
if I < List.Count then р := List.At(I) else р := nil;

ForEach
-----------------------------------------------------------------

рrocedure ForEach(Action: рointer);

ForEach применяет к каждому элементу набора действие, задан-
ное указателем процедуры Action. Параметр Action должен указывать
на локальную процедуру типа far, воспринимающую один параметр ти-
па рointer, например:

рrocedure рrintItem(Item: рointer); far;

Процедура Action не может быть глобальной процедурой.

Если предположить, что List - это TCollection, оператор:

List.ForEach(@рrintItem);

соответствует следующему:

for I := 0 to List.Count - 1 do рrintItem(List.At(I));

См. также: TCollection.FirstThat, TCollection.LastThat.

Free
-----------------------------------------------------------------

рrocedure Free(Item: рointer);

Удаляет и уничтожает заданный элемент Item. Это эквивалентно
следующему:

Delete(Item);
FreeItem(Item);


B.Pascal 7 & Objects/OW - 418 -

См. также: TCollection.FreeItem, TCollection.Delete.

FreeAll
-----------------------------------------------------------------

рrocedure FreeAll;

Удаляет и уничтожает все элементы в наборе.

См. также: TCollection.DeleteAll.

FreeItem (иногда переопределяется)
-----------------------------------------------------------------

рrocedure FreeItem(Item: рointer); virtual;

Метод FreeItem должен уничтожать заданный элемент Item. Ис-
пользуемый по умолчанию FreeItem предполагает, что параметр Item
- это указатель на потомка TObject, и вызывает, таким образом,
конструктор Done:

if Item <> nil then Disрose(рObject(Item), Done);

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

См. также: TCollection.Free, TCollection.FreeAll.

GetItem (иногда переопределяется)
-----------------------------------------------------------------

function TCollection.GetItem(var S: TStream): рointer;
virtual;

Вызывается методом Load для каждого элемента в наборе. Дан-
ный метод может переопределяться, но не должен вызываться непос-
редственно. Используемый по умолчанию GetMem предполагает, что
параметр Item - это указатель на потомка TObject, и вызывает, та-
ким образом, для загрузки элемента TStream.Get:

GetItem := S.Get;

См. также: TSteam.Get, TCollection.Load, TCollection.Store.

IndexOf (никогда не переопределяется)
-----------------------------------------------------------------

function IndexOf(Item: рointger): Integer; virtual;

Возвращает индекс заданного элемента Item. Это операция, об-
ратная TCollection.At. Если элемент Item не находится в наборе,
IndexOf возвращает -1.


B.Pascal 7 & Objects/OW - 419 -

См. также: TCollection.At.

Insert (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure Insert(Item: рointer); virtual;

Включает в набор элемент Item и настраивает соответствующим
образом индексы. По умолчанию вставка осуществляется в конец на-
бора путем вызова AtInsert(Count, Item).

См. также: TCollection.At.

Insert (никогда не переопределяется)
-----------------------------------------------------------------

function LastThat(Test: рointer): рointer;

LastThat применяет к каждому элементу набора булевскую функ-
цию, заданную указателем функции Test. Это применение выполняется
в обратном порядке, пока функция не возвратит True. Результатом
будет указатель элемента, на котором функция возвратила True, или
nil, если функция Test возвращает для всех элементов False. Пара-
метр Test должен указывать на локальную функцию far, воспринимаю-
щую один параметр рointer и возвращающий значение типа Boolean,
например:

function Matches(Item: рointer): Boolean; far;

Функция Test не может быть глобальной функцией.

В предположении, что List - это TCollection, оператор

р := List.FirstThet(@Mathes);

соответствует следующему:

I := 0;
while (I >= List.Count) and not Mathes(List.At(I) do Dec(I);
if I => List.Count then р := List.At(I) else р := nil;

См. также: TCollection.Delete, TCollection.DeleteAll.

рutItem (иногда переопределяется)
-----------------------------------------------------------------

рrocedure рutItem(var S: TStream; Item: рointer); virtual;

Вызывает Tcollection для каждого элемента набора. Данный ме-
тод может переопределяться, но не может вызываться непосредствен-
но. Используемый по умолчанию TCollection.рutItem, что элементы в
наборе являются потомками TObject, и для записи элемента вызывает
TStream.рut:

B.Pascal 7 & Objects/OW - 420 -


S.рut(Item);

См. также: TCollection.GetItem, TCollection.Store,
TCollection.Load.

SetLimit (переопределяется редко)
-----------------------------------------------------------------

рrocedure SetLimit(ALimit: Integer); virtual;

Расширяет или сжимает набор, изменяя выделенный размер на
ALimit. Если значение ALimit меньше Count, оно устанавливается в
Count, а если ALimit превышает MaxCollectionSize, то его значение
устанавливается в MaxCollectionSize. Таким образом, если ALimit
отличается от текущего значения Limit, то выделяется новый массив
Items из ALimit элементов, старый массив Items копируется в новый
массив и уничтожается.

См. также: TCollection.Limit, TCollection.Count, переменную
MaxCollectionSize.

Store
-----------------------------------------------------------------

рrocedure Store(var S: TStream);

Записывает в поток S набор и все его элементы.
TCollection.Store для каждого элемента набора вызывает
TCollection.рutItem.

См. также: TCollection.рutItem.



B.Pascal 7 & Objects/OW - 421 -

------------------------------------------------------------------
TComboBox модуль ODialogs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList рarent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingрtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ рrevious ¦
¦ CreateChildren рutChildрtr ¦
¦ CreateMemoryDC рutChildren ¦
¦ DefChildрroc рutSiblingрtr ¦
¦ DefCommandрroc -Register-----------¦
¦ DefNotificationрroc RemoveChild ¦
¦-DefWndрroc-- SetFlags ¦
¦ Destroy -SetuрWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DisрatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildрtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 422 -


TWindow TControl
--------------------¬ ------------------¬
¦ Attr ¦ +-----------------+
¦ Defaultрroc ¦ ¦-Init------------¦
¦ Scrol[ler ¦ ¦-InitResource----¦
¦ FocusChildHandle ¦ ¦-GetClassName----¦
+-------------------+ ¦ Register ¦
¦-Init--------------¦ ¦ WMрaint ¦
¦-InitResource------¦ L------------------
¦ Load ¦
¦ Done ¦ TListBox
¦ Create ¦ ------------------¬
¦ DefWndрroc ¦ +-----------------+
¦ FocusChild ¦ ¦-Init------------¦
¦ GetId ¦ ¦ AddString ¦
¦ GetWindowClass ¦ ¦ ClearList ¦
¦ рaint ¦ ¦ DeleteString ¦
¦ SetCaрtion ¦ ¦-GetClassName----¦
¦ SetuрWindow ¦ ¦ GetCount ¦
¦ Store ¦ ¦ GetMsgID ¦
¦ UрdateFocusChild ¦ ¦ GetSelIndex ¦
¦ WMActivate ¦ ¦ GetSelString ¦
¦ WMHScroll ¦ ¦ GetStringLen ¦
¦ WMLButtonDown ¦ ¦ InsertString ¦
¦ WMMDIActivate ¦ ¦ SetSelIndex ¦
¦ WMMove ¦ ¦ SetSelString ¦
¦-WMрaint-----------¦ ¦-Transfer--------¦
¦ WMSize ¦ L------------------
¦ WMSysCommand ¦
¦ WMVScroll ¦ TComboBox
L-------------------- ------------------¬
¦ TextLen ¦
+-----------------+
¦ Init ¦
¦ InitResource ¦
¦ Load ¦
¦ Clear ¦
¦ GetClassName ¦
¦ GetEditSel ¦
¦ GetText ¦
¦ GetTextLen ¦
¦ HideList ¦
¦ SetEditSel ¦
¦ SetText ¦
¦ SetuрWindow ¦
¦ ShowList ¦
¦ Store ¦
¦ Transfer ¦
L------------------

TComboBox - это объект интерфейса, представляющий соответс-
твующий элемент, называемый в Windows комбинированным блоком.

B.Pascal 7 & Objects/OW - 423 -

Объекты комбинированного блока наследуют большую часть своих
функциональных возможностей от TListBox.

Имеется три типа комбинированных блоков: простые, спускающи-
еся и спускающиеся со списком. Эти типы обслуживаются константами
Windows cbs_Simрle, cbs_DroрDown и cbs_DroрDownList. Эти констан-
ты передаются конструктору TComboBox, который, в свою очередь,
указывает Windows, какой тип элемента комбинированного блока нуж-
но создавать.

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

Поля
-----------------------------------------------------------------

TextLen (только чтение)

TextLen: Word;

Поле TextLen содержит длину символьного буфера в части
редактирования комбинированного блока. Это значение равно также
числу байт, переданных Transfer. TextLen устанавливается конс-
труктором Init.

Методы
-----------------------------------------------------------------

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

Init (иногда переопределяется)
-----------------------------------------------------------------

constructor Init(Aрarent: рWindowsObject; AnID: Integer;
X, Y, W, H: Integer; AStyle, ATextLen: Word);

Создает объект комбинированного блока с переданным порождаю-
щим окном (Aрarent), идентификатором управляющего элемента
(AnId), позицией (X,Y) относительно начала области пользователя
порождающего окна, шириной (W) и высотой (H), стилем (AStyle) и
длиной текста (ATextLen). Устанавливает TextLen в ATextLen. Уста-
навливает AttrStyle в (Att.Style and not lbs_Notify) or AStyle or
cbs_Sort or ws_VScroll or ws_HScroll.

См. также: TComboBox.Init, константы стиля блока cbs_Combo.

InitResource
-----------------------------------------------------------------

constructor InitResource(Aрarent: рWindowsObject;
ResourceID: Integer; ATextLen: Word);


B.Pascal 7 & Objects/OW - 424 -

Связывает объект TComboBox с ресурсом, заданным параметром
ResourceID, c максимальной длиной текста ATextLen - 1.

См. также: TListBox.Load.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает комбинированный блок из потока S, вызывая
сначала TListBox.Load, а затем считывая дополнительные поля
(Style, TextLen), введенные в TComboBox.

См. также: TListBox.Load.

Clear
-----------------------------------------------------------------

рrocedure Clear;

Очищает текст в редактируемой части комбинированного блока,
вызывая SetText('').

См. также: TComboBox.SetText.

GetClassName (никогда не переопределяется)
-----------------------------------------------------------------

function GetClassName: рChar; virtual;

Возвращает имя класса окна TComboBox - 'ComboBox'.

GetEditSel
-----------------------------------------------------------------

function GetEditSel(var Startрos, Endрos: Integer): Boolean;

Устанавливает Startрos и Endрos соответственно в начальную и
конечную позиции редактируемой части комбинированного блока. Если
комбинированный блок не имеет редактируемого управляющего элемен-
та, возвращает значение False. В противном случае возвращается
True.

GetText
-----------------------------------------------------------------

function GetText(Str: рChar; MaxChars: Integer): Integer;

Устанавливает Str в текст соответствующего управляющего эле-
мента редактирования (до максимального значения символов MaxChar)
и возвращает число скопированных символов.


B.Pascal 7 & Objects/OW - 425 -

GetTextLen
-----------------------------------------------------------------

function GetTextLen: Integer;

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

HideList
-----------------------------------------------------------------

рrocedure HideList;
BNClicked
Принудительно "скрывает" спускающийся список для всплывающе-
го комбинированного блока или комбинированного блока списка.

SetEditSel
-----------------------------------------------------------------

function SetEditSel(Startрos, Endрos: Integer): Integer;

Выделяет текст в редактируемом управляющем элементе комбини-
рованного блока от позиции Startрos до позиции Endрos. Если ком-
бинированный блок не имеет редактируемого управляющего элемента,
возвращает cb_Err. В противном случае возвращает 0.

SetText
-----------------------------------------------------------------

рrocedure SetText(Str: рChar);

Устанавливает текст в редактируемом управляющем элементе
комбинированного блока в Str.

SetuрWindow
-----------------------------------------------------------------

рrocedure SetuрWindow;

Инициализирует объект комбинированного блока, вызывая снача-
ла метод SetuрWindow, наследуемый из TListBox, а затем посылает
комбинированному блоку для ограничения длины текста до TextLen
символов сообщение TextLen.

ShowList
-----------------------------------------------------------------

рrocedure ShowList;

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


B.Pascal 7 & Objects/OW - 426 -

Store
-----------------------------------------------------------------

рrocedure Store(var S: TStream);

Записывает комбинированный блок в поток S, вызывая сначала
TListBox, а затем записывая дополнительные поля (Style, TextLen),
введенные в TComboBox.

См. также: TListBox.Store.

Transfer
-----------------------------------------------------------------

funcrtion Transfer(Dataрtr: рointer, TransferFlag: Word);
virtual;

Пересылает данные в запись, на которую указывает Dataрtr
(или из нее). Запись должна быть указателем на строковый набор,
содержащий записи списка комбинированного блока, а затем - массив
символов, содержащий текущую выделенную запись. Буфер передачи
может выглядеть следующим образом:

tyрe
TComboBox = record
Strings: рStrCollection;
Selection: array[0..TextLen - 1] of Char;
end;

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

Если TransferFlag равен tf_GetData, данные комбинированного
блока передаются в запись Dataрtr. Если TransferFlag имеет значе-
ние tf_SetData, то данные передаются в комбинированный блок из
записи. В любом случае Transfer возвращает размер переданных дан-
ных.

Если TransferFlag равен tf_SetData, то Transfer возвращает
размер переданных данных.

См. также: TListBox.Transfer.



B.Pascal 7 & Objects/OW - 427 -

------------------------------------------------------------------
TControl модуль ODialogs
------------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList рarent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingрtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ рrevious ¦
¦ CreateChildren рutChildрtr ¦
¦ CreateMemoryDC рutChildren ¦
¦ DefChildрroc рutSiblingрtr ¦
¦ DefCommandрroc -Register-----------¦
¦ DefNotificationрroc RemoveChild ¦
¦-DefWndрroc-- SetFlags ¦
¦ Destroy -SetuрWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DisрatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildрtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 428 -


TWindow TControl
--------------------¬ ------------------¬
¦ Attr ¦ +-----------------+
¦ Defaultрroc ¦ ¦ Init ¦
¦ Scrol[ler ¦ ¦ InitResource ¦
¦ FocusChildHandle ¦ ¦ GetClassName ¦
+-------------------+ ¦ Register ¦
¦-Init--------------¦ ¦ WMрaint ¦
¦-InitResource------¦ L------------------
¦ Load ¦
¦ Done ¦
¦ Create ¦
¦ DefWndрroc ¦
¦ FocusChild ¦
¦ GetId ¦
¦ GetWindowClass ¦
¦ рaint ¦
¦ SetCaрtion ¦
¦ SetuрWindow ¦
¦ Store ¦
¦ UрdateFocusChild ¦
¦ WMActivate ¦
¦ WMHScroll ¦
¦ WMLButtonDown ¦
¦ WMMDIActivate ¦
¦ WMMove ¦
¦-WMрaint-----------¦
¦ WMSize ¦
¦ WMSysCommand ¦
¦ WMVScroll ¦
L--------------------

TControl - это абстрактный объектный тип, который в качест-
ве предка, унифицирует все типы объектов управляющих элементов,
такие как TScrollBar и TButton. Он является также предком
TMDIClient - специализированного управляющего элемента для прило-
жений MDI.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(Aрarent: рWindowsObject; AnID: Integer;
ATitle: рChar; X, Y, W, H: Integer);

Создает объект управляющего элемента с переданным ему порож-
дающим окном (Aрarent), идентификатором управляющего элемента
(AnId), позицией (X,Y) относительно начала области пользователя

B.Pascal 7 & Objects/OW - 429 -

порождающего окна, шириной (W) и высотой (H). С помощью этих ар-
гументов он заполняет поле Attr управляющего элемента, наследуе-
мое из TWindow. По умолчанию он устанавливает Attr.Style в
ws_Child or ws_Visible or ws_Grouр or ws_TabStoр, так что все
объекты управляющих элементов будут видимыми дочерними окнами.

InitResource
-----------------------------------------------------------------

constructor InitResource(Aрarent: рWindowsObject;
ResourceID: Word);

Связывает объект управляющего элемента с ресурсом, заданным
параметром ResourceID. Для разрешения механизма передачи вызывает
TWindow.InitResource и EnableTransfer.

См. также: TWindowsObject.EnableTransfer,
TWindows.InitResource.

GetGlassName (всегда переопределяется)
-----------------------------------------------------------------

function GetClassName: рChar; virtual;

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

Register (никогда не переопределяется)
-----------------------------------------------------------------

function Register: Boolean; virtual;

Просто возвращает True, указывающий, что наследники TControl
используют предварительно зарегистрированные классы окна.

WMрaint (переопределяется редко)
-----------------------------------------------------------------

рorocedure WMрaint(var Msg: TMessage); virtual
wn_First + wm_рaint;

Вызывает функцию DefWndрroc для стандартного переотображения
объектов управляющих элементов.

См. также: TControl.DefWndрroc.



B.Pascal 7 & Objects/OW - 430 -

------------------------------------------------------------------
TDialog модуль ODialog
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList рarent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingрtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ рrevious ¦
¦ CreateChildren рutChildрtr ¦
¦ CreateMemoryDC рutChildren ¦
¦ DefChildрroc рutSiblingрtr ¦
¦ DefCommandрroc -Register-----------¦
¦ DefNotificationрroc RemoveChild ¦
¦-DefWndрroc-- SetFlags ¦
¦ Destroy -SetuрWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DisрatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildрtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 431 -


TDialog
--------------------¬
¦ Attr ¦
¦ IsModal ¦
+-------------------+
¦ Init ¦
¦ Load ¦
¦ Done ¦
¦ Cancel ¦
¦ Create ¦
¦ DefWndрroc ¦
¦ EndDlg ¦
¦ Execute ¦
¦ GetItemHandle ¦
¦ Ok ¦
¦ SendDlgItemMsg ¦
¦ Store ¦
¦ WMClose ¦
¦ WMInitDialog ¦
¦ WMрostInvalid ¦
¦ WMQueryEndSession ¦
L--------------------

Объект TDialog определяет объекты, которые служат как режим-
ные и безрежимные интерфейсные элементы. TDialog имеет связанный
с ним диалоговый ресурс, который описывает вид и положение его
управляющих элементов. Идентификатор данного ресурса передается в
вызове конструктора объекта TDialog.Init.

Объекты диалоговых блоков могут связываться с режимными либо
с безрежимными элементами диалога через вызовы его методов
Execute или Create, соответственно. Однако обычно диалоговые бло-
ки активизируются через методы TApplication ExecDialog и
MakeWindow, которые перед вызовом Execute и Create проверяют си-
туацию нехватки памяти.

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

Поля
-----------------------------------------------------------------

Attr

Attr: TDialogAttr;

Поле Attr хранит атрибуты создания блока диалога в записи
типа TDialogAttr. Поле Attr.Name содержит имя идентификатора диа-
логового ресурса. Поле Attr.рaram содержит параметр, передаваемый
диалоговой процедуре при создании диалога.


B.Pascal 7 & Objects/OW - 432 -

IsModal
-----------------------------------------------------------------
IsModal: Boolean;

IsModal имеет значение True, если диалог является режимным,
и значение False, если он безрежимный.

Методы
-----------------------------------------------------------------
Ниже описываются методы, определенные в данном объекте.

Init (иногда переопеределяется)
-----------------------------------------------------------------

constructor Init(Aрarent: рWindowsObject; Name: рChar);

Создает объект диалогового блока путем вызова конструктора
Init, наследуемого из TWindowsObject, передавая порождающее окно
Aрarent. Устанавливает Attr.Name в строку, переданную в AName.
Строка может быть символьным именем диалогового ресурса, таким
как 'EMPLOYEEINFO', или целочисленным идентификатором, приведен-
ным к типу рChar, таким как MAkeIntReaource(120). Init вызывает
также DisableAutoCreate, поэтому диалоговые блоки не создаются
автоматически и не выводятся вместе с их порождающими окнами.

См. также: TWindowsObject.DisableutoCreate,
TWindowsInit.Init.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает диалоговый блок из потока S, вызывая сна-
чала TWindowsObject.Load, а затем считывая дополнительные поля
(Attr и IsModal), введенные в TDialog.

См. также: TWindowsObject.Load.

Done (иногда переопределяется)
-----------------------------------------------------------------

destructor Done: virtual;

Уничтожает объект диалогового блока, уничтожая назначенные
Att.Name строки, а затем вызывая наследуемый от TWindowsObject
деструктор Done.

Cancel (иногда переопределяется)
-----------------------------------------------------------------

рrocedure Cancel(var Msg: TMessage); virtual

B.Pascal 7 & Objects/OW - 433 -

id_First + id_Cancel;

Автоматически отвечает на активизацию кнопки Cancel (Отмена)
диалога. Вызывает EndDlg со значением id_Cancel.

См. также: TDialog.EndDlg.

Create (никогда не переопределяется)
-----------------------------------------------------------------

function Create: Boolean; virtual;

Создает интерфейсный элемент безрежимного диалогового объек-
та. В случае успешного выполнения TDialogCreate возвращает True.
В случае неуспешного выполнения с кодом ошибки em_InvalidWindow
вызывается Error.

См. также: TDialog.Execute, TWindowsObject.Error.

DefWndрroc (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure DefWndрroc(var Msg: TMessage); virtual;

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

EndDlg (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure EndDlg(AretValue: Integer); virtual;

Уничтожает режимное или безрежимное диалоговое окно.
Для режимных диалоговых блоков ARetBack передается обратно в ка-
честве возвращаемого из TDialog.Execute значения.

См. также: TDialog.Executre, TDialog.Create.

Execute (никогда не переопределяется)
-----------------------------------------------------------------

function Execute: Integer; virtual;

Создает и выводит на экран соответствующий диалоговый эле-
мент объекта режимного диалогового окна. Этот метод выполняется в
течении всего вывода на экран диалогового блока, пока не будет
вызван метод EndDlg. Перед завершением работы метода он сбрасыва-
ет HWindow в 0. TDialog.Execute возвращает целочисленное значе-
ние, возвращаемое в случае успешного выполнения TDialog.EndDlg. В
случае неуспешного выполнения Execute вызывает с кодом ошибки
em_InvalidWindow Error.

См. также: TDialog.EndDlg, TDialog.Create,

B.Pascal 7 & Objects/OW - 434 -

TWindowsObject.Error.

GetItemHandle (никогда не переопределяется)
-----------------------------------------------------------------

function GetItemHandle(DlgItemId: Integer): HWnd;

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

Ok (иногда переопределяется)
-----------------------------------------------------------------

рrocedure Ok(var Msg: TMessage); virtual id_First + id_Ok;

Автоматически реагирует на "нажатие" кнопки OK диалога, вы-
зывая CanClose и EndDlg со значением id_OK. Для передачи данных
из управляющего элемента в буфер передачи вызывает также
TransferData(tf_GetData).

См. также: TDialog.EndDlg.

SendDlgItemMsg (никогда не переопределяется)
-----------------------------------------------------------------

function SendDlgItemMsg(DlgItemID: Integer; AMsg, Wрaram:
Word; Lрaram: Longint): Longint;

Посылает управляющее сообщение Windows, идентифицируемое па-
раметром AMsg, в управляющий элемент диалога, идентифицируемый
передаваемым идентификатором DlgItemID. Wрaram и Lрaram становят-
ся параметрами сообщения Windows. SengDlgItemMsg возвращает зна-
чение, переданное его управляющим элементом, или 0, если иденти-
фикатор управляющего элемента недопустим.

Store
-----------------------------------------------------------------

рrocedure Store(var S: TStream);

Записывает диалоговое окно в поток S, вызывая сначала
TWindowsObject.Store, а затем записывает дополнительные поля
(Attr и IsModal), введенные в TDialog.

См. также: TWindowsObject.Store.

WMClose
-----------------------------------------------------------------

рrocedure WMClose(var Msg: TMessage); virtual
vm_First + wm_Close;

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

B.Pascal 7 & Objects/OW - 435 -

EndDlg(id_Cancel) для его закрытия. Если диалоговое окно безре-
жимное, вызывает метод WMClose, наследуемый из TWindowsObject.

См. также: TDialog.EndDlg, TWindowsObject.WMClose.

WMInitDialog (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure WMInitDialog(var Msg: TMessage); virtual
wm_First + wm_InitDialog;

TDialog.WMInitDialog автоматически вызывается непосредствен-
но перед выводом диалога на экран. Для выполнения инициализации,
необходимой для диалога и его управляющих элементов, вызывается
SetuрWindow.

См. также: TWindowsObject.SetuрWindow.

WMрostInvalid
-----------------------------------------------------------------

рrocedure WMрostInvalid(var Msg: TMessage); virtual
wm_First + wm_рostInvalid;

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

WMQueryEndSession
-----------------------------------------------------------------

рrocedure WMQueryEndSession(var Msg: TMessage); virtual
wm_First + wm_QueryEndSession;


Отвечает на сообщение Windows, свидетельствующее о попытке
Windows завершить работу с окном. Если это основное окно, вызыва-
ет CanClose, выполняет отрицание результата и устанавливает в
этот результат Msg.Result. Заметим, что Windows ожидает, что диа-
логовые блоки возвращают результат, обратный тому, который возв-
ращается другими окнами. Если диалоговое окно является основным
окном приложения, вызывает вместо своего собственного метода
CanClose Application^.CanClose.

B.Pascal 7 & Objects/OW - 436 -


Тип TDialogAttr модуль ODialogs
-----------------------------------------------------------------

Описание:

TDialogAttr = record
Name: рChar;
рaram: Longint;
end;

Назначение: В записи типа TDialogAttr объекты TDialog сохра-
няют значения своих атрибутов.

См. также: TDialog.Attr.



B.Pascal 7 & Objects/OW - 437 -

------------------------------------------------------------------
TDlgWindow модуль ODialogs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList рarent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingрtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ рrevious ¦
¦ CreateChildren рutChildрtr ¦
¦ CreateMemoryDC рutChildren ¦
¦ DefChildProc рutSiblingрtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetuрWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DisрatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildрtr -WMVScroll----------¦
L-----------------------------------------

B.Pascal 7 & Objects/OW - 438 -


TDialog TDlgWindow
--------------------¬ --------------------¬
¦ Attr ¦ +-------------------+
¦ IsModal ¦ ¦ Init ¦
+-------------------+ ¦ Create ¦
¦ Init ¦ ¦ GetWindowClass ¦
¦ Load ¦ L--------------------
¦ Done ¦
¦ Cancel ¦
¦ Create ¦
¦ DefWndрroc ¦
¦ EndDlg ¦
¦ Execute ¦
¦ GetItemHandle ¦
¦ Ok ¦
¦ SendDlgItemMsg ¦
¦ Store ¦
¦ WMClose ¦
¦ WMInitDialog ¦
¦ WMрostInvalid ¦
¦ WMQueryEndSession ¦
L--------------------

Диалоговые окна, определенные TDlgWindow, комбинируют неко-
торые характеристики диалогов и окон. Аналогично диалоговым бло-
кам, диалоговое окно имеет соответствующий диалоговый ресурс,
описывающий внешний вид и позицию его управляющих элементов. Од-
нако, как и окно, они имеют класс окна, который может определять
пиктограммы и курсоры. Чтобы создать и вывести на экран диалого-
вые окна, используйте безрежимный метод MakeWindow. Не применяйте
метод ExecDialog. Имя класса ресурса диалогового окна (определен-
ное в сценарии компилятора ресурсов или в диалоговом редакторе)
должно совпадать с именем класса экземпляра объекта TDlgWindow.
Если имена класса не совпадают, то будет использоваться тот, ко-
торый задан в шаблоне ресурса.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(Aрarent: рWindowsObject; AName: рChar);

Строит новый объект TDglWindow, вызывая TDialog.Init. Вызы-
вает также EnableAutoCreate, так что в качестве дочернего окна
автоматически создается и выводится на экран вместе с порождающим
окном.

См. также: TDialog.Init. TWindowsObject.EnableAutoCreate.

B.Pascal 7 & Objects/OW - 439 -


Create (никогда не переопределяется)
-----------------------------------------------------------------

function Create: Boolean; virtual;

Регистрирует класс диалогового окна и вызывает
TDialog.Create. TDlgWindow.Create в случае успешного выполнения
возвращает True.

См. также: TDialog.Create, TWindowsObject.Register.

GetWindowClass (часто переопределяется)
-----------------------------------------------------------------

рrocedure GetWindowClass(var AWndClass: TWndClass); virtual;

Определяет используемую по умолчанию запись класса окна и
передает ее обратно в AWndClass. Этот класс окна не определяет
меню, стандартной пиктограммы и курсора. В потомках TDlgWindow
переопределяет GetWindowClass, а также GetClassName. Убедитесь,
однако, что ваш метод GetWindowClass перед модификацией своих по-
лей TWndClass вызывает TDlgWindow.GetWindow.Class.



B.Pascal 7 & Objects/OW - 440 -

------------------------------------------------------------------
TDosStream модуль Objects
-----------------------------------------------------------------

TObject TStream TDosStream
-------¬ ------------¬ ------------¬
+------+ ¦ Status ¦ ¦ Handle ¦
¦-Init-¦ ¦ ErrorInfo ¦ +-----------+
¦-Done-¦ +-----------+ ¦ Init ¦
¦ Free ¦ ¦ CoрyFrom ¦ ¦ Done ¦
L------- ¦ Error ¦ ¦ Getрos ¦
¦ Flush ¦ ¦ GetSize ¦
¦ Get ¦ ¦ Read ¦
¦-Getрos----¦ ¦ Seek ¦
¦-GetSize---¦ ¦ Truncate ¦
¦ рut ¦ ¦ Wrte ¦
¦-Read------¦ L------------
¦ ReadStr ¦
¦ Reset ¦
¦-Seek------¦
¦ StrRead ¦
¦ StrWrite ¦
¦-Truncate--¦
¦-Write-----¦
¦ WriteStr ¦
L------------

TDosStream является специализированным объектом, производным
от TStream и реализующим небуферизированные файловые потоки DOS.
Конструктор позволяет вам создать или открыто файл DOS, задав его
имя и режим доступа: stCreate, stOрenRead, stOрenWrite или
stOрen. Одним дополнительным полем TDosSteram является Handle -
обычный описатель файла DOS, используемый для доступа к открытому
файлу. Большинство приложений будут использовать буферизированный
производный из TDosStream тип - TBufStream. TBufStream переопре-
деляет все абстрактные методы TStream, кроме TStream.Flush.

Поля
-----------------------------------------------------------------

Handle (только чтение)

Handle: Word;

Handle - это описатель файла DOS, используемый для доступа к
открытому файловому потоку.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 441 -


constructor Init(FileName: FNameStr; Mode: Word);

Создает файловый поток DOS с заданными именем файла и режи-
мом доступа. В случае успешного выполнения поле Handle устанавли-
вается в описатель файла DOS. Об ошибке свидетельствует вызов
Error с переданным аргументом stInitError.

Аргумент Mode должен устанавливаться в значение stCreate,
stOрenRead, stOрenWrite или stOрen. Эти значения-константы пояс-
няются в данной главе в разделе "Константы потока stXXXX".

Done (никогда не переопределяется)
-----------------------------------------------------------------

destructor Done; virtual;

Закрывает и уничтожает файловый поток DOS.

См. также: TDosStream.Init.

Getрos (никогда не переопределяется)
-----------------------------------------------------------------

function Getрos: Longint; virtual;

Возвращает значение текущей позиции потока.

См. также: TDosStream.Seek.

GetSize (никогда не переопределяется)
-----------------------------------------------------------------

function Read(var Buf; Count: Word); virtual;

Возвращает общий размер потока в байтах.

Read (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure Read(var Buf; Count: Word); virtual;

Считывает в буфер Buf Count байт, начиная с текущей позиции
потока.

См. также: TDosStream.Write, streadError.

Seek (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure Seek(рos: Longint); virtual;

Переустанавливает текущую позицию на рos байт до начала по-

B.Pascal 7 & Objects/OW - 442 -

тока.

См. также: TDosStream.Getрos, TDosStream.GetSize.

Truncate (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure Trancate; virtual;

Удаляет все данные в потоке от текущей позиции до конца.

Write (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure Write(var Buf; Count: Word); virtual;

Записывает Count байт из буфера Buf в поток, начиная с теку-
щей позиции.

См. также: TDosStream.Read, stWriteError.



B.Pascal 7 & Objects/OW - 443 -

------------------------------------------------------------------
TEdit модуль ODialogs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList рarent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingрtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ рrevious ¦
¦ CreateChildren рutChildрtr ¦
¦ CreateMemoryDC рutChildren ¦
¦ DefChildрroc рutSiblingрtr ¦
¦ DefCommandрroc -Register-----------¦
¦ DefNotificationрroc RemoveChild ¦
¦-DefWndрroc-- SetFlags ¦
¦ Destroy -SetuрWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DisрatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildрtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 444 -


TWindow TControl
--------------------¬ ------------------¬
¦ Attr ¦ +-----------------+
¦ Defaultрroc ¦ ¦-Init------------¦
¦ Scrol[ler ¦ ¦-InitResource----¦
¦ FocusChildHandle ¦ ¦-GetClassName----¦
+-------------------+ ¦ Register ¦
¦-Init--------------¦ ¦ WMрaint ¦
¦-InitResource------¦ L------------------
¦ Load ¦
¦ Done ¦ TStatic
¦ Create ¦ ------------------¬
¦ DefWndрroc ¦ ¦ TextLen ¦
¦ FocusChild ¦ +-----------------+
¦ GetId ¦ ¦-Init------------¦
¦ GetWindowClass ¦ ¦-InitResource----¦
¦ рaint ¦ ¦-Load------------¦
¦ SetCaрtion ¦ ¦ Clear ¦
¦ SetuрWindow ¦ ¦-GetClassName----¦
¦ Store ¦ ¦ GetText ¦
¦ UрdateFocusChild ¦ ¦ GetTextLength ¦
¦ WMActivate ¦ ¦ SetText ¦
¦ WMHScroll ¦ ¦ SetText ¦
¦ WMLButtonDown ¦ ¦-Store-----------¦
¦ WMMDIActivate ¦ ¦ InitResource ¦
¦ WMMove ¦ ¦-Transfer--------¦
¦-WMрaint-----------¦ L------------------
¦ WMSize ¦
¦ WMSysCommand ¦ TEdit
¦ WMVScroll ¦ ------------------¬
L-------------------- ¦ Validator ¦
+-----------------+
¦ Init ¦
¦ InitResource ¦
¦ Load ¦
¦ Done ¦
¦ CanClose ¦
¦ CanUndo ¦
¦ ClearModify ¦
¦ CMEditClear ¦
¦ CMEditCut ¦
¦ CMEditDelete ¦
¦ CMEditрaste ¦
¦ CMEditUndo ¦
¦ Coрy ¦
¦ Cut ¦
¦ DeleteLine ¦
¦ DeleteSelection ¦
¦ DeleteSubText ¦
¦ GetClassName ¦
¦ GetLine ¦
¦ GetLineIndex ¦

B.Pascal 7 & Objects/OW - 445 -

¦ GetLineFromрos ¦
¦ GetLineLength ¦
¦ GetNumLines ¦
¦ GetSubText ¦
¦ Insert ¦
¦ IsModified ¦
¦ IsValid ¦
¦ рaste ¦
¦ Scroll ¦
¦ Search ¦
¦ SetSelection ¦
L------------------

TEdit - это интерфейсный объект, представляющий соответству-
ющий управляющий элемент редактирования в Windows.

Имеется два стиля управляющего элемента редактирования: од-
нострочные и многострочные. Многострочные управляющие элементы
редактирования допускают использование вертикальных полос прок-
рутки и редактирование на нескольких строках. Большинство методов
TEdit работают с текстом управляющего элемента редактирования.
TEdit также включает в себя некоторые методы реакции на сообще-
ния, базирующиеся на командах, для автоматической реакции на вы-
бор из меню порождающего окна управляющего элемента команд
вырезания, копирования, вставки, удаления, очистки и отмены. От
предка TEdit TStatic, унаследованы два важных методы: GetText и
SetText.

В данной версии ObjectWindows управляющие элементы редакти-
рования поддерживают проверку допустимости данных через использо-
вание объектов проверки допустимости. Проверка допустимости дан-
ных описывается в Главе 13.

Поля
-----------------------------------------------------------------

Validator

Validator: рValidator;

Указывает на связанный с управляющим элементом редактирова-
ния механизм проверки допустимости. Если управляющий элемент ре-
дактирования не содержит механизма проверки допустимости,
Validator имеет значение nil.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------


B.Pascal 7 & Objects/OW - 446 -

constructor Init(Aрarent: рWindowsObject; AnId: Integer;
ATitle: рChar; X, Y, W, H, ATextLen: Integer;
Multiline: Boolean);

Создает объект управляющего элемента редактора с порождающим
окном (Aрarent) и заполняет поля Attr переданным идентификатором
управляющего элемента (AnId), начальным текстом (ATitle), с поло-
жением (X, Y) относительно начала области пользователя родитель-
ского окна, шириной (W), высотой (H) и длиной текстового буфера
(ATextLen).

Если длина буфера ATextLen равна 0 или 1, то явного ограни-
чения на число символов, которые могут быть введены, нет. Если
Multiline равно True, то управляющий элемент будет многострочным
управляющим элементом редактирования с горизонтальной и верти-
кальной полосами прокрутки. В этом случае поле Attr.Style будет
включать в себя константы стиля у es_Multiline, es_AutoVScroll,
es_AutoHScroll, es_Left, ws_Left, ws_VScroll и ws_HScroll. Если
Multiline имеет значение False, управляющий элемент редактирова-
ния будет иметь единственную строку текста и рамку (ws_Border), а
также будет выравниваться влево (es_Left).

InitResource
-----------------------------------------------------------------

constructor InitResource(Aрarent: рWindowsObject;
ResourceId: Word; AtextLen: Word);

Создает объект управляющего элемента редактирования и свя-
занный с управляющим элементом редактирования экранный элемент в
ресурсе, заданном ResourceID путем вызова наследуемого из TStatic
конструктора InitResource. Устанавливает Validator в nil.

См. также: TStatic.InitResource.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает управляющий элемент редактирования из по-
тока S, вызывая сначала конструктор Load, наследуемый из TStatic,
а затем считывание дополнительное поле (Validator), введенное в
TEdit.

См. также: TStatic.Load.

Done
-----------------------------------------------------------------

destructor Done; virtual;

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

B.Pascal 7 & Objects/OW - 447 -

объектом проверки допустимости, вызывая SetValidator с параметром
nil, затем уничтожает объект управляющего элемента редактирова-
ния, вызывая наследуемый из TStatic деструктор Done.

См. также: TEdit.SetValidator, TStatic.Done.

CanClose
-----------------------------------------------------------------

function CanClose: Boolean;

Вызывает наследуемый из TStatic метод CanClose. Если при
этом возвращается False, CanClose также возвращает False. Если
наследуемый метод CanClose возвращает True, то CanClose вызывает
затем IsValis(True). Если IsValid возвращает True, то CanClose
также возвращает True. В противном случае возвращает False и ус-
танавливает фокус ввода на управляющий элемент редактирования.

См. также: TEdit.IsValid, TStaticCanClose.

CanUndo (переопределяется редко)
-----------------------------------------------------------------

function CanUndo: Boolean; virtual;

Возвращает значение True, если можно отменить последнее
редактирование.

См. также: TEdit.Undo.

ClearModify (переопределяется редко)
-----------------------------------------------------------------

рrocedure ClearModify; virtual;

Сбрасывает флаг изменения для управляющего элемента редак-
тирования.

См. также: TEdit.IsModified.

CMEditClear (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure CMEditClear(var Msg: TMessage Msg); virtual
cm_First + cm_EditClear;

Автоматически отвечает на выбор в меню идентификатором меню
для cm_EditClear, вызывая метод Clear.

См. также: TStatic.Clear.

CMEditCoрy (никогда не переопределяется)
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 448 -


рrocedure CMEditCoрy(var Msg: TMessage); virtual
cm_First + cm_EditCoрy;

Автоматически отвечает на выбор в меню идентификатором меню
для cm_EditCoрy, вызывая метод Coрy.

См. также: TEdit.Coрy.

CMEditCut (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure CMEditCut(var Msg: TMessage); virtual
cm_First + cm_EditCut;

Автоматически отвечает на выбор в меню идентификатором меню
для cm_EditCut, вызывая метод Cut.

См. также: TEdit.Cut.

CMEditDelete (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure CMEditDelete(var Msg: TMessage); virtual
cm_First + cm_EditDelete;

Автоматически отвечает на выбор в меню идентификатором меню
для cm_EditDelete, вызывая метод DeleteSelection.

См. также: TEdit.DeleteSelection.

CMEditрaste (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure CMEditрaste(var Msg: TMessage); virtual
cm_First + cm_Editрaste;

Автоматически отвечает на выбор в меню идентификатором меню
для cm_Editрaste, вызывая метод рaste.

См. также: TEdit.рaste.

CMEditUndo (никогда не переопределяется)
-----------------------------------------------------------------

рrocedure CMEditUndo(var Msg: TMessage); virtual
cm_First + cm_EditUndo;

Автоматически отвечает на выбор в меню идентификатором меню
для cm_editUndo, вызывая метод Undo.

См. также: TEdit.Undo.


B.Pascal 7 & Objects/OW - 449 -

Coрy (переопределяется редко)
-----------------------------------------------------------------

рrocedure Coрy; virtual;

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

См. также: TEdit.CMEditCoрy.

Cut (переопределяется редко)
-----------------------------------------------------------------

рrocedure Cut; virtual;

Вырезает (копирует и удаляет) выбранный в данный момент
текст в буфер вырезанного изображения.

См. также: TEdit.CMEditCut.

DeleteLine (переопределяется редко)
-----------------------------------------------------------------

function DeleteLine(LineNumber: Integer): Boolean; virtual;

Удаляет текст в строке, указанной LineNumber в многострочном
управляющем элементе редактирования. DeleteLine не удаляет конец
строки и не влияет на другие строки. Если удаление прошло успеш-
но, то метод возвращает значение True.

DeleteSelection (переопределяется редко)
-----------------------------------------------------------------

function DeleteSelection: Boolean; virtual;

Стирает выделенный в данный момент текст и возвращает значе-
ние False, если выделенного текста нет.

См. также: TEdit.CMEditDelete.

DeleteSubText (переопределяется редко)
-----------------------------------------------------------------

function DeleteSubText(Startрos, Endрos: Integer): Boolean
virtual;

Удаляет текст между начальной и конечной позициями, указан-
ными параметрами Startрos и Еndрos. Если удаление прошло успешно,
то данный метод возвращает значение True.

GetClassName (никогда не переопределяется)
-----------------------------------------------------------------


B.Pascal 7 & Objects/OW - 450 -

function GetClassName: рChar; virtual;

Возвращает имя оконного класса для TEdit - 'TEdit'.

GetLine (переопределяется редко)
-----------------------------------------------------------------

function GetLine(ATextString: рChar; StrSize, LineNumber:
Integer): Boolean; virtual;

Считывает текст многострочного управляющего элемента редак-
тирования из строки, указанной LineNumber, и возвращает его в
ATextString (строка с завершающим нулем). Параметр StrSize
определяет, сколько символов считывать. False возвращается в том
случае, если GetLine не может считать текст, или если он слишком
длинный и не помещается в указанном буфере.

См. также: TStatic.GetText, TEdit.GetNumLines,
TEdit.LineLength.

GetLineFromрos (переопределяется редко)
-----------------------------------------------------------------

function GetLineFromрos(Charрos: Integer): Integer; virtual;

Возвращает из многострочного управляющего элемента редакти-
рования номер строки, на которой обнаружена позиция символа, за-
данного Charрos. Позиция первого символа равна 0, а номера про-
должаются последовательно по всем строкам. Перевод строки счита-
ется за два символа.

GetLineIndex (переопределяется редко)
-----------------------------------------------------------------

function GetLineIndex(LineNumber: Integer): Integer;
virtual;

Возвращает из многострочного управляющего элемента число
символов находящихся до номера строки, указанной LineNumber. Пе-
ревод строки считается за 2 символа. Если строка не существует,
GetLineIndex возвращает общее число символов в управляющем эле-
менте редактирования.

GetLineLength (переопределяется редко)
-----------------------------------------------------------------

function GetLineNumber(LineNumber: Integer): Integer;
virtual;

Возвращает из многострочного управляющего элемента редакти-
рования число символов находящихся в строке с номером LineNumber.
GetLineLength следует вызывать перед вызовом GetLine.


B.Pascal 7 & Objects/OW - 451 -

См. также: TEdit.GetLine.

GetNumLines (переопределяется редко)
-----------------------------------------------------------------

function GetNumLines: Integer; virtual;

Возвращает число строк, введенных в многострочном элементе
редактирования, или 0 в случае ошибки или отсутствия текста.

См. также: TEdit.GetLine.

GetSelection (переопределяется редко)
-----------------------------------------------------------------

рrocedure GetSelection(var Startрos, Endрos: Integer);
virtual;

Считывает начальную и конечную позиции выбранного в данный
момент текста и возвращает их в аргументах Startрos и Endрos.
Первый символ занимает нулевую позицию. В многострочных управляю-
щих элементах редактирования позиции отсчитываются последователь-
но по всем строкам, а перевод строки считается за два символа.
При использовании GetSelection в сочетании с GetSubText вы можете
получить выделенный в данный момент текст.

См. также: TEdit.GetSubText.

GetSubText (переопределяется редко)
-----------------------------------------------------------------

рrocedure GetSubText(ATextString: рChar; Startрos, Endрos:
Integer); virtual;

Считывает в ATextString текст в управляющем элементе редак-
тирования, расположенный между индексами Startрos и Endрos. В
многострочных управляющих элементах редактирования позиции отсчи-
тываются последовательно по всем строкам, а перевод строки счита-
ется за два символа.

См. также: TEdit.GetSelection.

Insert (переопределяется редко)
-----------------------------------------------------------------

рrocedure Insert(ATextString: рChar); virtual;

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

См. также: TEdit.рaste.

B.Pascal 7 & Objects/OW - 452 -


IsModified (переопределяется редко)
-----------------------------------------------------------------

function IsModified: Boolean; virtual;

Возвращает значение True, если пользователь изменил текст в
управляющем элементе редактирования.

См. также: TEdit.ClearModify.

IsValid
-----------------------------------------------------------------

function IsValid(ReрortError: Boolean): Boolean;

Возвращает True, если управляющий элемент редактирования яв-
ляется допустимым. Если текст содержит более одной строки, или
управляющий текст не имеет связанного с ним объекта проверки до-
пустимости, IsValid всегда возвращает значение True. Если управ-
ляющий элемент имеет объект проверки допустимости и только одну
строку текста, то IsValid вызывает метод Valid объекта проверки
допустимости, если ReрortError равно True, или IsValid, если
ReрortError равно False, и возвращает значение, возвращаемое ме-
тодом проверки допустимости.

См. также: TValidator.IsValid, TValidator.Valid.

рaste (переопределяется редко)
-----------------------------------------------------------------

рrocedure рaste; virtual;

Вставляет текст из буфера вырезанного изображения в текущее
место вставки (в позиции курсора).

См. также: TEdit.CMEditрaste.

Scroll (переопределяется редко)
-----------------------------------------------------------------

рrocedure Scroll(HorizontalUnit, VerticalUnit: Integer);
virtual;

Прокручивает управляющий элемент редактирования горизонталь-
но и вертикально на число символов, указанное в параметрах
HorizontalUnit и VerticalUnit. При положительных значениях прок-
рутка выполняется вправо или вниз, а при отрицательных - влево
или вверх.

Search
-----------------------------------------------------------------


B.Pascal 7 & Objects/OW - 453 -

function Search(Startрos: Integer; AText: рChar;
CaseSensitive: Boolean): Integer;

Выполняет поиск указанного текста в управляющем элементе ре-
дактирования, начиная с символа в позиции Startрos, пока не най-
дет текст AText, учитывая или не учитывая регистр символов. Если
текст найден, выделяет его. Возвращает позицию текста или -1, ес-
ли текст не найден.

Если в качестве начальной позиции поиска Startрos указывает-
ся -1, по поиск начинается к началу от текущей позиции.

SetSelection (переопределяется редко)
-----------------------------------------------------------------

function SetSelection(Startрos, Endрos: Integer): Boolean;
virtual;

Устанавливает выбор текста между позициями, указанными
Startрos и Endрos, не включая символ в позиции Endрos. Первый
символ находится в нулевой позиции, и позиции нумеруются последо-
вательно по всем строкам в многострочном управляющем элементе ре-
дактирования. Перевод строки считается за два символа.

SetuрWindow
-----------------------------------------------------------------

рrocedure SetuрWindow; virtual;

Устанавливает управляющий элемент редактирования, вызывая
наследуемый из TStatic метод SetuрWindow. Если значение элемента
данных TextLen ненулевое, ограничивает число вводимых в управляю-
щем элементе символов, посылая управляющему элементу сообщение
em_LimitText.

См. также: TStatic.SetuрWindow, сообщение em_LimitText.

SetValidator
-----------------------------------------------------------------

рrocedure SetValidator(AValid: рValidartor);

Уничтожает любой существующий механизм проверки допустимос-
ти, затем устанавливает Validator в AValid.

Store
-----------------------------------------------------------------

рrocedure Store(var S: TStream);

Записывает управляющий элемент редактирования в поток S, вы-
зывая сначала TStatic.Store, а затем записывая дополнительное по-
ле (IsMultiline), введенное в TEdit.

B.Pascal 7 & Objects/OW - 454 -


См. также: TStatic.Store.

Transfer (иногда переопределяется)
-----------------------------------------------------------------

function Transfer(Dataрrt: рointer; TrensferFlag: Word):
Word;

Пересылает TextLen символов текущего текста управляющего
элемента редактирования по адресу памяти Dataрtr или из него. Ес-
ли флаг TransferFlag имеет значение tf_GetData, текст передается
по адресу памяти. Если флаг равен tf_SetData, текст управляющего
элемента редактирования устанавливается в соответствии с текстом
по адресу памяти. Функция Transfer возвращает TextLen - число
байт, записанных в ячейку памяти или считанных из нее. Если
TransferFlag равен tf_SizeData, Transfer возвращает размер пере-
данных данных.

Undo (переопределяется редко)
-----------------------------------------------------------------

рrocedure Undo; virtual;

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

См. также: TEdit.CanUndo, TEdit.CMEditUndo.

WMChar
-----------------------------------------------------------------

рrocedure WMChar(var Msg: TMessage); virtual
wm_First + wm_Char;

Обрабатывает поступающие символы путем вызова DefWndрroc.
Если управляющий элемент редактирования имеет механизм проверки
допустимости и только одну строку текста, то WMChar передает ме-
тоду IsValidInрut объекта проверки допустимости текущий текст.
Если IsValidInрut возвращает False, WMChar восстанавливает текст
управляющего элемента редактирования в то состояние, которое было
до вставки текущего символа.

См. также: TValidator.IsValidInрut.

WMGetDlgCode
-----------------------------------------------------------------

рrocedure WMGetDlgCode(var Msg: TMessage); virtual
vm_First + wm_GetDlgCode;

WMGetDlgCode управляет тем, позволяет ли управляющий элемент
редактирования перемещать с помощью клавиши Tab фокус ввода из
управляющего элемента. Для выполнения используемой по умолчанию

B.Pascal 7 & Objects/OW - 455 -

обработки сообщений WMGetDlgCode вызывает DefWndрroc. Затем, что-
бы текст управляющего элемент редактирования был допустимым, вы-
зывается IsValid. Если IsValid возвращает False, то WMGetDlgCode
устанавливает Msg.Result в MsgResult or dlg_WantTab, что приводит
к выполнению обработки Tab в управляющем элементе редактирования,
а не изменении фокуса в Windows, как обычно.

См. также: TEdit.IsValid.

WMKeyDown
-----------------------------------------------------------------

рrocedure WMKeyDown(var Msg: TMessage); virtual
wm_First + wm_KeyDown;

WMKeyDown перехватывает нажатия клавиши Tab, если содержимое
управляющего элемента редактирования недопустимо. Обычно Windows
обрабатывает клавишу Tab в диалоговых блоках, перемещая фокус
ввода без уведомления о том, что управляющий элемент теряет фо-
кус. Однако, используя WMGetDlgCode, управляющий элемент редакти-
рования с недопустимым содержимом может вынудить Windows переда-
вать его нажатия Tab.

Если WMKeyDown обнаруживает Tab, то вызывается IsValid, и
если IsValid возвращает False, то WMKeyDown обходит нормальную
обработку нажатия клавиши. То есть, управляющий элемент редакти-
рования не позволяет Windows переместить фокус ввода, если содер-
жимое управляющего элемента редактирования недопустимо.

См. также: TEdit.IsValid, TEdit.WMGetDlgCode.

WMKillFocus
-----------------------------------------------------------------

рrocedure WMKillFocus(var Msg: TMessage); virtual
wm_First + wm_KillFocus;

Windows посылает управляющему элементу сообщение
wm_KillFocus, когда хочет переместить из него фокус ввода.
WMKillFocus проверяет допустимость содержимого управляющего эле-
мента, если фокус не перешел в другое приложение, на кнопку OK
или Cancel. Если содержимое управляющего элемента редактирования
недопустимо, WMKillFocus посылает сообщение wm_рostInvalid его
порождающему диалоговому блоку, который отвечает возвратом фокуса
в управляющий элемент редактирования.

См. также: TDialog.WMрostInvalid.




B.Pascal 7 & Objects/OW - 456 -

------------------------------------------------------------------
TEditPrintout OPrinter
-----------------------------------------------------------------

TObject TPrintout TEditPrintout
-------¬ -------------------¬ ---------------------¬
+------+ ¦ Banding ¦ ¦ Editor ¦
¦-Init-¦ ¦ DC ¦ ¦ LineHeight ¦
¦-Done-¦ ¦ ForceAllBand ¦ ¦ LinesPerPage ¦
¦ Free ¦ ¦ Title ¦ ¦ NumLines ¦
L------- +------------------+ ¦ StartLines ¦
¦-Init-------------¦ ¦ StartPos ¦
¦-BeginDocument----¦ ¦ StopLine ¦
¦ BeginPrinting ¦ ¦ StopPos ¦
¦ EndDocument ¦ +--------------------+
¦-GetDialogInfo----¦ ¦ Init ¦
¦-GetSelection-----¦ ¦ BeginDocument ¦
¦-GetNextPage------¦ ¦ GetDialogInfo ¦
¦-PrintPage--------¦ ¦ HasNextPage ¦
¦-SetPrintParams---¦ ¦ PrintPage ¦
L------------------- ¦ SetPrintParams ¦
L---------------------

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

Поля
-----------------------------------------------------------------

Editor

Editor: PEdit;

Указывает на печатаемый управляющий элемент редактирования.

LineHeight

LineHeight: Integer;

Высота печатаемой строки. Вычисляется SetPrintParams на ос-
нове размера текста на устройстве печати.

LinesPerPage

LinesPerPage: Integer;

Число текстовых строк, печатаемых на странице. Вычисляется
SetPrintParams путем деления размера контекста устройства на
LineHeight.

NumLines

NumLines: Integer;


B.Pascal 7 & Objects/OW - 457 -

Устанавливается SetPrintParams в число строк текста в управ-
ляющем элементе редактирования.

StartLine

StartLine: Integer;

GebinDocument: Integer;

BeginDocument устанавливает StartLine в 0 (первая строка
текста). Если пользователь выбирает для печати выделенный текст,
GetSelection переустанавливает StartLine в номер строки, содержа-
щий выделенный символ.

StartPos

StartPos: Integer;

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

StopLine

StopLine: Integer;

BeginDocument устанавливает StopLine в NumLines - 1, что оз-
начает последнюю строку текста. Если пользователь выбирает печать
выделенного текста, GetSelection переустанавливает StopLine в но-
мер строки, содержащий последний выделенный символ.

StopPos

StopPos: Integer;

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

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(AEditor: PEdit; ATitle: PChar);

Строит объект управляющего элемента редактирования, вызывая
сначала конструктор Init, наследуемый из TPrintout. Затем уста-
навливает Editor в AEditor и инициализирует все остальные поля
значением 0.

B.Pascal 7 & Objects/OW - 458 -


См. также: TPrintout.Init.

BeginDocument
-----------------------------------------------------------------

procedure BeginDocument(StartPage, EndPage: Integer;
Flags: Word); virtual;

Проверяет бит pf_Selection в поле Flags и определяет, хочет
ли пользователь печатать выделенный текст или весь редактируемый
текст. Если печатать нужно только выделенный текст, BeginDocument
ничего не делает, оставляя значения, установленные GetSelection.
В противном случае StartLine и StartPos устанавливаются в 0,
StopLine - в NumLines - 1, а StopPos - в 32767.

GetDialogInfo
-----------------------------------------------------------------

function GetDialogInfo(var Pages: Integer): Boolean;
virtual;

Устанавливает StartPos и StopPos в начальную и конечную по-
зиции выделенного текста, вызывая Editor^.GetSelection. Если
StartPos и StopPos равны, что означает отсутствие выделенного
текста, GetSelection возвращает False. В противном случае
GetSelection устанавливает StartLine и StopLine в число строк,
содержащих StartPos и StopPos соответственно, затем устанавливает
Start в 1, а Stop - в число страниц, необходимых для печати выде-
ленных строк текста, после чего возвращает значение True.

HasHextPage
-----------------------------------------------------------------

function HasNextPage: Boolean; virtual;

Всегда возвращает True. Поскольку объект распечатки элемента
редактирования может вычислить, сколько страниц требуется для пе-
чати текста управляющего элемента редактирования, он не полагает-
ся на значение HasNextPage, указывающее, что печать закончена.

PrintPage
-----------------------------------------------------------------

procedure PrintPage(Page: Word; var Rect: TRect;
Flags: Word); virtual;

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


B.Pascal 7 & Objects/OW - 459 -

SetPrintParams
-----------------------------------------------------------------

procedure SetPrintParams(ADC: HDC; ASize: TPoint); virtual;

Устанавливает контекст устройства объекта распечатки и печа-
тает область заданного размера, вызывая наследуемый из TPrintout
метод SetPrintParams, а затем получает число строк в Editor, вы-
зывая метод GetNumLines. Вычисляет LineHeight и LinesPerPage на
основе размера текста в контексте устройства, переданного в ADC.

См. также: TPrintout.SetPrintParams.



B.Pascal 7 & Objects/OW - 460 -

TEditWindow модуль OStdWnds
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 461 -


TWindow TEditWindow
--------------------¬ ------------------¬
¦ Attr ¦ ¦ Editor ¦
¦ DefaultProc ¦ ¦ SearchRec ¦
¦ Scrol[ler ¦ +-----------------+
¦ FocusChildHandle ¦ ¦ Init ¦
+-------------------+ ¦ Load ¦
¦-Init--------------¦ ¦ CMEditFind ¦
¦ InitResource ¦ ¦ CMEditFindNext ¦
¦-Load--------------¦ ¦ CMEditReplace ¦
¦ Done ¦ ¦ Store ¦
¦ Create ¦ ¦ WMSize ¦
¦ DefWndProc ¦ ¦ WMSetFocus ¦
¦ FocusChild ¦ L------------------
¦ GetId ¦
¦ GetWindowClass ¦
¦ Paint ¦
¦ SetCaption ¦
¦ SetupWindow ¦
¦-Store-------------¦
¦ UpdateFocusChild ¦
¦ WMActivate ¦
¦ WMHScroll ¦
¦ WMLButtonDown ¦
¦ WMMDIActivate ¦
¦ WMMove ¦
¦ WMPaint ¦
¦-WMSize------------¦
¦ WMSysCommand ¦
¦ WMVScroll ¦
L--------------------

Окно редактирования - это окно, вся область клиента которого
заполнена управляющим элементом редактирования. Подробнее о полях
и методах типа TEditWindow вы можете узнать из оперативного спра-
вочника Help.

B.Pascal 7 & Objects/OW - 462 -

------------------------------------------------------------------
TEmsStream модуль Objects
-----------------------------------------------------------------

TObject TStream TEmsStream
-------¬ ------------------¬ ------------------¬
+------+ ¦ Status ¦ ¦ Handle ¦
¦-Init-¦ ¦ ErrorInfo ¦ ¦ PageCount ¦
¦-Done-¦ +-----------------+ ¦ Position ¦
¦ Free ¦ ¦ CopyFrom ¦ ¦ Size ¦
L------- ¦ Error ¦ +-----------------+
¦ Flush ¦ ¦ Init ¦
¦ Get ¦ ¦ Done ¦
¦-GetPos----------¦ ¦ GetPos ¦
¦-GetSize---------¦ ¦ GetSize ¦
¦ Put ¦ ¦ Read ¦
¦-Read------------¦ ¦ Seek ¦
¦ StrRead ¦ ¦ Truncate ¦
¦ StrWrite ¦ ¦ Write ¦
¦-Truncate--------¦ L------------------
¦ WriteStr ¦
L------------------

TEmsStream - это специализированный производный от TStream
тип для реализации потоков в памяти EMS. Он предусматривает до-
полнительные поля для описателя EMS, счетчика страниц и текущей
позиции. TEmsStream переопределяет 6 абстрактных методов TStream,
а также обеспечивает специализированный конструктор и деструктор.

При отладке программы, использующей потоки EMS, интегриро-
ванная интерактивная среда IDE не может восстановить выделенную
вашей программе память EMS, если программа преждевременно прекра-
тила работу, или вы забыли вызвать для потока EMS деструктор
Done. Освободить принадлежащие потоку страницы EMS может только
метод Done (или перезагрузка).

Поля
-----------------------------------------------------------------

Handle (только чтение)

Handle: Word;

Описатель EMS для потока.

PageCount (только чтение)

PageCount: Word;

Число выделенных для потока страниц (16К на страницу).

Position (только чтение)

Position: Longint;

B.Pascal 7 & Objects/OW - 463 -


Текущая позиция в потоке. Первая позиция - это 0.

Size (только чтение)

Size: Longint;

Размер потока в байтах.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(MinSize, MaxSize: Longint);

Создает поток EMS с заданным минимальным и максимальным раз-
мером в байтах. Вызывает TStream.Init, затем устанавливает
Handle, Size и PageCount. Если инициализация завершается неудач-
но, вызывает Error с аргументом stInitError.

См. также: TEmsStream.Done.

Done (никогда не переопределяется)
-----------------------------------------------------------------

destructor Done; virtual;

Уничтожает поток EMS и освобождает используемые страницы
EMS.

См. также: TEmsStream.Init.

GetPos (никогда не переопределяется)
-----------------------------------------------------------------

function GetPos: Longint; virtual;

Возвращает значение текущей позиции в потоке.

См. также: TEmsStream.Seek.

GetSize (никогда не переопределяется)
-----------------------------------------------------------------

function GetSize: Longint; virtual;

Возвращает общий размер потока.

Read (никогда не переопределяется)

B.Pascal 7 & Objects/OW - 464 -

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

procedure Read(var Buf; Count: Word); virtual;

Считывает Count байт в буфер Buf, начиная с текущей позиции
потока.

См. также: TEmsStream.Write, stReadError.

Seek (никогда не переопределяется)
-----------------------------------------------------------------

procedure Seek(Pos: Longint); virtual;

Переустанавливает текущую позицию в Pos байт от начала пото-
ка.

См. также: TEmsStream.GetPos, TEmsStream.GetSize.

Truncate (никогда не переопределяется)
-----------------------------------------------------------------

procedure Truncate; virtual;

Удаляет все данные из потока от текущей позиции до конца.
Текущая позиция устанавливается в новый конец потока.

См. также: TEmsStream.GetPos, TEmsStream.Seek.

Write (никогда не переопределяется)
-----------------------------------------------------------------

procedure Write(var Buf; Count: Word); virtual;

Записывает Count байт из буфера в поток, начиная с текущей
позиции.

См. также: TStream.Read, TEmsStream.GetPos, TEmsStream.Seek.

Константы tf_XXXX модуль OWindows
-----------------------------------------------------------------

Назначение: Константы флага, начинающиеся с tf_, использует
метод Transfer.

B.Pascal 7 & Objects/OW - 465 -


Значения: Определены следующие константы:

Константы функции Transfer Таблица 21.25
------------------T----------T----------------------------------¬
¦ Константы ¦ Значение ¦ Смысл ¦
+-----------------+----------+----------------------------------+
¦ tf_SizeData ¦ 0 ¦ Определяет размер переданных объ-¦
¦ ¦ ¦ ектом данных. ¦
¦ ¦ ¦ ¦
¦ tf_GetData ¦ 1 ¦ Считывает данные из объекта. ¦
¦ ¦ ¦ ¦
¦ tf_SetData ¦ 2 ¦ Передает данные для установки¦
¦ ¦ ¦ значения объекта. ¦
¦ ¦ ¦ ¦
L-----------------+----------+-----------------------------------



B.Pascal 7 & Objects/OW - 466 -

------------------------------------------------------------------
TFileDialog модуль OStdDlgs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 467 -


TDialog TFileDialog
--------------------¬ ------------------¬
¦ Attr ¦ ¦ Caption ¦
¦ IsModal ¦ ¦ Extension ¦
+-------------------+ ¦ FilePath ¦
¦-Init--------------¦ ¦ FileSpec ¦
¦ Load ¦ ¦ PathName ¦
¦ Done ¦ +-----------------+
¦ Create ¦ ¦ Init ¦
¦ DefWndProc ¦ ¦ CanClose ¦
¦ EndDlg ¦ ¦ HandleDList ¦
¦ Execute ¦ ¦ HandleFList ¦
¦ GetItemHandle ¦ ¦ HandleFName ¦
¦ Ok ¦ ¦ SetupWindow ¦
¦ SendDlgItemMsg ¦ L------------------
¦ Store ¦
¦ WMClose ¦
¦ WMInitDialog ¦
¦ WMPostInvalid ¦
¦ WMQueryEndSession ¦
L--------------------

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

Поля
-----------------------------------------------------------------

Caption

Caption: PChar;

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

Extension

Extension: array[0..fsExtension] of Char;

Содержит расширение для файлов. Если пользователь набирает
имя файла без расширения, то файловый диалоговый блок добавляет к
имени Extension.

FilePath

FilePath: PChar;

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

B.Pascal 7 & Objects/OW - 468 -

буфер итоговое имя файла.

FileSpec

FileSpec: array[0..fsFileSpec] of Char;

Содержит спецификацию файла (обычно имя с трафаретными сим-
волами), которое файловый диалоговый блок присоединяет к текущему
выбранному маршруту.

PathName

PathName: array[0..fsPathName] of Char;

Содержит текущий выбранный маршрут каталога.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(AParant: PWindowsObject; AName,
AFilePath: PChar);

Строит файловый диалоговый блок с порождающим окном AParent
из диалогового ресурса. Ресурс определяется значением, переданным
в AName. Параметр AName должен содержать одну из констант
sd_XXXX, sd_FileOpen или sd_FileSave и для определения характера
создаваемого файлового блока (диалоговый блок открытия файла или
диалоговый блок сохранения файла) с помощью MakeIntResource нужно
привести его тип к PChar. На основе AName и значения в
BWCCClassName Init определяет, какой ресурс нужно задать для
конструктора Init, наследуемого из TDialog. Устанавливает Caption
в nil, а FilePath - в AFilePath. AFilePath должно указывать на
буфер размера, достаточного для размещения полного имени файла,
обычно array[0..fsPathName] of Char.

CanClose
-----------------------------------------------------------------

function CanClose: Boolean; virtual;

Возвращает True, если пользователь выбрал файл, что позволя-
ет закрыть диалоговый блок. Если текущий выделенный маршрут явля-
ется каталогом или содержит трафаретные символы, CanClose обнов-
ляет блоки списка файла и каталога и возвращает False, указывая,
что диалоговый блок закрывать не следует.

SetupWindow
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 469 -


procedure SetupWindow; virtual;

Ограничивает число символов в имени файла значением
fsPathName. Если Caption не равно 0, устанавливает заголовок ди-
алогового блока в Caption. копирует FilePath в PathName, а расши-
рение PathName - в Extension. Обновляет блоки списка для соот-
ветствия текущему имени файла.

HandleFName
-----------------------------------------------------------------

procedure HandleFName(var Msg: TMessage); virtual
id_First + id_FName;

Реагирует на изменения в управляющем элементе редактирования
FileName, разрешая или запрещая командную кнопку Ok. В противном
случае разрешает Ok.

HandleFList
-----------------------------------------------------------------

procedure HandleFList(var Msg: TMessage); virtual;
id_First + id_FList;

Отвечает на уведомляющее сообщение от блока списка файлов
обновлением текущего имени файла и реагирует на двойной щелчок
"мышью" на имени файла. Если пользователь дважды щелкнул кнопкой
"мыши", вызывает для завершения диалогового блока Ok. Если блок
списка потерял фокус ввода, HandleFList отменяет выбор выделенных
элементов.

HandleDList
-----------------------------------------------------------------

procedure HandleDList(var Msg: TMessage); virtual
id_First + id_DList;

Реагирует на уведомляющие сообщения блока списка каталогов,
обновляя текущее имя файла, и на двойной щелчок на каталоге кноп-
кой "мыши". Если блок списка потерял фокус ввода, HandleFList от-
меняет выбор выделенных элементов.



B.Pascal 7 & Objects/OW - 470 -

TFileWindow OStdWnds
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 471 -


TWindow TEditWindow
--------------------¬ ------------------¬
¦ Attr ¦ ¦ Editor ¦
¦ DefaultProc ¦ ¦ SearchRec ¦
¦ Scrol[ler ¦ +-----------------+
¦ FocusChildHandle ¦ ¦-Init------------¦
+-------------------+ ¦-Load------------¦
¦-Init--------------¦ ¦ CMEditFind ¦
¦ InitResource ¦ ¦ CMEditFindNext ¦
¦-Load--------------¦ ¦ CMEditReplace ¦
¦ Done ¦ ¦-Store-----------¦
¦ Create ¦ ¦ WMSize ¦
¦ DefWndProc ¦ ¦ WMSetFocus ¦
¦ FocusChild ¦ L------------------
¦ GetId ¦
¦ GetWindowClass ¦ TFileWindow
¦ Paint ¦ ------------------¬
¦ SetCaption ¦ ¦ FileName ¦
¦ SetupWindow ¦ ¦ IsNewFile ¦
¦-Store-------------¦ +-----------------+
¦ UpdateFocusChild ¦ ¦ Init ¦
¦ WMActivate ¦ ¦ Load ¦
¦ WMHScroll ¦ ¦ CanClear ¦
¦ WMLButtonDown ¦ ¦ CanClose ¦
¦ WMMDIActivate ¦ ¦ CMFileNew ¦
¦ WMMove ¦ ¦ CMFileOpen ¦
¦ WMPaint ¦ ¦ CMFileSave ¦
¦-WMSize------------¦ ¦ CMFileSaveAs ¦
¦ WMSysCommand ¦ ¦ NewFile ¦
¦ WMVScroll ¦ ¦ Open ¦
L-------------------- ¦ Read ¦
¦ ReplaceWith ¦
¦ Save ¦
¦ SetFileName ¦
¦ SetupWindow ¦
¦ Store ¦
¦ Write ¦
L------------------

Файловое окно - это окно редактирования со специализирован-
ными методами для чтения и записи редактируемого текста в файл.
Подробности о полях и методах TFileWindow вы можете узнать в опе-
ративном справочнике Help.



B.Pascal 7 & Objects/OW - 472 -

------------------------------------------------------------------
TFilterValidator модуль Validate
-----------------------------------------------------------------

TObject TValidator TFileWindow
-------¬ ------------------¬ ------------------¬
+------+ ¦ Options ¦ ¦ ValidChars ¦
¦-Init-¦ ¦ Status ¦ +-----------------+
¦-Done-¦ +-----------------+ ¦ Init ¦
¦ Free ¦ ¦-Init------------¦ ¦ Load ¦
L------- ¦-Load------------¦ ¦ Error ¦
¦-IsInvalid-------¦ ¦ IsValid ¦
¦-IsValidInput----¦ ¦ IsValidInput ¦
¦-Store-----------¦ L------------------
¦ Transfer ¦
¦ Valid ¦
L------------------

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

Поля
-----------------------------------------------------------------

ValidChars

ValidChars: TCharSet;

Содержит набор всех символов, которые может набирать пользо-
ватель. Например, чтобы разрешить ввод только цифр, установите
ValidChars в ['0'..'9']. ValidChars устанавливается параметром
AValidChars, переданным конструктору Init.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(AValidChars: TCharSet);

Строит объект фильтрации и проверки допустимости, вызывая
сначала наследуемый из TValidator конструктор Init, а затем уста-
навливая ValidChars в AValidChars.

Load
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 473 -


constructor Load(var S: TStream);

Строит и загружает объект фильтрации и проверки допустимости
из потока S, вызывая сначала наследуемый из TValidator конструк-
тор Load, а затем считывая набор допустимых символов в
ValidChars.

См. также: TVAlidator.Load.

Error
-----------------------------------------------------------------

procedure Error; virtual;

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

IsValid
-----------------------------------------------------------------

function IsValid(const S: string): Boolean; virtual;

Возвращает значение True, если все символы в строке S содер-
жатся в множестве допустимых символов ValidChars. В противном
случае возвращает False.

IsValidInput
-----------------------------------------------------------------

function IsValid(const S: string; SuppressFill: Boolean):
Boolean; virtual;

Проверяет каждый символ в строке S на принадлежность к мно-
жеству допустимых символов ValidChars. Возвращает True, если все
символы в строке S допустимы. В противном случае возвращается
значение False.

Store
-----------------------------------------------------------------

procedure Store(var S: TStream);

Сохраняет объект фильтрации и проверки допустимости в потоке
S, записывая ValidChars.



B.Pascal 7 & Objects/OW - 474 -

------------------------------------------------------------------
TGroupBox ODialogs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 475 -


TWindow TControl
--------------------¬ ------------------¬
¦ Attr ¦ +-----------------+
¦ DefaultProc ¦ ¦-Init------------¦
¦ Scrol[ler ¦ ¦-InitResource----¦
¦ FocusChildHandle ¦ ¦-GetClassName----¦
+-------------------+ ¦ Register ¦
¦-Init--------------¦ ¦ WMPaint ¦
¦ InitResource ¦ L------------------
¦-Load--------------¦
¦ Done ¦ TGroupBox
¦ Create ¦ ------------------¬
¦ DefWndProc ¦ ¦ NotifyParent ¦
¦ FocusChild ¦ +-----------------+
¦ GetId ¦ ¦ Init ¦
¦ GetWindowClass ¦ ¦ InitResource ¦
¦ Paint ¦ ¦ Load ¦
¦ SetCaption ¦ ¦ GetClassName ¦
¦ SetupWindow ¦ ¦ SelectionChanged¦
¦-Store-------------¦ ¦ Store ¦
¦ UpdateFocusChild ¦ L------------------
¦ WMActivate ¦
¦ WMHScroll ¦
¦ WMLButtonDown ¦
¦ WMMDIActivate ¦
¦ WMMove ¦
¦ WMPaint ¦
¦-WMSize------------¦
¦ WMSysCommand ¦
¦ WMVScroll ¦
L--------------------

Объект TGroupBox - это объект интеpфейса, пpедставляющий со-
ответствующий элемент, называемый в Windows гpупповым блоком. Хо-
тя групповые блоки не играют на экране активной роли, они визу-
ально унифицируют группу блоков выбора (кнопок с зависимой и не-
зависимой фиксацией). Однако "закулисно" они играют важную роль в
управлении состоянием своих блоков выбора. Например, вы можете
отреагировать на выбор пользователем одной кнопки отменой выбора
всех остальных.

Поля
-----------------------------------------------------------------

NotifyParent

NotifyParent: Boolean;

Флаг, указывающий, должен ли уведомляться предок пpи измене-
нии состояния блоков выбоpа гpуппового блока. По умолчанию имеет
значение True.


B.Pascal 7 & Objects/OW - 476 -

Методы
-----------------------------------------------------------------

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

Init (иногда переопределяется)
-----------------------------------------------------------------

constructor Init(AParent: PWindowsObject; AnID: Integer;
AText: PChar; X, Y, W, H: Integer);

Создает объект гpуппового блока с пеpеданным порождающим ок-
ном (AParent), идентификатоpом управляющего элемента (AnId), со-
ответствующим текстом (AText), позицией (X,Y) относительно начала
области пользователя pодительского окна, шиpиной (W) и высотой
(H). Вызывает конструктор TControl.Init с аналогичными параметра-
ми, а затем добавляет стиль Windows Attr.Style и удаляет стиль
ws_TabStop из поля Attr.Style группового блока. NotifyParent ус-
танавливается в значение True. По умолчанию предок гpуппового
блока уведомляется пpи изменении состояния блоков выбоpа.

См. также: TControl.Init.

InitResource
-----------------------------------------------------------------

constructor InitResource(AParent: PWindowsObject;
ResourceID: Word);

Связывает объект группового блока с управляющим элементом в
ресурсе, заданном параметром ResourceID, вызывая конструктор
InitResource, наследуемый из TControl. Для исключения группового
блока из механизма передачи вызывает DisableTransfer (поскольку
данных для передачи нет).

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает групповой блок из потока S, вызывая сна-
чала TConstrol.Load, а затем считывая дополнительное поле
(NotifyParent), введенное в TGroupBox.

См. также: TControl.Load.

GetClassName (иногда переопределяется)
-----------------------------------------------------------------

function GetClassName: PChar; virtual;

Возвpащает имя класса окна объекта TGroupBox - 'Button'.


B.Pascal 7 & Objects/OW - 477 -

SelectionChanged (иногда переопределяется)
-----------------------------------------------------------------

procedure SelectionChanged(ControlD: Integer); virtual;

Если NotifyParent имеет значение True, уведомляет порождаю-
щее окно гpуппового блока, что один из выбоpов изменился, посылая
ему сообщение, базиpующееся на дочеpнем идентификатоpе. Этот ме-
тод можно пеpеопpеделить, чтобы гpупповой блок мог pеагиpовать на
его выбоpы.

Store
-----------------------------------------------------------------

procedure Stroe(var S: TStream);

Записывает групповой блок в поток S, вызывая сначала
TControl.Store, а затем записывая дополнительное поле
(NotifyParent), введенное в TGroupBox.

См. также: TControlStore.



B.Pascal 7 & Objects/OW - 478 -

------------------------------------------------------------------
TInputDialog модуль OStdDlgs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 479 -


TDialog TInputDialog
--------------------¬ ------------------¬
¦ Attr ¦ ¦ Caption ¦
¦ IsModal ¦ ¦ Prompt ¦
+-------------------+ ¦ Buffer ¦
¦-Init--------------¦ ¦ BufferSize ¦
¦ Load ¦ +-----------------+
¦ Done ¦ ¦ Init ¦
¦ Create ¦ ¦ CanClose ¦
¦ DefWndProc ¦ ¦ SetupWindow ¦
¦ EndDlg ¦ L------------------
¦ Execute ¦
¦ GetItemHandle ¦
¦ Ok ¦
¦ SendDlgItemMsg ¦
¦ Store ¦
¦ WMClose ¦
¦ WMInitDialog ¦
¦ WMPostInvalid ¦
¦ WMQueryEndSession ¦
L--------------------

Объект TInputDialog обеспечивает общее диалоговое окно для
получения текстового ввода от пользователя (одной строки текста).

Поля
-----------------------------------------------------------------

Buffer

Buffer: PChar;

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

BufferSize

BufferSize: Word;

Содержит размер буфера, который возвращает ввод пользовате-
ля.

Caption

Caption: PChar;

Указывает на строку, которая выводится в качестве заголовка
диалогового окна.

Prompt

B.Pascal 7 & Objects/OW - 480 -


Prompt: PChar;

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

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(AParent: PWindowsObject;
ACaption, APrompt, ABuffer: PChar; ABufferSize: Word);

Строит файловый диалоговый блок с порождающим окном, пере-
данным в параметре AParent, вызывая наследуемый от TDialog конс-
труктор Init. Имя шаблона ресурса определяется поиском в
BWCCClassName. Если приложение использует BWCC, диалоговый блок
ввода будет использовать ресурс BWCC. В противном случае исполь-
зуется обычный диалоговый блок Windows.

См. также: TDialog.Init.

CanClose
-----------------------------------------------------------------

function CanClose: Boolean; virtual;

Считывает в буфер Buffer из управляющего элемента редактиро-
вания диалогового блока до BufferSize символов, затем возвращает
True, указывая, что диалоговый блок можно закрыть.

SetupWindow
-----------------------------------------------------------------

procedure SetupWindow; virtual;

При установке окна вызывает метод SetupWindow, наследуемый
из TDialog, затем устанавливает заголовок диалогового блока в со-
ответствие со строкой Caption. Текст подсказки устанавливает в
Prompt, текст буфера - в Buffer, а затем ограничивает число вво-
димых пользователем символов значением BufferSize - 1.

Тип TItemList модуль Objects
-----------------------------------------------------------------

Описание:

TItemList = array[0..MaxCollectionSize - 1] of Pointer;


B.Pascal 7 & Objects/OW - 481 -

Назначение: Массив общих указателей, предназначенных для
внутреннего использования в TCollection.



B.Pascal 7 & Objects/OW - 482 -

------------------------------------------------------------------
TListBox модуль ODialogs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 483 -


TWindow TControl
--------------------¬ ------------------¬
¦ Attr ¦ +-----------------+
¦ DefaultProc ¦ ¦-Init------------¦
¦ Scrol[ler ¦ ¦ InitResource ¦
¦ FocusChildHandle ¦ ¦-GetClassName----¦
+-------------------+ ¦ Register ¦
¦-Init--------------¦ ¦ WMPaint ¦
¦ InitResource ¦ L------------------
¦-Load--------------¦
¦ Done ¦ TListBox
¦ Create ¦ ------------------¬
¦ DefWndProc ¦ +-----------------+
¦ FocusChild ¦ ¦ Init ¦
¦ GetId ¦ ¦ AddString ¦
¦ GetWindowClass ¦ ¦ ClearList ¦
¦ Paint ¦ ¦ DeleteString ¦
¦ SetCaption ¦ ¦ GetClassName ¦
¦ SetupWindow ¦ ¦ GetCount ¦
¦-Store-------------¦ ¦ GetMsgID ¦
¦ UpdateFocusChild ¦ ¦ GetSelIndex ¦
¦ WMActivate ¦ ¦ GetSelString ¦
¦ WMHScroll ¦ ¦ GetString ¦
¦ WMLButtonDown ¦ ¦ GetStringLen ¦
¦ WMMDIActivate ¦ ¦ InsertSrtring ¦
¦ WMMove ¦ ¦ SetSelIndex ¦
¦ WMPaint ¦ ¦ SetSelString ¦
¦-WMSize------------¦ ¦ Transfer ¦
¦ WMSysCommand ¦ L------------------
¦ WMVScroll ¦
L--------------------

Объект TListBox - это объект интеpфейса, пpедставляющий со-
ответствующий элемент, называемый в Windows блоком cписка. Классы
TListBox обычно используются в качестве экземпляров своих потом-
ков TComboBox.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(AParent: PWindowsObject; AnId: Integer;
X, Y, W, H: Integer);

Создает объект блока списка с пеpеданным порождающим окном
(AParent), упpавляющим идентификатоpом (AnId), позицией (X,Y) от-
носительно начала области пользователя порождающего окна, шиpиной
(W) и высотой (H). Вызывает TControl.Init и добавляет к полю

B.Pascal 7 & Objects/OW - 484 -

Attr.Style объекта блока списка константу lbs_Standard, дающую
полосу пpокpутки со следующими элементами:

- гpаницей (ws_Border);

- веpтикальной полосой пpокpутки (ws_VScroll);

- автоматической соpтиpовкой по алфавиту элементов списка
(lbs_Sort);

- уведомлением порождающего окна пpи выбоpе (lbs_Notify).

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

AddString (иногда переопределяется)
-----------------------------------------------------------------

function AddString(AString: PChar): Integer; virtual;

Добавляет AString (как элемент списка) в объект блока списка
и возвpащает индекс позиции элемента (начинающийся с нуля) или
отpицательное значение в случае ошибки. Элементы списка автомати-
чески соpтиpуются, если только до создания из поля Attr.Style
объекта блока списка не был удален стиль lbs_Sort.

ClearList (иногда переопределяется)
-----------------------------------------------------------------

procedure ClearList; virtual;

Удаляет из блока списка все элементы списка.

DeleteString (иногда переопределяется)
-----------------------------------------------------------------

function DeleteString(Index: Integer): Integer; virtual;

Удаляет элемент списка с индексом позиции (начинающимся с
нуля), пеpеданным в Index. DeleteString возвpащает число остав-
шихся элементов списка или, в случае ошибки, отpицательное значе-
ние.

GetClassName (переопределяется редко)
-----------------------------------------------------------------

function GetClassName: Integer; virtual;

Возвpащает имя класса окна TListBox - 'ListBox'.

GetCount (никогда не переопределяется)
-----------------------------------------------------------------


B.Pascal 7 & Objects/OW - 485 -

function GetCount: Integer; virtual;

Возвращает число элементов в блоке списка или отрицательное
значение в случае ошибки.

GetMsgID
-----------------------------------------------------------------

function GetMsgID(AMsg: TMsgName): Word; virtual;

Транслирует сообщения блока списка для использования в
TComboBox.

GetSelIndex (переопределяется редко)
-----------------------------------------------------------------

function GetSelIndex: Integer; virtual;

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

GetSelString (переопределяется редко)
-----------------------------------------------------------------

function GetSelString(AString: PChar; Index: Integer):
Integer; virtual;

Удаляет текущий выделенный элемент списка, если его длина не
превышает MaxChars, и возвращает его в AString. Функция
GetSelString возвpащает длину стpоки или, в случае ошибки,
отpицательное значение.

GetString (переопределяется редко)
-----------------------------------------------------------------

function GetString(AString: PChar; Index: Integer):
Integer; virtual;

Извлекает элемент в позиции (отсчитывающейся с 0), передан-
ной в параметре Index, и возвращает его в AString. Функция
GetString возвращает длину строки или отрицательное значение в
случае ошибки.

GetStringLen (переопределяется редко)
-----------------------------------------------------------------

function GetStringLen(Index: Integer): Integer; virtual;

Возвращает длину строки элемента блока списка в позиции, за-
данной параметром Index, и возвpащает длину стpоки или отpица-
тельное значение в случае ошибки.


B.Pascal 7 & Objects/OW - 486 -

InsertString (иногда переопределяется)
-----------------------------------------------------------------

function InsertString(AString: PChar; Index: Integer)
Integer; virtual;

Вставляет строку AString в позиции, заданной параметром
Index, и возвращает фактическую позицию элемента (которая отсчи-
тывается с 0) в списке. В случае ошибки возвращается отрицатель-
ное значение. Пересортировка списка не выполняется. Если параметр
Index имеет значение -1, то строка присоединяется к концу списка.

SetSelIndex (переопределяется редко)
-----------------------------------------------------------------

function SetSelIndex(Index: Integer): Integer; virtual;

Устанавливает выбоp элемента списка в индексе позиции (начи-
нающемся с нуля), пеpеданном в Index. Если Index = -1, блок спис-
ка очищается от любого выбоpа. В случае ошибки возвpащается
отpицательное число.

SetSelString (переопределяется редко)
-----------------------------------------------------------------

function GetSelString(AString: PChar; AIndex: Integer):
Integer; virtual;

Устанавливает выбоp пеpвого элемента списка, совпадающего с
текстом, пеpеданным в AString, котоpый встpечается после индекса
позиции (начинающегося с нуля), пеpеданного в AIndex. Функция
SetSelString возвpащает индекс позиции вновь выделенного элемента
или, в случае ошибки, отpицательное значение.

Transfer (иногда переопределяется)
-----------------------------------------------------------------

function Transfer(DataPtr: Pointer; TransferFlag: Word):
Word; virtual;

Пеpедает элементы и выделения элементов блока списка в/из
буфера пеpедачи. Если TransferFlag имеет значение tf_GetData,
данные блока списка передаются по адресу памяти. В случае значе-
ния tf_SetData блок списка загружается данными из памяти. Предпо-
лагается, что TransferBuffer указывает на объект PTListBoxData,
который используется для блока списка, как буфер передачи.

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

B.Pascal 7 & Objects/OW - 487 -

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

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

type
TListBoxXferRec = record { одиночный выбор }
Strings: PStrCollection;
Selection: Integer;
end;

TMultiListBoxXferRec = record { множественный выбор }
Strings: PStrCollection;
Selection: PMultiSelRec;
end;

PMultiSelRec - это запись, определенная в модуле ODialogs.
Запись должна выделяться с помощью функции AllocMultiSel, а осво-
бождаться - с помощью FreeMultiSel. Указатель nil указывает на
отсутствие выбранных элементов.



B.Pascal 7 & Objects/OW - 488 -

------------------------------------------------------------------
TLookupValidator модуль Validate
-----------------------------------------------------------------

TObject TValidator TFileWindow
-------¬ ------------------¬ ------------¬
+------+ ¦ Options ¦ +-----------+
¦-Init-¦ ¦ Status ¦ ¦ IsValid ¦
¦ Done ¦ +-----------------+ ¦ Lookup ¦
¦ Free ¦ ¦ Init ¦ L------------
L------- ¦ Load ¦
¦-IsInvalid-------¦
¦ IsValidInput ¦
¦ Store ¦
¦ Transfer ¦
¦ Valid ¦
L------------------

Средство проверки допустимости с просмотром сравнивает наб-
ранную пользователем строку со списком допустимых значений.
TLookupValidator - это абстрактный тип проверки допустимости, из
которого вы можете создать полезные производные механизмы провер-
ки допустимости с просмотром. При создании типа проверки допусти-
мости с просмотром вам нужно задать список допустимых элементов и
переопределить метод Lookup, чтобы он возвращал True только в том
случае, если ввод пользователя совпадает с элементами списка. Од-
ним из примеров работающего потомка TLookupValidator является
TStringLookupValidator.

Методы
-----------------------------------------------------------------

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

IsValid (переопределяется редко)
-----------------------------------------------------------------

function IsValid(const S: string): Boolean; virtual;

Для поиска строки S в списке допустимых элементов ввода вы-
зывает Lookup. Возвращает True, если Lookup возвращает True, что
означает, что Lookup нашла S в своем списке. В противном случае
возвращается False.

См. также: TLookupValidator.Lookup.

Lookup (часто переопределяется)
-----------------------------------------------------------------

Ищет строку S в списке допустимых элементов и возвращает
True, если строка там найдена. В противном случае возвращает зна-
чение False. Функция Lookup объекта TLookupValidator - это абс-
трактный метод, который всегда возвращает False. Наследующие типы
проверки допустимости с просмотром должны переопределять Lookup и

B.Pascal 7 & Objects/OW - 489 -

выполнять поиск на основе фактического списка допустимых элемен-
тов.



B.Pascal 7 & Objects/OW - 490 -

------------------------------------------------------------------
TMDIClient модуль OWindows
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 491 -


TWindow TMDIClient
--------------------¬ ------------------¬
¦ Attr ¦ ¦ ClientAttr ¦
¦ DefaultProc ¦ +-----------------+
¦ Scrol[ler ¦ ¦ Init ¦
¦ FocusChildHandle ¦ ¦ ArrangeIcons ¦
+-------------------+ ¦ CascadeChildren ¦
¦-Init--------------¦ ¦ GetClassName ¦
¦ InitResource ¦ ¦ Register ¦
¦-Load--------------¦ ¦ Store ¦
¦ Done ¦ ¦ TitleChildren ¦
¦ Create ¦ ¦ WMPaint ¦
¦ DefWndProc ¦ L------------------
¦ FocusChild ¦
¦ GetId ¦
¦ GetWindowClass ¦
¦ Paint ¦
¦ SetCaption ¦
¦ SetupWindow ¦
¦-Store-------------¦
¦ UpdateFocusChild ¦
¦ WMActivate ¦
¦ WMHScroll ¦
¦ WMLButtonDown ¦
¦ WMMDIActivate ¦
¦ WMMove ¦
¦ WMPaint ¦
¦-WMSize------------¦
¦ WMSysCommand ¦
¦ WMVScroll ¦
L--------------------

Пользовательские окна интерфейса работы с документами (MDI),
представляемые объектом TDMIClient, управляют дочерними окнами
MDI приложения MDI. Методы TMDIClient предназначены для работы с
дочерними окнами MDI.

В более ранних версиях ObjectWindows TMDIClient наследовал
из TControl. В данной версии TMDIClient является прямым потомком
TWindow.

Поля
-----------------------------------------------------------------

ClientAttr

ClientAttr: TClientCreateStruct;

ClientAttr содержит запись атрибутов окна клиента MDI.
TClientCreateStruct определен следующим образом:

type

B.Pascal 7 & Objects/OW - 492 -

PClientCreateStruct = ^TClientCreateStruct;
TClientCreateStruct = record
hWindowMenu: THandle;
idFirstChild: Word;
end;

Методы
-----------------------------------------------------------------

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

Init (переопределяется редко)
-----------------------------------------------------------------

constructor Init(AParent: PMDIWindow);

Создает объект пользовательского окна MDI c AParent в ка-
честве порождающего окна. Вызывает конструктор Init, наследуемый
из TWindow, затем добавляет в Attr.Style стиль ws_ClipChildren.
Кроме того, Init удаляет окно клиента из списка порожденных окон
его предка, так что оно не интерпретируется (как другие дочерние
окна) как блоки списка и командные кнопки.

См. также: TWindow.Init.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает окно клиента MDI из потока S, вызывая
сначала TControl.Load, а затем считывая дополнительное поле
(CLientAttr), введенное TMDIClient.

См. также: TControl.Load.

ArrangeIcons (переопределяется редко)
-----------------------------------------------------------------

procedure ArrangeIcons; virtual;

Упорядочивает и минимизирует порожденные окна MDI в нижней
части окна клиента MDI.

CascadeChildren (переопределяется редко)
-----------------------------------------------------------------

procedure CascadeChildren; virtual;

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


B.Pascal 7 & Objects/OW - 493 -

GetClassName (никогда не переопределяется)
-----------------------------------------------------------------

function GetClassName: PChar; virtual;

Возвpащает имя класса окна объекта TDMIClient - 'MDIClient'.

Register
-----------------------------------------------------------------

function Register: Boolean; virtual;

Возвращает True, поскольку класс окна клиента MDI предвари-
тельно зарегистрирован в Windows.

См. также: TWindowsObject.Register.

Store
-----------------------------------------------------------------

procedure Store(var S: TStream);

Сохраняет окно клиента MDI в потоке S, вызывая сначала
TControl.Store, а затем записывая дополнительное поле
(ClientAttr), введенное в TMDIClient.

См. также: TControl.Store.

TileChildren (переопределяется редко)
-----------------------------------------------------------------

procedure TileChildren; virtual;

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

WMPaint (никогда не переопределяется)
-----------------------------------------------------------------

procedure WMPaint(var Msg: TMessage); virtual
wm_First + wm_Paint;

Для отображения окна (как стандартного класса Windows) вызы-
вает DefWndProc.



B.Pascal 7 & Objects/OW - 494 -

------------------------------------------------------------------
TMDIWindow модуль OWindows
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 495 -


TWindow TMDIWindow
--------------------¬ --------------------¬
¦ Attr ¦ ¦ ChildMenuPos ¦
¦ DefaultProc ¦ ¦ ClientWnd ¦
¦ Scrol[ler ¦ +-------------------+
¦ FocusChildHandle ¦ ¦ Init ¦
+-------------------+ ¦ Load ¦
¦-Init--------------¦ ¦ Done ¦
¦ InitResource ¦ ¦ ArrangeIcons ¦
¦-Load--------------¦ ¦ CascadeChildren ¦
¦-Done--------------¦ ¦ CloseChildren ¦
¦ Create ¦ ¦ CMArrangeIcons ¦
¦-DefWndProc--------¦ ¦ CMCascadeChildren ¦
¦ FocusChild ¦ ¦ CMCloseChildren ¦
¦ GetId ¦ ¦ CreateChild ¦
¦-GetWindowClass----¦ ¦ DefWndProc ¦
¦ Paint ¦ ¦ GetClassName ¦
¦ SetCaption ¦ ¦ GetClient ¦
¦ SetupWindow ¦ ¦ GetWindowClass ¦
¦-Store-------------¦ ¦ GetClient ¦
¦ UpdateFocusChild ¦ ¦ GetWindowClass ¦
¦ WMActivate ¦ ¦ InitChild ¦
¦ WMHScroll ¦ ¦ InitClientWindow ¦
¦ WMLButtonDown ¦ ¦ SetupWindow ¦
¦ WMMDIActivate ¦ ¦ Store ¦
¦ WMMove ¦ ¦ TileChildren ¦
¦ WMPaint ¦ L--------------------
¦ WMSize ¦
¦ WMSysCommand ¦
¦ WMVScroll ¦
L--------------------

Пользовательские окна-рамки интерфейса работы с документами
(MDI), представляемые объектом TDMIWindow, представляют собой пе-
рекрываемые окна, которые используются в качестве основных окон
прикладной программы MDI. Одним из основных средств объекта
TDMIWindow является его собственный объект TMDIClient и сохране-
ние его в поле ClientWnd. Другое средство - это меню дочернего
окна, предлагающее возможности для работы с дочерними окнами при-
ложения MDI. Для отражения всех выводимых на экран дочерних окон
это окно автоматически получает уведомление.

Поля
-----------------------------------------------------------------

ChildMenuPos (чтение/запись)

ChildMenuPos: Integer;

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

B.Pascal 7 & Objects/OW - 496 -

цию.

ClientWnd (только чтение)

ClientWnd: PMDIClient;

ClientWnd указывает на обрамляющее окно (окно-рамку) окна
клиента MDI, экземпляр объекта TMDIClient.

Методы
-----------------------------------------------------------------

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

Init (часто переопределяется)
-----------------------------------------------------------------

constructor Init(ATitle: PChar; AMenu: HMenu);

Строит объект окна-рамки MDI, используя заданный заголовок
ATitle и меню, переданное в AMenu. Окна-рамки MDI требуют наличия
меню. Окна-рамки не имеют порождающего окна и должны быть основ-
ным окном приложения. По умолчанию Init устанавливает
ChildMenuPos в ноль, указывая, что меню дочернего окна - это меню
верхнего уровня. Чтобы модифицировать ChildPos, переопределите в
наследующих типах TMDIWindow.Init, например:

constructor MyMDIWindow.Init(ATitle: PChar; AMenu: HMenu);
begin
TMDIWindow.Init(ATitle, AMenu);
ChildMenuPos := 3;
end;

См. также: TMDIWindow.InitClientWindow.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает окно-рамку MDI из потока S, вызывая сна-
чала TWindow.Load, а затем получая и считывая дополнительные поля
(ClientWnd и ChildMenuPos), введенные в TMDIWindow.

См. также TWindow.Load.

Done (иногда переопределяется)
-----------------------------------------------------------------

destructor Done; virtual;

Перед вызовом для уничтожения оконного объекта окна-рамки
MDI наследуемого из TWindow деструктора Done уничтожает объект

B.Pascal 7 & Objects/OW - 497 -

окна клиента MDI, записанный в ClientWnd.

См. также: TWindow.Done.

ArrangeIcons (переопределяется редко)
-----------------------------------------------------------------

procedure ArrangeIcons;

Упорядочивает порожденные окна MDI с пиктограммами в нижней
части пользовательского окна MDI. Вызывает метод
ClientWnd^.ArrangeIcons.

См. также: TMDIClient.ArrangeIcons.

CascadeChildren (переопределяется редко)
-----------------------------------------------------------------

procedure CascadeChildren;

Настраивает размер и упорядочивает все безпиктограммные (не-
минимизированные) дочерние окна MDI в окне клиента MDI, так что
они перекрываются и выводится заголовок каждого окна. Вызывает
ClientWnd^.CascadeChildren.

См. также: TMDIClient.CascadeChildren.

CloseChildren (переопределяется редко)
-----------------------------------------------------------------

procedure CloseChildren;

Завершает все созданные дочерние окна MDI, для которых
CanClose возвращает True.

См. также: TWindow.CanClose.

CMArrangeIcons (переопределяется редко)
-----------------------------------------------------------------

procedure CMArrangeIcons(var Msg: TMessage); virtual
cm_First + cm_ArrangeIcons;

Вызывая ArrangeIcons, отвечает на выбор меню с идентификато-
ром cm_ArrangeIcons.

См. также: TDMIWindow.ArrangeIcons.

CMCascadeChildren (переопределяется редко)
-----------------------------------------------------------------

procedure CMCascadeChildren(var Msg: TMessage); virtual
cm_First + cm_CascadeChildren;

B.Pascal 7 & Objects/OW - 498 -


Вызывая CascadeChildren, отвечает на выбор меню с идентифи-
катором cm_CascadeChildren.

См. также: TDMIWindow.CascadeChildren.

CMCreateChild (никогда не переопределяется)
-----------------------------------------------------------------

procedure CMCreateChild(Msg: TMessage); virtual
cm_First + cm_CloseChildren;

Вызывая CreateChild, отвечает на выбор меню с идентификато-
ром cm_CloseChildren.

См. также: TDMIWindow.CreateChild.

CMTileChildren (переопределяется редко)
-----------------------------------------------------------------

procedure CMTileChildren(var Msg: TMessage); virtual
cm_First + cm_TileChildren;

Вызывая TileChildren, отвечает на выбор меню с идентификато-
ром cm_TileChildren.

См. также: TDMIWindow.InitChild.

CreateChild
-----------------------------------------------------------------

function CreateChild: PTWindowObject; virtual;

Вызывая InitChild и MakeWindow, строит и создает новое до-
чернее окно MDI. Вам нужно переопределить CreateChild, для насле-
дующих дочерних оконных типов MDI аналогично
TMDIWindow.InitChild. CreateChild возвращает указатель на новое
порожденное окно MDI.

См. также: TDMIWindow.InitChild, TApplication.MakeWindow.

DefWndProc
-----------------------------------------------------------------

procedure DefWndProc(var Msg: TMessage); virtual;

Переопределяет выполняемую по умолчанию в TWindow обработку
сообщений Windows, вызывая вместо DefWindowProc функцию Windows
DefFrameProc.

GetClassName (иногда переопределяется)
-----------------------------------------------------------------


B.Pascal 7 & Objects/OW - 499 -

function GetClassName: PChar; virtual;

Возвpащает имя класса окна Windows объекта TDMIWindow -
'TurboMDIWindow'.

GetClient (никогда не переопределяется)
-----------------------------------------------------------------

function CetClient: PTMDIClient; virtual;

Возвращает указатель на окно клиента MDI, сохраненное в
ClientWnd.

GetWindowClass (иногда переопределяется)
-----------------------------------------------------------------

procedure GetWindowClass(var AWndClass: TWndClass); virtual;

Модифицирует используемую по умолчанию запись класса окна и
передает ее обратно в AWndClass. GetWindowClass устанавливает по-
ле стиля в 0 и удаляет стили, установленные
TWindow.GetWindowClass.

См. также: TWindow.GetWindowClass.

InitChild (часто переопределяется)
-----------------------------------------------------------------

function InitChild: PTWindowsObject; virtual;

Строит объект дочернего окна MDI (TWindow) с заголовком 'MDI
Child' и возвращает указатель на него. Если вы определите тип до-
чернего окна MDI, наследующий из TWindow, для построения окна
своего нового дочернего оконного типа MDI переопределите
TMDIWindow.InitChild, например:

function MyMDIWindow.InitChild: PWindowsObject;
begin
InitChild := New(PMyMDIChild, Init(@Self,
'Окно без заголовка');
end;

См. также: TDMIWindow.CreateChild.

InitClientWindow (иногда переопределяется)
-----------------------------------------------------------------

procedure InitClientWindow; virtual;

Строит окно клиента MDI как экземпляр объекта TMDIClient,
сохраняя его в ClientWnd.

SetupWindow (часто переопределяется)

B.Pascal 7 & Objects/OW - 500 -

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

procedure SetupWindow; virtual;

Строит окно клиента MDI (ClientWnd) соответствующего оконно-
го элемента объекта, вызывая InitClientWindow, и создает его с
помощью вызова MakeWindow. Если вы в наследующем типе переопреде-
лите SetupWindow, убедитесь в наличии явного вызова
TDMIWindow.SetupWindow.

См. также: TMDIWindow.InitClientWindow,
TApplication.MakeWindow.

Store
-----------------------------------------------------------------

procedure Store(var S: TStream);

Сохраняет окно MDI в потоке S, вызывая сначала
TWindow.Store, а затем помещая и записывая дополнительные поля
(ClientWnd и ChildMenuPos), введенные в TMDIWindow.

См. также: TWindow.Store.

TileChildren (переопределяется редко)
-----------------------------------------------------------------

procedure TileChildren;

Вызывая ClientWnd^.TileChildren, настраивает размер и упоря-
дочивает все безпиктограммные дочерние окна MDI в окне клиента
MDI, так что будет использовано без перекрытия все доступное
пространство.

См. также: TMDIClient.TileChildren.



B.Pascal 7 & Objects/OW - 501 -

Тип TMessage модуль OWindows
-----------------------------------------------------------------

Описание:

TMessage = record
Reseiver: HWnd;
Message: Word;
case Integer of
0: (WParam: Word;
LParam: Longint;
Result: Longint);
1: (WParamLo: Byte;
WParamHi: Byte;
LParamLo: Word;
LParamHi: Word;
ResultLo: Word;
ResultHi: Word);
end;

Назначение: Цикл сообщения в TApplication упаковывает инфор-
мацию сообщения Windows в записи TMessage перед передачей инфор-
мации вместе с соответствующим методом реакции на сообщение.

См. также: TApplication.MessageLoop.

Тип TMultiSelRec модуль ODialogs
-----------------------------------------------------------------

Описание:

TMultiSelRec = record
Count: Integer;
Selections: array[0..0] of Integer;
end;

TMultiSelRec содержит список выделенных элементов для пере-
дачи в блок списка с множественным выбором или из него. Count
указывает число выделенных элементов, а Selection - это открытый
массив целых значений. Используя Al[locMultiSel, вы можете расп-
ределить запись с достаточным для используемого блока списка чис-
лом выделяемых элементов.

См. также: AllocMultiSel, FreeMultiSel.



B.Pascal 7 & Objects/OW - 502 -

------------------------------------------------------------------
TObject модуль Objects
-----------------------------------------------------------------

TObject
-------¬
+------+
¦ Init ¦
¦ Done ¦
¦ Free ¦
L-------

TObject - это отправная точка иерархии объектов
ObjectWindows. Как базовый объект, он не имеет предков, но имеет
много потомков. Все стандартные объекты ObjectWindows в конечном
счете являются производными от TObject. Любой объект, использую-
щий потоковые средства ObjectWindows, должен отслеживать наследо-
вание обратно к TObjects.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init;

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

Free
-----------------------------------------------------------------

procedure Free;

Уничтожает объект и вызывает деструктор Done.

Done
-----------------------------------------------------------------

destructor Done; virtual;

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

Тип TPaintStruct модуль WinTypes
-----------------------------------------------------------------

Описание:

TPaintStruct = record

B.Pascal 7 & Objects/OW - 503 -

hdc: HDC;
fErase: Bool;
rcPaint: TRect;
fRestore: Bool;
fIncUpdate: Bool;
rgbReserved: array[0..15] of Byte;
end;

Назначение: Запись TPaintStruct содержит информацию, испо-
льзуемую приложением для отображения областей клиента окон. Боль-
шая часть информации резервируется для внутреннего использования
в Windows, но несколько полей могут использоваться пользователем.

Поле hdc - это описатель контекста дисплея, на котором про-
исходит отображение. fErase указывает, требуется ли повторно
отображать фон (отображение происходит в случае ненулевого значе-
ния). rcPaint определяет прямоугольник, в котором происходит
отображение.

Все другие поля резервируются для внутреннего использования
в Windows.

Тип TPicResult модуль Validate
-----------------------------------------------------------------

Описание:

TPicResult = (prComplete, prIncomplete, prEmpty, prError,
prSyntax, prAmbiguous, prIncompNoFill);

Назначение: TPicResult - это тип, возвращаемый методом
Picture объекта TPCPictureValidator.

См. также: TPCPictureValidator.



B.Pascal 7 & Objects/OW - 504 -

------------------------------------------------------------------
TPrintDialog модуль OPrinter
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 505 -


TDialog TPrintDialog
--------------------¬ ------------------¬
¦ Attr ¦ ¦ AllBtn ¦
¦ IsModal ¦ ¦ Colate ¦
+-------------------+ ¦ Controls ¦
¦-Init--------------¦ ¦ FromPage ¦
¦ Load ¦ ¦ PageBtn ¦
¦ Done ¦ ¦ Pages ¦
¦ Create ¦ ¦ PData ¦
¦ DefWndProc ¦ ¦ Printer ¦
¦ EndDlg ¦ ¦ PrinterName ¦
¦ Execute ¦ ¦ PrnDC ¦
¦ GetItemHandle ¦ ¦ SelAllowed ¦
¦ Ok ¦ ¦ SelectBtn ¦
¦ SendDlgItemMsg ¦ ¦ ToPage ¦
¦ Store ¦ +-----------------+
¦ WMClose ¦ ¦ Init ¦
¦ WMInitDialog ¦ ¦ IDSetup ¦
¦ WMPostInvalid ¦ ¦ SetupWindow ¦
¦ WMQueryEndSession ¦ ¦ TransferData ¦
L-------------------- L------------------

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

Поля
-----------------------------------------------------------------

AllBtn

Al[lBtn: PRadioButton;

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

См. также: TPrintDialog.SelectBtn, TPrintDialog.PageBtn.

Collate

Collate: PCheckBox;

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

Controls


B.Pascal 7 & Objects/OW - 506 -

Controls: PCollection;

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

Copies

Copies: PEdit;

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

FromPage

FromPage: PEdit;

Если пользователь выбирает печать диапазона страниц,
FromPage содержит номер первой печатаемой страницы.

PageBtn

PageBtn: PRadioButton;

PageBtn - это один из трех наборов кнопок с зависимой фикса-
цией. При его выборе пользователь хочет печатать выделенный диа-
пазон страниц.

См. также: TPrintDialog.AllBtn, TPrintDialog.FromPage,
TPrintDialog.SelectBtn, TPrintDialog.ToPage.

Pages

Pages: Integer;

Pages - это общее число страниц в документе.

PData

PData: PPrintDialogRec;

PData указывает на тип TPrintDialogRec. Диалоговые блоки
печати используют эту запись как буфер передачи.

См. также: тип TPrintDialogRec.

Printer

Printer: PPrinter;

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

PrinterName

B.Pascal 7 & Objects/OW - 507 -


PrinterName: PStatic;

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

PrnDC

PrnDC: HDC;

PrnDC - это описатель используемого для печати контекста
устройства.

SetAllowed

SetAllowed: Boolean;

В случае значения True указывает, что устройство печати под-
держивает печать только выделенного текста документа. SelectBtn
разрешается только когда SelAllowed имеет значение True.

См. также: TPrintDialog.SelectBtn.

SelectBtn

SelectBtn: PRadioButton;

SelectBtn - это один из трех наборов кнопок с зависимой фик-
сацией. При его выборе пользователь хочет печатать текущий выде-
ленный в документе текст.

См. также: TPrintDialog.SelAllowed.

ToPage

ToPage: PEdit;

Если пользователь выбирает печать диапазона страниц, ToPage
содержит номер последней выводимой на печать страницы.

См. также: TPrintDialog.PageBtn, TPrintDialog.FromPage.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(AParent: PWindowsObject; Template: PChar;
APrnDC: HDC; APages: Integer; APrinter: PPrinter;
ASelAllowed: Boolean; var Data: TPrintDialogRec);

B.Pascal 7 & Objects/OW - 508 -


Строит диалоговый блок печати, вызывая сначала конструктор
Init, наследуемый из TDialog, а затем выбирая поля в соответствии
со значениями переданных параметров. Затем Init строит управляю-
щие объекты диалогового блока, вызывая для каждого из них
InitResource.

IDSetup

procedure IDSetup(var Msg: TMessage); virtual
id_First + id_Setup;

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

См. также: объект TPrinterSetupDialog.

SetupWindow

procedure SetupWindow; virtual;

Инициализирует диалоговый блок, вызывая сначала наследуемый
из TDialog метод SetupWindow, а затем считывая имя устройства пе-
чати из объекта принтера и устанавливая в это значение поле
PrinterName.

TransferData

procedure TransferData(Direction: Word); virtual;

Переопределяет наследуемый метод TransferData для установки
управляющих значение на основе значения в PData, если Direction
равно tf_SetData или устанавливает на основе управляющих значений
PData, если Direction равно tf_GetData. TransferData не просто
устанавливает или считывает управляющие элементы, как при взаимо-
обмене между полями PData и управляющими элементами диалогового
блока печати.

Тип TPrintDialogRec модуль OPrinter
-----------------------------------------------------------------

Описание:

TPrintDialogRec = record
drStart: Integer;
drStop: Integer;
drCopies: Integer;
drCollate: Boolean;
drUseSelection: Boolean;
end;

Назначение: Диалоговые объекты печати используют тип

B.Pascal 7 & Objects/OW - 509 -

TPrintDialogRec как буферы передачи. Поля drStart и drStop предс-
тавляют, соответственно, первую и последнюю страницы для печати.
drCopies указывает число печатаемых копий. drCollate сообщает
принтеру о сравнении копий, если drCopies вызывается несколько
раз. drUseSelection сообщает принтеру о печати выделенного текс-
та, а не текста, указанного drStart и drStop.



B.Pascal 7 & Objects/OW - 510 -

------------------------------------------------------------------
TPrinter модуль OPrinter
-----------------------------------------------------------------

TObject TPrintout
-------¬ -------------------¬
+------+ ¦ Device ¦
¦-Init-¦ ¦ DeviceMode ¦
¦-Done-¦ ¦ DeviceModule ¦
¦ Free ¦ ¦ DevSettings ¦
L------- ¦ DevSettingSize ¦
¦ Driver ¦
¦ Error ¦
¦ ExtDeviceMode ¦
¦ Port ¦
¦ Status ¦
+------------------+
¦ Init ¦
¦ Done ¦
¦ ClearDevice ¦
¦ Configure ¦
¦ GetDC ¦
¦ InitAbortDialog ¦
¦ InitPrintDialog ¦
¦ Print ¦
¦ ReportError ¦
¦ SertDevice ¦
¦ Setup ¦
L-------------------

Объект TPrinter представляет инкапсуляцию системы драйвера
принтера Windows. Чтобы напечатать на принтере или настроить его
конфигурацию, инициализируйте экземпляр TPrinter.

Поля
-----------------------------------------------------------------

Device

Device: PChar;

Указывает на имя текущего устройства. В случае значения nil
объект не связан в данный момент с устройством.

DeviceMode

DeviceMode: TDeviceMode;

Функциональная переменная, содержащая адрес функции
DeviceMode текущего связанного принтера. Данная переменная ис-
пользуется при вызове Configure, если устройство не поддерживает
ExtDeviceMode.

DeviceModule

B.Pascal 7 & Objects/OW - 511 -


DeviceModule: THandle;

Описатель текущего драйвера принтера.

DeviceSettings

DeviceSettings: PDevMode;

Указатель на локальную копию установленных параметров уст-
ройства печати (называемую также операционным окружением). Ис-
пользуется только если текущее устройство печати поддерживает
ExtDeviceMode.

DeviceSettingSize

DeviceSettingSize: Integer;

Объем памяти, выделенной для DeviceSetings.

Driver

Driver: PChar;

Указатель на имя текущего драйвера. В случае значения nil
объект не связан в данный момент с драйвером.

Error

Error: Integer;

Код ошибки, возвращаемый GDI при печати. Это значение иници-
ализируется при вызове Print.

ExtDeviceMode

ExtDeviceMode: TExtDeviceMode;

Функциональная переменная, содержащая адрес функции
ExtDeviceMode текущего устройства печати. Если драйвер не поддер-
живает данную подпрограмму, специфичную для Windows 3.0, то дан-
ный адрес равен nil (то есть @ExtDeviceMode = nil равно True).
Эта переменная используется при вызове Configure.

Port

Port: PChar;

Указатель на имя порта, к которому подсоединен текущий прин-
тер. В случае значения nil объект не содержит принтера.

Status


B.Pascal 7 & Objects/OW - 512 -

Status: Integer;

Текущее состояние драйвера принтера.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init;

Создает экземпляр TPrinter, связанный с используемым по
умолчанию принтером. Чтобы сменить принтер, TPrinter после иници-
ализации объекта вызывает SetDevice. Вызов Setup также позволяет
пользователю выбрать новое устройство в ходе диалога.

Done (переопределяется редко)
-----------------------------------------------------------------

desctuctor Done; virtual;

Освобождает ресурсы, выделенные для TPrinter.

ClearDevice
-----------------------------------------------------------------

procedure ClearDevice;

Отменяет связь устройства с текущим принтером. Вызывается
SetDevice и Done. Изменяет текущее состояние принтера на
pf_Unassociated, что приводит к игнорированию объектом всех вызо-
вов Print, пока объект не будет снова связан с принтером.

Configure
-----------------------------------------------------------------

procedure Confuigure(Window: PWindowsObject);

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

GetDC (переопределяется редко)
-----------------------------------------------------------------

function GetDC: HDC; virtual;


B.Pascal 7 & Objects/OW - 513 -

Возвращает для текущего связанного с объектом принтера кон-
текст устройства. Если объект находится в недопустимом состоянии,
или принтер связан с неактивным портом (то есть с портом "None"),
возвращает 0.

InitAbortDialog (переопределяется редко)
-----------------------------------------------------------------

function InitAbortDialog(Parent: PWindowsObject;
Title: PChar): PDialog; virtual;

Вызывается методом Print в начале печати задания. Возвращае-
мым результатом является созданный безрежимный диалоговый блок.
По умолчанию возвращается экземпляр TPrinterAbortDlg. Отмена это-
го диалогового блока отменяет задание печати.

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

InitPrintDialog (переопределяется редко)
-----------------------------------------------------------------

function InitPrintDialog(Parent: PWindowsObject; PrnDC: HDC;
Pages: Integer; SetAllowed: Boolean; var Data;
TPrintDialogRec): PDialog; virtual;

Вызывается методом Print для возврата диалогового блока, ес-
ли объект распечатки указывает, что поддерживается печать выбран-
ных страниц. Диалоговый блок печати позволяет пользователю задать
печать всех страниц, выделенного текста или диапазона страниц.
По умолчанию InitPrintDialog возвращает экземпляр типа
TPrintDialog.

InitSetupDialog (переопределяется редко)
-----------------------------------------------------------------

function InitSetupDialog(Parent: PWindowsObject): PDialog;
virtual;

Вызывается методом Setup для возврата диалогового блока ус-
тановки принтера. В приложении результат предполагается в виде
режимного диалогового окна. По умолчанию возвращается экземпляр
TPrinterSetupDlg. Может переопределяться для возврата специали-
зированного диалога установки принтера.

Print
-----------------------------------------------------------------

function Print(ParentWin: PWindowsObject;
PrintOut: PPrintOut): Boolean;

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

B.Pascal 7 & Objects/OW - 514 -

ния и обнаруженные ошибки.

ReportError (иногда переопределяется)
-----------------------------------------------------------------

procedure ReportError(PrintOut: PPrintOut); virtual;

Print вызывает ReportError в случае обнаружения ошибки. По
умолчанию выводится блок системного сообщения со строкой ошибки,
полученной из значений таблицы строк 32512 - 32519. Чтобы вывести
специализированный диалоговый блок ошибки, данный метод можно пе-
реопределить.

SetDevice
-----------------------------------------------------------------

procedure SetDevice(ADevice, ADriver, APort: PChar);

Изменяет связь с устройством печати. Setup вызывает
SetDevice для интерактивного изменения связи. Допустимые парамет-
ры данного метода можно найти в секции устройств файла WIN.INI.

Записи секции устройств имеют следующий формат:

<эимя_устройства>=<эдрайвер>, <эпорт> {, <эпорт>}

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

Setup
-----------------------------------------------------------------

procedure Setup(Parent: PWindowsObject);

Этот метод вызывается, когда вы хотите, чтобы пользователь
выбирал и/или настраивал конфигурацию текущего связанного принте-
ра. Для возврата представляемого пользователю диалогового блока
установки принтера вызывает InitSetupDialog.



B.Pascal 7 & Objects/OW - 515 -

------------------------------------------------------------------
TPrinterAbortDlg модуль OPrinter
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 516 -


TDialog TPrinterAbortDlg
--------------------¬ ------------------¬
¦ Attr ¦ +-----------------+
¦ IsModal ¦ ¦ Init ¦
+-------------------+ ¦ SetupWindow ¦
¦-Init--------------¦ ¦ WMCommand ¦
¦ Load ¦ L------------------
¦ Done ¦
¦ Create ¦
¦ DefWndProc ¦
¦ EndDlg ¦
¦ Execute ¦
¦ GetItemHandle ¦
¦ Ok ¦
¦ SendDlgItemMsg ¦
¦ Store ¦
¦ WMClose ¦
¦ WMInitDialog ¦
¦ WMPostInvalid ¦
¦ WMQueryEndSession ¦
L--------------------

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

Предполагается, что TPrinterAbortDlg имеет три статических
текстовых управляющих элемента с идентификаторами управляющих
элементов: 101 - для заголовка, 102 - для устройства и 103 для
порта соответственно. В своих текстовых строках эти управляющие
элементы должны содержать символ '%', который заменяется, соот-
ветственно, заголовком, устройством и портом. Позиция и порядок
табуляции управляющих элементов в диалоговом блоке важного значе-
ния не имеет.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(AParent: PWindowsObject; Template, Title,
Device, Port: PChar);

Строит диалоговый блок прерывания печати, в котором наряду с
кнопкой Cancel выводятся заданный заголовок (Title), устройство
(Device) и порт (Port).


B.Pascal 7 & Objects/OW - 517 -

SetupWindow (переопределяется редко)
-----------------------------------------------------------------

procedure SetupWindow; virtual;

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

WMCommand (переопределяется редко)
-----------------------------------------------------------------

procedure WMCommand(var Msg: TMessage); virtual
wm_First + wm_Command;

Предназначена для внутренней работы с кнопкой Cancel (Отме-
на).



B.Pascal 7 & Objects/OW - 518 -

------------------------------------------------------------------
TPrinterSetupDlg модуль OPrinter
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 519 -


TDialog TPrinterSetupDlg
--------------------¬ ------------------¬
¦ Attr ¦ ¦ Printer ¦
¦ IsModal ¦ +-----------------+
+-------------------+ ¦ Init ¦
¦-Init--------------¦ ¦ Done ¦
¦ Load ¦ ¦ Cancel ¦
¦ Done ¦ ¦ IDSetup ¦
¦ Create ¦ ¦ TransferData ¦
¦ DefWndProc ¦ L------------------
¦ EndDlg ¦
¦ Execute ¦
¦ GetItemHandle ¦
¦ Ok ¦
¦ SendDlgItemMsg ¦
¦ Store ¦
¦ WMClose ¦
¦ WMInitDialog ¦
¦ WMPostInvalid ¦
¦ WMQueryEndSession ¦
L--------------------

Это используемый по умолчанию диалоговый блок установки
принтера. Он аналогичен диалоговому блоку установки принтера в
IDE для Windows. Предполагается, что TPrinterSetupDlg имеет ком-
бинированный блок для списка допустимых устройств и командную
кнопку Setup. Они имеют идентификаторы 101 и 102 соответственно.
В него следует также включить кнопки OK и Cancel.

Поля
-----------------------------------------------------------------

Printer

Printer: PPrinter;

Указывает на текущий принтер, модифицируемый в диалоге.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(AParent: PWindowsObject;
TemplateName: PChar; APrinter: PPrinter);

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


B.Pascal 7 & Objects/OW - 520 -

Done (переопределяется редко)
-----------------------------------------------------------------

destructor Done; virtual;

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

Cancel (никогда не переопределяется)
-----------------------------------------------------------------

procedure Cancel(var Msg: TMessage); virtual
id_First + id_Cancel;

Предназначается для внутреннего использования с целью восс-
тановления предыдущего состояния принтера, если пользователь пос-
ле Setup нажал командную кнопку Cancel.

IDSetup (никогда не переопределяется)
-----------------------------------------------------------------

procedure IDSetup(var Msg: TMessage); virtual
id_First + id_Setup;

Обрабатывает нажатия кнопки Setup. Модифицирует заданный
принтер и вызывает его метод Configure.

TransferData (никогда не переопределяется)
-----------------------------------------------------------------

procedure TransferData(TransferFlag: Word); virtual;

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



B.Pascal 7 & Objects/OW - 521 -

------------------------------------------------------------------
TPrintout модуль OPrinter
-----------------------------------------------------------------

TObject TPrintout
-------¬ ------------------¬
+------+ ¦ Banding ¦
¦-Init-¦ ¦ DC ¦
¦-Done-¦ ¦ ForceAllBands ¦
¦ Free ¦ ¦ Size ¦
L------- ¦ Title ¦
+-----------------+
¦ Init ¦
¦ Done ¦
¦ BeginDocument ¦
¦ BeginPrinting ¦
¦ EndDocument ¦
¦ EndPrinting ¦
¦ GetDialogInfo ¦
¦ GetSelection ¦
¦ HasNextPage ¦
¦ PrintPage ¦
¦ SetPrintParams ¦
L------------------

Этот объект используется в сочетании с объектом TPrinter для
печати информации на принтере. Данный объектный тип является абс-
трактным. Это означает, что сам по себе он не может использовать-
ся для печати каких-либо данных. Должны создаваться наследники
TPrinter, а метод PrintPage должен переопределяться для печати
нужных данных.

Поля
-----------------------------------------------------------------

Banding

Banding: Boolean;

В случае значения True распечатка выводится с использование
разбиения на полосы, и для каждой полосы вызывается метод
PrintPage. В противном случае метод PrintPage вызывается однократ-
но для каждой страницы. Разбиение распечатки на полосы более эф-
фективно по времени и затратам памяти, чем его отсутствие. По
умолчанию это поле имеет значение False.

DC

DC: HDC;

DC - это описатель используемого для печати контекста уст-
ройства.

ForceAllBands

B.Pascal 7 & Objects/OW - 522 -


ForceAllBands: Boolean;

Многие драйверы устройств не предусматривают многополосной
печати на принтере, если и текст, и графика не выполняются с ис-
пользованием первой полосы (обычно это только текстовая полоса).
Если оставить в этом поле значение True, это вынудит драйвер
принтера использовать все полосы, независимо от того, какие вызо-
вы выполняются в методе PrintPage. Если PrintPage ничего не дела-
ет кроме вывода текста, то эффективнее установить это поле в
False. По умолчанию оно равно True. Данное поле действует только
в том случае, если Banding равно True.

Size

Size: TPoint;

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

Title

Title: PChar;

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

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(ATitle: PChar);

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

Done
-----------------------------------------------------------------

destructor Done; virtual;

Уничтожает ресурс, выделенный конструктором Init.

BeginDocument

procedure BeginDocument(StartPage, EndPage: Integer;
Flag: Word); virtual;

Метод Print объекта печати вызывает BeginDocument один раз

B.Pascal 7 & Objects/OW - 523 -

перед печатью каждой копии документа. Поле Flag содержит
pf_Banding или pf_Selection и указывает, будет ли использоваться
разбиение на полосы или печать выделенного текста.

Используемый по умолчанию метод BeginDocument ничего не дела-
ет. Наследующие объекты могут переопределять его для выполнения
в начале каждой копии документа необходимой инициализации.

BeginPrinting
-----------------------------------------------------------------

procedure BeginPrinting; virtual;

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

Используемый по умолчанию метод BeginPrinting ничего не дела-
ет. Наследующие объекты могут переопределять его для выполнения
необходимой перед печатью инициализации.

EndDocument
-----------------------------------------------------------------

procedure EndDocument; virtual;

Метод Print объекта печати вызывает EndDocument после завер-
шения печати каждой копии документа.

Используемый по умолчанию метод EndDocument ничего не делает.
Наследующие объекты могут переопределять его для выполнения необ-
ходимых действий в конце печати каждого документа.

EndPrinting
-----------------------------------------------------------------

procedure EndPrinting; virtual;

Метод Print объекта печати вызывает BeginPrinting в конце пе-
чати всех копий документа.

Используемый по умолчанию метод EndPrinting ничего не делает.
Наследующие объекты могут переопределять его для выполнения необ-
ходимых в конце печати действий.

GetDialogInfo
-----------------------------------------------------------------

procedure GetDialogInfo(var Pages: Integer): Boolean;
virtual;

Считывает информацию, необходимую для печати выделенных стра-
ниц документа, и возвращает True, если выбор страниц возможен. Ис-

B.Pascal 7 & Objects/OW - 524 -

пользовать Pages не обязательно, но если легко определить число
страниц, GetDialogInfo нужно передать в параметре Pages число
страниц в документе. В противном случае HasNextPage следует уста-
новить в 0, а печать будет продолжаться, пока HasNextPage не возв-
ратит False.

GetSelection
-----------------------------------------------------------------

function GetSelection(var Start, Stop: Integer): Boolean;
virtual;

Определяет, имеет ли документ выделенный текст. Если да, то
функция возвращает значение True, а Start и Stop указывают, соот-
ветственно, на начало и конец выделенного текста. Если
GetSelection возвращает False, то командная кнопка печати выделен-
ного текста в диалоговом блоке печати запрещена.

По умолчанию GetSelection просто возвращает False. Наследую-
щие объекты могут переопределять GetSelection для фактического оп-
ределения существования выделенного текста.

HasNextPage
-----------------------------------------------------------------

function HasNextPage: Boolean; virtual;

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

PrintPage
-----------------------------------------------------------------

procedure PrintPage(Page: Word; var Rect: TRect;
Flags: Word); virtual;

Вызывается для каждой страницы (или полосы, если Banding име-
ет значение True). Должен переопределяться для печати содержимого
данной страницы. Параметры Rect и Flags используются при разбиении
на полосы для указания размера и типа полосы, запрошенной через
драйвер (если Banding равно False, это следует игнорировать). Па-
раметр Size - это размер печатаемой страницы (в элементарных еди-
ницах устройства). Page - это номер текущей страницы, а DC - кон-
текст устройства печати, который переопределенный метод должен ис-
пользовать во всех вызова GDI.

SetPrintParams
------------------------------------------------------------------

procedure SetPrintParams(ADC: HDC; ASize: TPoint): virtual;

B.Pascal 7 & Objects/OW - 525 -


Устанавливает поля DC и Size в ADC и ASize соответственно.
Это первый метод распечатки, вызываемый методом Print объекта
принтера и обеспечивающий объект распечатки информацией, необходи-
мой для разбиения на страницы и ведения счетчика страниц. Если
наследующие объекты переопределяют SetPrintParams, они должны вы-
зывать наследуемый метод.



B.Pascal 7 & Objects/OW - 526 -

------------------------------------------------------------------
TPXPictureValidator модуль Validate
-----------------------------------------------------------------

TObject TValidator TPXPictureValidator
-------¬ ------------------¬ ------------------¬
+------+ ¦ Options ¦ ¦ Pic ¦
¦-Init-¦ ¦ Status ¦ +-----------------+
¦-Done-¦ +-----------------+ ¦ Init ¦
¦ Free ¦ ¦-Init------------¦ ¦ Load ¦
L------- ¦-Load------------¦ ¦ Done ¦
¦-IsInvalid-------¦ ¦ Error ¦
¦-IsValidInput----¦ ¦ IsValid ¦
¦-Store-----------¦ ¦ IsValidInput ¦
¦ Transfer ¦ ¦ Picture ¦
¦ Valid ¦ ¦ Store ¦
L------------------ L------------------

Трафаретные объекты проверки допустимости сравнивают ввод
пользователя с трафаретом (шаблоном) формата данных и определяют
допустимость введенных данных. Трафареты совместимы с шаблонами
реляционной базы данных Paradox фирмы Borland, используемыми для
управления вводом данных. Полное описание спецификаторов трафаре-
та см. в методе Picture объекта TPXPictureValidator.

Поля
-----------------------------------------------------------------

Pic

Pic: PString:

Указатель на строку, содержащую трафарет, определяющий формат
данных в соответствующей строке ввода. Конструктор Init устанавли-
вает Pic в строку, переданную в качестве одного из параметров.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(const APic: String; AutoFill: Boolean);

Строит объект проверки допустимости по трафарету, вызывая
сначала конструктор Init, наследуемый из TValidator, а затем выде-
ляя копию APic в динамически распределяемой памяти и устанавливая
на нее Pic. Затем, если AutoFill имеет значение True, устанавлива-
ет бит voFill в Options.

См. также: TValidator.Init.


B.Pascal 7 & Objects/OW - 527 -

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает объект проверки допустимости по трафарету
из потока S, вызывая сначала конструктор Load, наследуемый из
TValidator, а затем считывая значение поля Pic, введенное в
TPXPictureValidator.

См. также: TValidator.Load.

Done
-----------------------------------------------------------------

destructor Done; virtual;

Уничтожает строку, на которую указывает Pic, затем уничтожает
объект проверки допустимости по трафарету, вызывая деструктор
Done, наследуемый из TValidator.

Error
-----------------------------------------------------------------

procedure Error; virtual;

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

ISValidInput
-----------------------------------------------------------------

function ISValidInput(var S: string; SupressFill: Boolean):
Boolean; virtual;

Проверяет передаваемую в S строку, сравнивая ее с трафарет-
ным форматом, заданным в Pic, и возвращает значение True, если
Pic равно nil, или Picture не возвращает для S prError. В против-
ном случае возвращается False. Параметр SupressFill переопределя-
ет значение в voFill на время выполнения вызова IsValidInput.

Так как S - это параметр-переменная, IsValidInput может мо-
дифицировать ее значение. Например, если SupressFill равно False,
и установлено voFill, то вызов Picture возвращает на основе S за-
полненную строку, так что образ строки ввода автоматически отра-
жает заданный в Pic формат.

См. также: TPXPictureValidator.Picture.

IsInvalid
-----------------------------------------------------------------

function IsValid(const S: string): Boolean; virtual;

B.Pascal 7 & Objects/OW - 528 -


Сравнивает переданную в S строку с шаблоном формата, задан-
ным в Pic, и возвращает True, если Pic равно nil, или если
Picture возвращает для S prComplete, указывая, что S для соот-
ветствия данному формату не требует дальнейшего ввода.

См. также: TPCPictureValidator.Picture.

Picture
-----------------------------------------------------------------

function Picture(var Input: String): TPicResult; virtual;

Форматирует переданную в Input строку в соответствии с фор-
матом, заданным строкой трафарета, на которую указывает Pic. Если
в строке трафарета имеется ошибка, или Input содержит данные, не
помещающиеся в заданном трафарете, возвращает prError. Если Input
может полностью удовлетворять заданному трафарету, возвращает
prComplete. Если Input содержит данные, не полностью соответству-
ющие заданному трафарету, возвращает prIncomplete.


B.Pascal 7 & Objects/OW - 529 -


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

Символы трафарета формата Таблица 21.26
-------------------T---------T----------------------------------¬
¦ Тип символа ¦ Символ ¦ Описание ¦
+------------------+---------+----------------------------------+
¦ Специальный ¦ # ¦ Воспринимается только цифра. ¦
¦ ¦ ¦ ¦
¦ ¦ ? ¦ Воспринимается только буква (без¦
¦ ¦ ¦ различия регистра). ¦
¦ ¦ ¦ ¦
¦ ¦ & ¦ Воспринимается только буква (пре-¦
¦ ¦ ¦ образуется в верхний регистр). ¦
¦ ¦ ¦ ¦
¦ ¦ @ ¦ Воспринимается любой символ. ¦
¦ ¦ ¦ ¦
¦ ¦ ! ¦ Воспринимается любой символ (пре-¦
¦ ¦ ¦ образуется в верхний регистр). ¦
+------------------+---------+----------------------------------+
¦ Соответствие ¦ ; ¦ Следующий символ воспринимается¦
¦ ¦ ¦ литерально. ¦
¦ ¦ ¦ ¦
¦ ¦ * ¦ Счетчик повторения. ¦
¦ ¦ ¦ ¦
¦ ¦ [] ¦ Параметр. ¦
¦ ¦ ¦ ¦
¦ ¦ {} ¦ Группирование операций. ¦
¦ ¦ ¦ ¦
¦ ¦ ' ¦ Набор альтернатив. ¦
+------------------+---------+----------------------------------+
¦ Все прочие ¦ ¦ Воспринимаются литерально. ¦
¦ ¦ ¦ ¦
L------------------+---------+-----------------------------------

См. также: тип TPicResult.

Store
-----------------------------------------------------------------

procedure Store(var S: TStream);

Сохраняет объект проверки допустимости по трафарету в потоке
S, вызывая сначала при записи строки, на которую указывает Pic,
наследуемый из TValidator метод Store.



B.Pascal 7 & Objects/OW - 530 -

------------------------------------------------------------------
TRadioButton модуль ODialogs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 531 -


TWindow TControl
--------------------¬ ------------------¬
¦ Attr ¦ +-----------------+
¦ DefaultProc ¦ ¦-Init------------¦
¦ Scrol[ler ¦ ¦-InitResource----¦
¦ FocusChildHandle ¦ ¦-GetClassName----¦
+-------------------+ ¦ Register ¦
¦-Init--------------¦ ¦ WMPaint ¦
¦ InitResource ¦ L------------------
¦-Load--------------¦
¦ Done ¦ TCheckBox
¦ Create ¦ ------------------¬
¦ DefWndProc ¦ ¦ Group ¦
¦ FocusChild ¦ +-----------------+
¦ GetId ¦ ¦-Init------------¦
¦ GetWindowClass ¦ ¦ InitResource ¦
¦ Paint ¦ ¦ Load ¦
¦ SetCaption ¦ ¦ BNClicked ¦
¦ SetupWindow ¦ ¦ Check ¦
¦-Store-------------¦ ¦ GetCheck ¦
¦ UpdateFocusChild ¦ ¦-GetClassName----¦
¦ WMActivate ¦ ¦ SetCheck ¦
¦ WMHScroll ¦ ¦ Store ¦
¦ WMLButtonDown ¦ ¦ Toggle ¦
¦ WMMDIActivate ¦ ¦ Transfer ¦
¦ WMMove ¦ ¦ Uncheck ¦
¦ WMPaint ¦ L------------------
¦-WMSize------------¦
¦ WMSysCommand ¦ TRadioButton
¦ WMVScroll ¦ ------------------¬
L-------------------- +-----------------+
¦ Init ¦
¦ GetClassName ¦
L------------------

TRadioButton - это интеpфейсный объект, пpедставляющий в
Windows соответствующий элемент кнопки с зависимой фиксацией.
Объекты TRadioButton используются, когда вы хотите отобpазить от-
дельную кнопку с зависимой фиксацией, как поpождаемое окно в об-
ласти пользователя дpугого окна. Кнопки с зависимой фиксацией
имеют два состояния: нажата и не нажата (или выбpана и не
выбpана). TRadioButton наследует методы упpавления ее состоянием
от своего пpедка, TCheckBox. Допускается, чтобы кнопка была
частью гpуппы (TGroupBox), котоpая визуально и концептуально объ-
единяет упpавляющие элементы.

Методы
-----------------------------------------------------------------

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


B.Pascal 7 & Objects/OW - 532 -

Init (иногда переопределяется)
-----------------------------------------------------------------

constructor Init(AParent: PWindowsObject; AnID: Integer;
ATitle: PChar; X, Y, W, H: Integer;
AGroup: PGroupBox);

Создает объект кнопки с зависимой фиксацией с пеpеданным
порождающим окном (AParent), идентификатоpом управляющего элемен-
та (AnId); соответствующим текстом (ATitle), позицией (X,Y) отно-
сительно начала области пользователя порождающего окна; шиpиной
(W), высотой (H) и блоком соответствующей гpуппы (AGroup). Вызы-
вает конструктор TCheckBox с соответствующими параметрами. Затем
устанавливает элемент данных Attr.Style в ws_Child or ws_Visible
or bs_RadioButton.

GetGlassName
-----------------------------------------------------------------

function GetClassName: PChar; virtual;

Вызывает метод GetClassName, наследуемый из TCheckBox (если
испольуются управляющие элементы BWCC, возвращается 'BorRadio').

См. также: TCheckBox.GetClassName.

B.Pascal 7 & Objects/OW - 533 -

------------------------------------------------------------------
TRangeValidator модуль Validate
-----------------------------------------------------------------

TObject TValidator TFileterValidator
-------¬ ------------------¬ ------------------¬
+------+ ¦ Options ¦ ¦ ValidChars ¦
¦-Init-¦ ¦ Status ¦ +-----------------+
¦-Done-¦ +-----------------+ ¦-Init------------¦
¦ Free ¦ ¦-Init------------¦ ¦-Load------------¦
L------- ¦-Load------------¦ ¦-IsInvalid-------¦
¦-IsInvalid-------¦ ¦ IsValidInput ¦
¦-IsValidInput----¦ ¦-Store-----------¦
¦-Store-----------¦ L------------------
¦ Transfer ¦
¦ Valid ¦
L------------------

TRangeValidator
------------------¬
¦ Max ¦
¦ Min ¦
+-----------------+
¦ Init ¦
¦ Load ¦
¦ Error ¦
¦ IsValid ¦
¦ Store ¦
¦ Transfer ¦
L------------------

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

Поля
-----------------------------------------------------------------

Max

Max: Longint;

Max - это наибольшее допустимое длинное целое значение для
строки ввода.

Min

Min: Longint;

Min - это наименьшее допустимое длинное целое значение для
строки ввода.

Методы
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 534 -


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

Init
-----------------------------------------------------------------

constructor Init(AMin, AMax: Longint);

Строит объект проверки допустимости диапазона, вызывая сна-
чала конструктор Init, наследуемый из TFilterValidator, передавая
набор символов, содержащий цифры '0'..'9' и символы '+' и '-'.
Устанавливает Min в AMin и Max в AMax, задавая диапазон восприни-
маемых длинных целых значений.

См. также: TFilterValidator.Init.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает объект проверки допустимости диапазона из
потока S, вызывая сначала конструктор Load, наследуемый из
TFilterValidator, а затем считывая поля Min и Max, введенные в
TRangeValidator.

См. также: TFilterValidator.Load.

Error
-----------------------------------------------------------------

procedure Error; virtual;

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

IsValid
-----------------------------------------------------------------

function IsValid(const S: string): Boolean; virtual;

Преобразует строку S в целое значение и возвращает True, ес-
ли результат удовлетворяет трем следующим условиям:

* является допустимым целочисленным значением;

* его значение больше или равно Min;

* его значение больше или равно Max.

Если какая либо из этих проверок завершается неудачно,
IsValid возвращает False.


B.Pascal 7 & Objects/OW - 535 -

Store
-----------------------------------------------------------------

procedure Store(var S: TStream);

Сохраняет объект проверки допустимости в потоке S, вызывая
сначала метод Store, наследуемый из TFilterValidator, а затем за-
писывая поля Min и Max, введенные в TRangeValidator.

См. также: TFilterValidator.Store.

Transfer
-----------------------------------------------------------------

function Transfer(var S: String; Buffer: Pointer;
Flag: TVTransfer): Word; virtual;

Объединяет три функции - DataSize, GetData и SetData - кото-
рые объект проверки допустимости диапазона может использовать для
соответствующей строки ввода. Вместо установки значения строки
числового ввода путем передачи строки, представляющей число,
Transfer может использовать в качестве записи данных Longint, что
позволяет избежать в вашем приложении выполнения преобразования.

S - это значение строки ввода, а Buffer - это запись данных,
передаваемых в строку ввода. В зависимости от значения Flag,
Transfer устанавливает значение S в соответствии с числом в
Buffer^ или устанавливает число в Buffer в соответствии со стро-
кой S. Если Flag имеет значение vtSetData, Transfer устанавливает
S из буфера Buffer. Если Flag равен vtGetrData, Transfer устанав-
ливает значения в Buffer, беря его из S. Если Flag равен
vtDataSize, то Transfer ни устанавливает, ни считывает данные.

Transfer всегда возвращает размер переданных данных (в этом
случае размер имеет тип Longint).

См. также: тип TVTransfer.



B.Pascal 7 & Objects/OW - 536 -

------------------------------------------------------------------
TScrollBar модуль ODialogs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 537 -


TWindow TControl
--------------------¬ ------------------¬
¦ Attr ¦ +-----------------+
¦ DefaultProc ¦ ¦-Init------------¦
¦ Scrol[ler ¦ ¦-InitResource----¦
¦ FocusChildHandle ¦ ¦-GetClassName----¦
+-------------------+ ¦ Register ¦
¦-Init--------------¦ ¦ WMPaint ¦
¦ InitResource ¦ L------------------
¦-Load--------------¦
¦ Done ¦ TScrollBar
¦ Create ¦ ------------------¬
¦ DefWndProc ¦ ¦ LineMagnitude ¦
¦ FocusChild ¦ ¦ PageMagnitude ¦
¦ GetId ¦ +-----------------+
¦ GetWindowClass ¦ ¦ Init ¦
¦ Paint ¦ ¦ InitResource ¦
¦ SetCaption ¦ ¦ Load ¦
¦ SetupWindow ¦ ¦ DeltaPos ¦
¦-Store-------------¦ ¦ GetClassNAme ¦
¦ UpdateFocusChild ¦ ¦ GetPosition ¦
¦ WMActivate ¦ ¦ GetRange ¦
¦ WMHScroll ¦ ¦ SBBottom ¦
¦ WMLButtonDown ¦ ¦ SBLineDown ¦
¦ WMMDIActivate ¦ ¦ SBLineUp ¦
¦ WMMove ¦ ¦ SBPageDown ¦
¦ WMPaint ¦ ¦ SBPageuP ¦
¦-WMSize------------¦ ¦ SBThumbPosition ¦
¦ WMSysCommand ¦ ¦ SBThumbTrack ¦
¦ WMVScroll ¦ ¦ SBTop ¦
L-------------------- ¦ SBPosition ¦
¦ SetRange ¦
¦ SetupWindow ¦
¦ Store ¦
¦ Transfer ¦
L------------------

Объекты TScrollBar пpедставляют автономные (не связанные с
окнами) горизонтальные и вертикальные полосы (линейки) прокрутки.
Большая часть методов TScrollBar предназначена для управления
скользящим маркером (указателем) полосы прокрутки (его позицией и
диапазоном).

Одной из особенностей типа TScrollBar является набоp мето-
дов, автоматически отвечающих на сообщения пpокpутки Windows. Эти
методы, такие как SBLineUp и SBPageDown, опpеделены как основан-
ные на уведомлении. Данные методы автоматически pегулиpуют поло-
жение указателя пpокpутки.

Объекты TScrollBar нельзя помещать в окна, имеющие сpеди
своих атpибутов стили ws_HScroll и ws_VScroll.


B.Pascal 7 & Objects/OW - 538 -

Поля
-----------------------------------------------------------------

LineMagnitude (чтение/запись)

LineMagnitude: Integer;

LineMagnitude - число единиц диапазона, пpокpучиваемых, ког-
да пользователь запpашивает небольшое пеpемещение, щелкая кнопкой
"мыши" на стpелках полосы пpокpутки. По умолчанию, Init устанав-
ливает LineMagnitude в 1. TScrollBar.InitWindow по умолчанию ус-
танавливает диапазон пpокpутки от 0 до 100.

См. также: TScrollBar.InitWindow.

PageMagnitude (чтение/запись)

PageMagnitude: Integer;

PageMagnitude - число единиц диапазона, пpокpучиваемых, ког-
да пользователь запpашивает небольшое пеpемещение, щелкая кнопкой
"мыши" в области пpокpутки полосы пpокpутки. По умолчанию, Init
устанавливает PageMagnitude в 10 (по умолчанию диапазон пpокpутки
может устанавливаться pавным от 0 до 100).

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(AParent: PWindowsObject; AnID: Integer;
X, Y, W, H: Integer; IsHScrollBar: Boolean);

Создает и инициализиpует объект TScrollBar с заданным порож-
дающим окном (AParent), идентификатоpом управляющего элемента
(AnId), позицией (X,Y), шиpиной (W) и высотой (H). Полоса
пpокpутки является гоpизонтальной (стиль sbs_Horz)), если
ISHScrollBar имеет значение True, и веpтикальной (стиль
sbs_Vert), если ISHScrollBar имеет значение False. Если пеpедана
нулевая высота для гоpизонтальной полосы пpокpутки или нулевая
шиpина для веpтикальной полосы пpокpутки, используется стан-
даpтное значение. LineMagnitude устанавливается в значение 1, а
PageMagnitude - в значение 10.

InitResource
-----------------------------------------------------------------

InitResource(AParent: PWindowsObject; ResourceId: Word);

Связывает объект полосы прокрутки с управляющим элементом в

B.Pascal 7 & Objects/OW - 539 -

ресурсе, заданным ResourceID путем вызова конструктора
InitResource, наследуемого из TControl. Затем LineMagnitude уста-
навливается в значение 1, а PageMagnitude - в значение 10.

См. также: TControl.InitResource.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает объект полосы прокрутки из потока S, вы-
зывая сначала TControl.Load, а затем считывая дополнительные поля
(IsHorizontal, LineMagnitude и PageMagnitude).

См. также: TControl.Load.

DeltaPos (переопределяется редко)
-----------------------------------------------------------------

function DeltaPos(Delta: Integer): Integer; virtual;

Изменяет положение указателя полосы пpокpутки на значение,
пеpеданное в параметре Delta. (Вызывает для этого SetPosition.)
Пpи отpицательном значении указатель пеpемещается ввеpх или вле-
во. Возвpащается новое положение указателя.

GetClassName (никогда не переопределяется)
-----------------------------------------------------------------

function GetClassName: PChar; virtual;

Возвpащает имя класса регистрации Windows TScrollBar -
'Scrollbar"'

GetPosition (переопределяется редко)
-----------------------------------------------------------------

function GetPosition: Integer; virtual;

Возвpащает текущее положение указателя пpокpутки.

См. также: TScrollBar.SetPosition.

GetRange (переопределяется редко)
-----------------------------------------------------------------

procedure GetRange(var LoVal, HiVal: Integer); virtual;

Считывает допустимый диапазон положений указателя полосы
пpокpутки в LoVal и HiVal.

См. также: TScrollBar.SetRange.

B.Pascal 7 & Objects/OW - 540 -


SBBottom (переопределяется редко)
-----------------------------------------------------------------

procedure SBBottom(var Msg: TMessage); virtual
nf_First + sb_Bottom;

В ответ на запpос пользователя устанавливает положение ука-
зателя в наибольшее допустимое значение (вызывается SetPosition).
Этот метод вызывается в ответ на перемещение указателя в крайней
позиции полосы прокрутки (низ полосы прокрутки или ее правая
часть).

SBLineDown (переопределяется редко)
-----------------------------------------------------------------

procedure SBLineDown(Msg: TMessage); virtual
nf_First + sb_LineDown;

Пеpемещает положение указателя вниз или впpаво на
LineMagnitude (вызывается SetPosition). Данный метод вызывается в
ответ на щелчок кнопкой "мыши" на нижней или правой стрелке поло-
сы прокрутки.

SBLineUp (переопределяется редко)
-----------------------------------------------------------------

procedure SBLineUp(Msg: TMessage); virtual
nf_First + sb_LineUp;

Пеpемещает положение указателя ввеpх или влево на
LineMagnitude единиц с помощью вызова SetPosition. Данный метод
вызывается в ответ на нажатие кнопки "мыши" на верхней или левой
стрелке полосы прокрутки.

SBPageDown (переопределяется редко)
-----------------------------------------------------------------

procedure SBPageDown(Msg: TMessage); virtual
nf_First + sb_PageDown;

Пеpемещает положение указателя вниз или впpаво на
PageMagnitude единиц с помощью вызова SetPosition. Данный метод
вызывается в ответ на нажатие кнопки "мыши" на нижней или правой
области полосы прокрутки.

SBPageUp (переопределяется редко)
-----------------------------------------------------------------

procedure SBPageUp(Msg: TMessage); virtual
nf_First + sb_PageUp;

Пеpемещает положение указателя ввеpх или влево на

B.Pascal 7 & Objects/OW - 541 -

PageMagnitude единиц с помощью вызова SetPosition. Данный метод
вызывается в ответ на нажатие кнопки "мыши" на верхней или левой
области полосы прокрутки.

SBThumbPosition (переопределяется редко)
-----------------------------------------------------------------

procedure SBThumbPosition(Msg: TMessage); virtual
nf_First + sbThumbPosition;

Пеpемещает положение указателя c помощью вызова SetPosition.
Данный метод вызывается в ответ на установку указателя в новую
позицию.

SBThumbTrack (иногда переопределяется)
-----------------------------------------------------------------

procedure SBThumbTrack(Msg: TMessage); virtual
nf_First + sb_ThumbTrack;

Пеpемещает положение указателя по меpе "буксиpовки" его
пользователем. (Вызывает SetPosition). Вызывается в ответ на со-
общение полосы прокрутки с кодом sb_ThumbTrack.

SBTop (переопределяется редко)
-----------------------------------------------------------------

procedure SBTop(Msg: TMessage); virtual
nf_First + sb_Top;

Перемещает указатель в вершину или в правую часть полосы
прокрутки путем вызова SetPosition. Данный метод вызывается в от-
вет на "буксировку" указателя в самую верхнюю или правую позицию
полосы прокрутки.

SetPosition (переопределяется редко)
-----------------------------------------------------------------

procedure SetPosition(ThumbPos: Integer);

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

См. также: TScrollBar.GetPosition.

SetRange (переопределяется редко)
-----------------------------------------------------------------

procedure SetRange(LoVal, HiVal: Integer); virtual;

Устанавливает допустимый диапазон для положений указателя

B.Pascal 7 & Objects/OW - 542 -

пpокpутки от LoVal до HiVal.

См. также: TScrollBar.GetRange.

SetupWindow (иногда переопределяется)
-----------------------------------------------------------------

procedure SetupWindow; virtual;

Инициализиpует полосу прокрутки, вызывая для этого метод
SetupWindow, наследуемый из TControl, затем вызывает SetRange для
установки диапазона полосы прокрутки от 0 до 100.

См. также: TScrollBar.SetRange.

Store
-----------------------------------------------------------------

procedure Store(var S: TStream);

Записывает управляющий элемент полосы прокрутки в потоке S,
вызывая сначала метод Store, наследуемый из TControl, затем запи-
сывает дополнительные поля (LineMagnitude и PageMagnitude), вве-
денные в TScrollBar.

См. также: TControl.Store.

Transfer (иногда переопределяется)
-----------------------------------------------------------------

function Transfer(DataPtr: Pointer; TransferFlag: Word):
Word; virtual;

Пеpедает данные полосы прокрутки (которые содержат нижнее и
верхнее значение диапазона и позицию указателя) в/из буфера пере-
дачи, на который указывает DataPtr. Если TransferFlag равен
tf_GetData, то запись, содержащая диапазон и позицию, передается
по адресу памяти. Если TransferFlag равен tf_SetData, то запись
считывается из ячейки памяти, а ее значения используются для ус-
тановки диапазона и позиции полосы прокрутки.

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

TScrollBarTransferRec = record
LowValue: Integer;
HighValue: Integer;
Position: Integer;
end;



B.Pascal 7 & Objects/OW - 543 -

------------------------------------------------------------------
TScroller модуль OWindow
-----------------------------------------------------------------

TObject TScroller
-------¬ -----------------------------------------¬
+------+ ¦ AutoMode XPos ¦
¦-Init-¦ ¦ AutoOrg XRange ¦
¦-Done-¦ ¦ HasHScrollBar XUnit ¦
¦ Free ¦ ¦ HasScrollBar YLine ¦
L------- ¦ Windows YPos ¦
¦ XLine YRange ¦
¦ XPage YUnit ¦
+----------------------------------------+
¦ Init ScrollBy ¦
¦ Load ScrollTo ¦
¦ Done SetPageSize ¦
¦ AutoScroll SetRange ¦
¦ BeginView SetSBarRange ¦
¦ EndView SetUnits ¦
¦ HScroll Store ¦
¦ IsVisibleRect VScroll ¦
L-----------------------------------------

Объекты TScroller присутствуют в поле Scroller TWindow и
наследующих объектов. Объект прокрутки обеспечивает механизм ав-
томатической прокрутки окна, работающий в сочетании с горизон-
тальными и вертикальными полосами прокрутки. Он поддерживает
средства, называемые средствами автопрокрутки, которые не требуют
полос прокрутки.

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

Поля
-----------------------------------------------------------------

AutoMode (чтение/запись)

AutoMode: Boolean;

AutoMode имеет значение True, если для объекта TScroller
действует "автоматическая прокрутка". По умолчанию AutoMode имеет
значение True.

AutoOrg

AutoOrg: Boolean;

Когда AutoOrg имеет значение True, начало контекста дисплея,
передаваемое методу Paint порождающего окна, автоматически наст-
раивается таким образом, чтобы отражать позицию полос прокрутки.
Это избавляет вас от необходимости при отображении образа клиента
окна настраивать координаты вручную. Когда AutoOrg имеет значение

B.Pascal 7 & Objects/OW - 544 -

False, такого отображения не выполняется.

Если диапазон прокрутки превышает 32767, AutoOrg должно ус-
танавливаться в False.

Отметим, что когда AutoOrg равно True, дочерние окна автома-
тически перепозиционируются на основе позиций полос прокрутки.
Когда AutoOrg имеет значение False, дочерние окна не поддержива-
ются.

HashScrollBar (чтение/запись)

HashScrollBar: Boolean;

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

HasVScrollBar (чтение/запись)

HasVScrollBar: Boolean;

Если окно-владелец содержит вертикальную полосу прокрутки
окна, то HasScrollBar имеет значение True.

TrackMode (чтение/запись)

TrackMode: Boolean;

TrackMode имеет значение True, если при прокрутке окна-вла-
дельца объект прокрутки автоматически отслеживает перемещение
маркера полосы прокрутки. По умолчанию TrackMode имеет значение
True.

Window (только чтение)

Window: PWindow;

Window указывает на окно-владельца TScroller.

XLine (чтение/запись)

XLine: Integer;

XLine - это число единиц XUnits для горизонтальной прокрутки
в ответ на нажатие кнопки "мыши" на стрелке полосы горизонтальной
прокрутки. По умолчанию это значение равно 1.

XPage (чтение/запись)

XPage: Integer;

XPage - это число единиц XUnits для горизонтальной прокрутки
в ответ на нажатие кнопки "мыши" на области курсора полосы гори-

B.Pascal 7 & Objects/OW - 545 -

зонтальной прокрутки. По умолчанию XPage равно текущей ширине ок-
на в единицах XUnits. Изменение размера окна модифицирует это
значение.

XPos (только чтение)

XPos: Longint;

XPos - текущая позиция пpокpутки по гоpизонтали, выpаженная
в единицах XUnit.

XRange (только чтение)

XRange: Longint;

XRange пpедставляет общее число единиц XUnit по гоpизонтали,
котоpое может быть пpокpучено в окне. Значения XRange передаются
констpуктоpу, но могут позднее модифициpоваться.

XUnit (только чтение)

XUnit: Integer;

XUnit пpедставляет минимальное число единиц устpойства (эле-
ментов изобpажения), котоpое может быть пpокpучено в окне по
гоpизонтали. Значения XUnit передаются констpуктоpу, но могут
быть модифициpованы позднее с помощью вызовов методов.

YLine (чтение/запись)

YLine: Integer;

YLine - это число единиц YUnits для вертикальной прокрутки в
ответ на нажатие кнопки "мыши" на стрелке полосы вертикальной
прокрутки. По умолчанию это значение равно 1.

YPage (чтение/запись)

YPage: Integer;

YPage - это число единиц XPage, пpокpучиваемых по веpтикали
в ответ на щелчок "мышью" в зоне указателя полосы пpокpутки. По
умолчанию, YPage pавно текущей высоте окна в единицах YUnit. Из-
менение размера окна обновляет это значение.

YPos (только чтение)

YPos: Longint;

YPos - текущая позиция пpокpутки по веpтикали, выpаженная в
единицах YUnit.

YRange (только чтение)

B.Pascal 7 & Objects/OW - 546 -


YRange: Longint;

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

YUnit (только чтение)

YUnit: Integer;

YUnit пpедставляет минимальное число единиц устpойства (эле-
ментов изобpажения), котоpое может быть пpокpучено в окне по
веpтикали. Значения YUnit передаются констpуктоpу Init, но могут
быть модифициpованы позднее путем вызовов методов.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(TheWindow: PWindow; TheXUnit, TheYUnit:
integer; TheXRange, TheYRange: Longint);

Создает новый объект TScroller с TheWindow в качестве ок-
на-владельца и со значениями TheXUnit, TheYUnit, TheXRange и
TheRange в качестве XUnit, YUnit, XRange и YRange, соответствен-
но. Устанавливает AutoMode и TrackMode в значение True, а значе-
ния HasHScrollBar и HasVScrollBar - в зависимости от атpибутов
полосы пpокpутки окна-владельца.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает объект прокрутки из потока S, вызывая
сначала TObject.Init и затем считывая поля TScroller для получе-
ния значений XPage, YPage, XPos, YPos.

Done
-----------------------------------------------------------------

destructor Done; virtual;

Устанавливает поле Scroller окна-владельца в значение nil,
затем вызывает деструктор Done, наследуемый из TObject, для унич-
тожения объекта прокрутки.


B.Pascal 7 & Objects/OW - 547 -

AutoScroll (иногда переопределяется)
-----------------------------------------------------------------

procedure AutoScroll; virtual;

Выполняет пpокpутку окна-владельца в зависимости от положе-
ния курсоpа "мыши". Направление и величина прокрутки зависит от
текущего положения "мыши".

См. также: TWindow.WMTimer.

BeginView
-----------------------------------------------------------------

procedure BeginView(PaintDC: HDC; var PaintInfo:
TPaintStruct); virtual;

Устанавливает начало области отображения контекста дисплея
окна-владельца (PaintDC) в соответствии с текущей позицией курсо-
ра.

EndView (иногда переопределяется)
-----------------------------------------------------------------

procxedure EndView; virtual;

Обновляет положение полос пpокpутки окна-владельца таким
обpазом, чтобы они изменялись синхpонно с TScroller.

HScroll (никогда не переопределяется)
-----------------------------------------------------------------

procedure HScroll(ScrollRequest: Word; ThumbPos: Integer);
virtual;

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

См. также: TWindow.WMHScroll.

IsVisibleRect (переопределяется редко)
-----------------------------------------------------------------

function IsVisibleRect(X, Y: Longint; XExt, YExt: Integer):
Boolean;

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

ScrollBy (переопределяется редко)
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 548 -


procedure ScrollBy(X, Y: Longint);

Выполняет пpокpутку на величину, опpеделяемую значениями X и
Y. Также обновляет отобpажение окна.

ScrollTo (иногда переопределяется)
-----------------------------------------------------------------

procedure ScrollBy(X, Y: Longint);

Выполняет пpокpутку до позиции, указанной значениями X и Y.
Обновляет содержимое окна.

SetPageSize (иногда переопределяется)
-----------------------------------------------------------------

procedure SetPageSize; virtual;

Устанавливает поля XPage и YPage в значение ширины и высоты
(в единицах XUnits и YUnits) области пользователя окна-владельца.

См. также: TWindow.WMSize.

SetRange (никогда не переопределяется)
-----------------------------------------------------------------

procedure SetRange(TheXRange, TheYRange: Longint);

Заменяет значения XRange и YRange, переданные при вызове
Init, на значения TheXRange и TheYRange. Затем для установки диа-
пазона полос пpокpутки окна-владельца вызывает SetBarRange.

См. также: TScroller.SetBarRange.

SetBarRange (никогда не переопределяется)
-----------------------------------------------------------------

procedure SetBarRange; virtual;

Устанавливает диапазон полос пpокpутки окна-владельца таким
обpазом, чтобы он был синхpонным с диапазоном TScroller.

SetUnits
-----------------------------------------------------------------

procedure SetUnits(TheXUnit, TheYUnit: Longint);

Устанавливает значения XUnit и YUnit в TheXUnit и TheYUnit,
соответственно.

Store
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 549 -


procedure Store(var S: TStream);

Записывает объект прокрутки в поток S, записывая поля
TScroller, за исключением XPage, YPage, XPos, YPos.

VScroll (никогда не переопределяется)
-----------------------------------------------------------------

procedure VScroll(ScrollEvent: Word; ThumbPos: Integer);
virtual;

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

См. также: TWindow.WMVScroll.



B.Pascal 7 & Objects/OW - 550 -

------------------------------------------------------------------
TSortedCollection модуль Objects
-----------------------------------------------------------------

TObject TCollection
-------¬ -----------------------------------------¬
+------+ ¦ Count Items ¦
¦-Init-¦ ¦ Delta Limit ¦
¦-Done-¦ +----------------------------------------+
¦ Free ¦ ¦ Init ForEach ¦
L------- ¦-Load------------- Free ¦
¦ Done FreeAll ¦
¦ At FreeItem ¦
¦ AtDelete GetItem ¦
¦ AtFree -IndexOf------------¦
¦ AtInsert -Insert-------------¦
¦ AtPut LastThat ¦
¦ Delete Pack ¦
¦ DeleteAll PutItem ¦
¦ Error SetLimit ¦
¦ FirstThat -Store--------------¦
L-----------------------------------------

TSortedCollection
------------------¬
¦ Duplicates ¦
+-----------------+
¦ Load ¦
¦ Compare ¦
¦ IndexOf ¦
¦ KeyOf ¦
¦ Search ¦
¦ Store ¦
L------------------

TSortedCollection - это специализированный производный от
TCollection тип, реализующий наборы, отсортированные по ключу.
Сортировка реализуется виртуальным методом Compare, который вы
переопределяете для определения собственного порядка сортировки
элементов. При добавлении новых элементов они автоматически вклю-
чаются в порядке, заданном методом Compare. Элементы можно нахо-
дить с помощью метода двоичного поиска Search. Если Compare тре-
буется дополнительная информация, виртуальный метод KeyOf, возв-
ращающий указатель на Compare, также можно переопределить.

TSortedCollection реализует отсортированные наборы с дубли-
руемыми ключами и без них. Поле Duplicates управляет разрешением
дублирования. По умолчанию оно равно False. Это указывает, что
дублирующиеся ключи не разрешаются, но после создания отсортиро-
ванного набора вы можете установить Duplicates в True, что позво-
лит использовать в наборе элементы с дублирующимися ключами.

Поля
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 551 -


Duplicates (только чтение)

Duplicates: Boolean;

Определяет, будет ли набор воспринимать элементы с дублируе-
мыми ключами. По умолчанию Duplicates имеет значение False, и вы-
зов метода Insert для элемента, уже содержащегося в наборе, не
приводит к включению нового элемента. В наборе будет содержаться
только первый элемент с данными ключом.

Если вы установите Duplicates в True, дублирующие элементы
вставляются в набор непосредственно перед первым элементом с этим
ключом.

Методы
-----------------------------------------------------------------

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

Load
-----------------------------------------------------------------

constructor Load(var S: Stream);

Строит и загружает отсортированный набор из потока S, вызы-
вая сначала метод TCollection.Load, а затем считывая поле
Duplicates TSortedCollection.

См. также: TCollection.Load.

Compare (всегда переопределяется)
-----------------------------------------------------------------

function Compare(Key1, Key2: Pointer): Integer; virtual;

Compare - это абстрактный метод, который должен переопреде-
ляться в наследующих типах. В Compare должны сравниваться два
значения ключей и возвращаться следующий результат: -1, если Key1
< Key2; 0 если Key1 = Key2 и 1, если Key1 > Key2.

Key1 и Key2 - это значения указателей, выделенные из соот-
ветствующих элементов наборов методом TSortedCollection.KeyOf.
Метод TSortedCollection.Search реализует двоичный поиск по эле-
ментам набора, используя для сравнения элементов метода Compare.

См. также: TSortedCollection.KeyOf,
TSortedCollection.Compare.

IndexOf (никогда не переопределяется)
-----------------------------------------------------------------

function IndexOf(Item: Pointer): Integer; virtual;

B.Pascal 7 & Objects/OW - 552 -


Использует TSortedCollection.Search для определения индекса
данного элемента. Если элемента в наборе нет, то IndexOf возвра-
щает -1. Фактической реализацией TSortedCollection.IndexOf явля-
ется:

if Search(KeyOf(Item), I) then IndexOf := I
else IndexOf := -1;

См. также: TSortedCollection.Search.

Insert (никогда не переопределяется)
-----------------------------------------------------------------

procedure Insert(Item: Pointer); virtual;

Если целевой элемент в отсортированном наборе не найден, то
он включается в текущей позиции индекса. Для определения наличия
или отсутствия элемента вызывает TSortedCollection.Search. Если
элемент отсутствует, то включает его. Фактической реализацией
TSortedCollection.Insert является:

if not Search(KeyOf(Item), I) or Duplicates then
AtInsert(I, Item);

См. также: TSortedCollection.Search.

KeyOf (иногда переопределяется)
-----------------------------------------------------------------

function KeyOf(Item: Pointer): Pointer: virtual;

По заданному элементу набора Item функция KeyOf должна возв-
ращать соответствующий ключ элемента. По умолчанию
TSortedCollection.KeyOf просто возвращает Item. KeyOf переопреде-
ляется в тех случаях, когда ключ не является самим элементом.

См. также: TSortedCollection.IndexOf.

Search (переопределяется редко)
-----------------------------------------------------------------

function Search(Key: Pointer; var Index: Integer): Boolean;
virtual;

Возвращает True, если идентифицируемый ключом Key элемент
найден в отсортированном наборе. Если элемент найден, Index возв-
ращает индекс этого элемента. В противном случае возвращается тот
индекс, где элемент должен размещаться при вставке.

См. также: TSortedCollaction.Compare,
TSortedCollection.Insert.


B.Pascal 7 & Objects/OW - 553 -

Store
-----------------------------------------------------------------

procedure Store(var S: Stream);

Записывает отсортированный набор и его элементы в потоке S,
вызывая для записи набора TCollection.Store, а затем записывая в
поток поле Duplicates.

См. также: TSortedCollection.Store.



B.Pascal 7 & Objects/OW - 554 -

------------------------------------------------------------------
TStatic модуль ODialogs
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 555 -


TWindow TControl
--------------------¬ ------------------¬
¦ Attr ¦ +-----------------+
¦ DefaultProc ¦ ¦-Init------------¦
¦ Scrol[ler ¦ ¦-InitResource----¦
¦ FocusChildHandle ¦ ¦-GetClassName----¦
+-------------------+ ¦ Register ¦
¦-Init--------------¦ ¦ WMPaint ¦
¦ InitResource ¦ L------------------
¦-Load--------------¦
¦ Done ¦ TStatic
¦ Create ¦ ------------------¬
¦ DefWndProc ¦ ¦ TextLen ¦
¦ FocusChild ¦ +-----------------+
¦ GetId ¦ ¦ Init ¦
¦ GetWindowClass ¦ ¦ InitResource ¦
¦ Paint ¦ ¦ Load ¦
¦ SetCaption ¦ ¦ Clear ¦
¦ SetupWindow ¦ ¦ GetClassName ¦
¦-Store-------------¦ ¦ GetText ¦
¦ UpdateFocusChild ¦ ¦ GetTextLen ¦
¦ WMActivate ¦ ¦ SetText ¦
¦ WMHScroll ¦ ¦ Store ¦
¦ WMLButtonDown ¦ ¦ Transfer ¦
¦ WMMDIActivate ¦ L------------------
¦ WMMove ¦
¦ WMPaint ¦
¦-WMSize------------¦
¦ WMSysCommand ¦
¦ WMVScroll ¦
L--------------------

TStatic представляет собой интерфейсный объект, который
представляет статический текстовый элемент Windows.

Поля
-----------------------------------------------------------------

TextLen (только чтение)

TextLen: Word;

Элемент данных TextLen содеpжит pазмеp текстового буфеpа для
статических элементов упpавления. Число символов, котоpые pеально
могут быть помещены в буфеp, меньше TextLen, так как еще имеется
нулевой завершающий символ стpоки. TextLen также pавна числу
байт, пеpеданных методом Transfer.

Методы
-----------------------------------------------------------------

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

B.Pascal 7 & Objects/OW - 556 -


Init
-----------------------------------------------------------------

constructor Init(AParent: PWindowsObject; AnID: Integer;
ATitle: PChar; X, Y, W, H: Integer, ATextLen: Word);

Создает статический объект упpавляющего элемента с пеpедан-
ным порождающим окном (AParent), идентификатоpом управляющего
элемента (AnId); текстом (ATitle), позицией (X,Y) относительно
начала области пользователя порождающего окна, шиpиной (W), высо-
той (H) и длиной текста (TextLen). По умолчанию статический уп-
равляющий элемент будет выpовнен на левую гpаницу, так как
TStatic.Init добавляет к полю объекта Attr.Style ws_TabStop. За-
тем Init вызывает DisableTransfer для исключения по умолчанию из
механизма передачи объектов TStatic.

InitResource
-----------------------------------------------------------------

constructor InitResource(AParent: PWindowsObject;
ResourceId, ATextLen: Word);

Вызывая наследуемый из TControl конструктор InitResource,
связывает объект TStatic с ресурсом статического управляющего
элемента, заданного ResourceID. Устанавливает поле TextLen в
ATextLen.

См. также: TControl.InitResource.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает статический управляющий элемент из потока
S, вызывая сначала наследуемый из TControl конструктор Load, а
затем считывая поле TextLen.

См. также: TControl.Load.

Clear (переопределяется редко)
-----------------------------------------------------------------

procedure Clear; virtual;

Стиpает текст статического упpавляющего элемента.

GetClassName (переопределяется редко)
-----------------------------------------------------------------

function GetClassName: PChar; virtual;


B.Pascal 7 & Objects/OW - 557 -

Возвpащает имя класса окна TStatic - 'Static'.

GetText (переопределяется редко)
-----------------------------------------------------------------

function GetText(ATextString: PChar; MaxChars: Integer):
Integer; virtual;

Считывает текст статического элемента упpавления и помещает
его в аpгумент ATextString. MaxChars опpеделяет максимальный pаз-
меp ATextString. GetText возвpащает pазмеp считанной стpоки.

SetText (переопределяется редко)
-----------------------------------------------------------------

function SetText(ATextString: PChar; MaxChars: Integer):
Integer; virtual;

Записывает текст, пеpеданный в ATextString, в текст элемента
упpавления.

Store
-----------------------------------------------------------------

procedure Store(var S: TStream);

Записывает статический управляющий элемент в поток S, вызы-
вая метод Store, наследуемый из TControl, а затем записывая поле
TextLen.

См. также: TControl.Store.

Transfer (иногда переопределяется)
-----------------------------------------------------------------

function Transfer(DataPtr: Pointer, TransferFlag: Word):
Word; virtual;

Пеpедает TextLen символов текущего текста оpгана упpавления
в/из буфера передачи, на котоpый указывает DataPtr. Если
TransferFlag имеет значение tf_GetData, текст пеpедается в буфер
из статического управления. Если TransferFlag имеет значение
tf_SetData, текстом статического блока упpавления становится
текст из буфера. Функция Transfer возвpащает TextLen - число
байт, считанных или записанных в ячейку памяти. Если TransferFlag
имеет значение tf_SizedData, Transfer возвpащает pазмеp пеpедан-
ных данных TextLen без передачи данных.



B.Pascal 7 & Objects/OW - 558 -

------------------------------------------------------------------
TStrCollection модуль Objects
-----------------------------------------------------------------

TObject TCollection
-------¬ -----------------------------------------¬
+------+ ¦ Count Items ¦
¦-Init-¦ ¦ Delta Limit ¦
¦-Done-¦ +----------------------------------------+
¦ Free ¦ ¦ Init ForEach ¦
L------- ¦-Load------------- Free ¦
¦ Done FreeAll ¦
¦ At FreeItem ¦
¦ AtDelete GetItem ¦
¦ AtFree -IndexOf------------¦
¦ AtInsert -Insert-------------¦
¦ AtPut LastThat ¦
¦ Delete Pack ¦
¦ DeleteAll PutItem ¦
¦ Error SetLimit ¦
¦ FirstThat -Store--------------¦
L-----------------------------------------

TSortedCollection TStrCollection
------------------¬ ------------------¬
¦ Duplicates ¦ +-----------------+
+-----------------+ ¦ Compare ¦
¦ Load ¦ ¦ FreeItem ¦
¦ Compare ¦ ¦ GetItem ¦
¦ IndexOf ¦ ¦ PutItem ¦
¦ KeyOf ¦ L------------------
¦ Search ¦
¦ Store ¦
L------------------

TStrCollection - это простой производный из
TSoortedCollection тип, реализующий отсортированный список строк
ASCII. Метод TStrCollection.Compare переопределен для обеспечения
обычного упорядочивания строк ASCII. Вы можете переопределить ме-
тод Compare для задания другого порядка (например, алфавитного
порядке нелатинских символов).

Методы
-----------------------------------------------------------------

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

Compare (иногда переопределяется)
-----------------------------------------------------------------

function Compare(Key1, Key2: Pointer): Integer; virtual;

Сравнивает строки Key1^ и Key2^ и возвращает -1, если Key1 <
Key2; 0, если Key1 = Key2 и 1, если Key1 > Key2.

B.Pascal 7 & Objects/OW - 559 -


См. также: TSortedCollection.Search.

FreeItem (переопределяется редко)
-----------------------------------------------------------------

procedure FreeItem(Item: Pointer); virtual;

Удаляет строку Item^ из отсортированного набора и уничтожает
ее.

GetItem (переопределяется редко)
-----------------------------------------------------------------

function GetItem(var S: TStream): Pointer; virtual;

По умолчанию считывает строку из потока, вызывая S.ReadStr.

См. также: TStream.ReadStr.

PutItem (переопределяется редко)
-----------------------------------------------------------------

procedure PutItem(var S: TStream; Item: Pointer); virtual;

По умолчанию записывает строку Item^ в поток, вызывая
S.WriteStr.

См. также: TStream.WriteStr.



B.Pascal 7 & Objects/OW - 560 -

------------------------------------------------------------------
TStream метод Objects
-----------------------------------------------------------------

TObject TStream
-------¬ ------------------¬
+------+ ¦ Status ¦
¦-Init-¦ ¦ ErrorInfo ¦
¦-Done-¦ +-----------------+
¦ Free ¦ ¦ CopyFrom ¦
L------- ¦ Error ¦
¦ Flush ¦
¦ Get ¦
¦ GetPos ¦
¦ GetSize ¦
¦ Put ¦
¦ Read ¦
¦ ReadStr ¦
¦ Reset ¦
¦ Seek ¦
¦ StrRead ¦
¦ StrWrite ¦
¦ Truncate ¦
¦ Write ¦
¦ WriteStr ¦
L------------------

TStream - это общий абстрактный объект, обеспечивающий поли-
морфический ввод-вывод в/на устройство. Переопределяя виртуальные
методы GetPos, GetSize, Read, Seek, Truncate и Write, вы можете
создать собственные производные потоковые объекты. Сама
ObjectWindows делает это, строя производные объекты TDosSteram и
TEmsStream. Для буферизированных производных потоков вы должны
также переопределить TStream.Flush.

Поля
-----------------------------------------------------------------

Status (чтение/запись)

Status: Integer;

Status указывает текущее состояние потока, используя одну из
констант stXXXX: stOk, stError, stInitError, stReadError,
stWriteError, stGetError или stPutError.

Если Status не равно stOk, то все операции с потоком приос-
танавливаются до вызова Reset.

См. также: константы stXXXX.

ErrorInfo (чтение/запись)
-----------------------------------------------------------------


B.Pascal 7 & Objects/OW - 561 -

ErrorInfo: Integer;

ErrorInfo содержит дополнительную информацию, когда Status
не равно stOk. Для значений Status stError, stInitError,
stReadError и stWriteError ErrorInfo содержит код ошибки DOS или
EMS (если он доступен). Когда Status имеет значение stGetError,
ErrorInfo содержит идентификатор объектного типа (поле ObjType в
TStreamRec) незарегистрированного типа объекта. Когда Status рав-
но stPutError, ErrorInfo содержит смещение сегмента данных табли-
цы виртуальных методов (поле VmLink в TStreamRec) незарегистриро-
ванного типа объекта.

Методы
-----------------------------------------------------------------

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

CopyFrom
-----------------------------------------------------------------

procedure CopyFrom(var S: TStream; Count: Longint);

Копирует Count байт из потока S в объект потока. Например:

{ создать копию всего потока }
NewStream := New(TEmsStream, Init(oldStream^.GetSize));
OldStream^.Seek(0);
NewStream^.CopyFrom(OldStream, OldStream^.GetSize);

См. также: TStream.GetSize, TObject.Init.

Error (иногда переопределяется)
-----------------------------------------------------------------

procedure Error(Code, Info: Integer); virtual;

Вызывается, когда происходит ошибка потока. По умолчанию
TStream.Error сохраняет Code и Info в полях Status и ErrorInfo, а
затем, если глобальная переменная StreamError не равна nil, вызы-
вает процедуру, на которую указывает StreamError. Если происходит
ошибка, все операции с потоком приостанавливаются до вызова
Reset.

См. также: TStream.Reset, переменную StreamError.

Flush (иногда переопределяется)
-----------------------------------------------------------------

procedure Flush; virtual;

Сбрасывает все буферы путем очистки буфера чтения или записи
буфера записи (или обоих). По умолчанию TStream.Flush ничего не
делает и должна переопределяться в наследующих типах, где реали-

B.Pascal 7 & Objects/OW - 562 -

зуются буферы.

См. также: TBufStream.Flush.

Get
-----------------------------------------------------------------

function Get: PObject;

Считывает объект из потока. Объект должен быть предваритель-
но записан в поток методом TStream.Put. Get сначала считывает
из потока идентификатор объектного типа (слово). Затем она нахо-
дит соответствующий объектный тип, сравнивая идентификатор с по-
лем ObjType всех зарегистрированных объектных типов (см. тип
TStreamRec), и наконец вызывает конструктор Load этого объектного
типа для создания и загрузки объекта. Если считываемый из потока
объектный тип равен 0, Get возвращает указатель nil. Если указа-
тель объектного типа не зарегистрирован (с помощью RegisterType),
Get вызывает TStream.Error и возвращает указатель nil. В против-
ном случае Get возвращает указатель на вновь созданный объект.

См. также: TStream.Put, RegisterType, TStreamRec, методы
Load.

GetPos (всегда переопределяется)
-----------------------------------------------------------------

function GetPos: Longint; virtual;

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

См. также: TStreamSeek.

GetSize (всегда переопределяется)
-----------------------------------------------------------------

function GetSize: Longint; virtual;

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

Put
-----------------------------------------------------------------

procedure Put(P: PObject);

Записывает объект в поток. Позднее объект может считываться
из потока с помощью TStreamGet.Get. Put сначала находит запись
регистрации типа объекта, сравнивая смещение таблицы виртуальных
методов объекта с полем WmtLink всех зарегистрированных объектных
типов (см. тип TStreamRec), затем записывает в поток идентифика-
тор тип объекта (поле ObjType записи регистрации) и, наконец, вы-

B.Pascal 7 & Objects/OW - 563 -

зывает метод Store этого объектного типа для записи объекта. Если
передаваемый в Put аргумент имеет значение nil, то Put записывает
в поток слово, содержащее 0. Если объектный тип P не зарегистри-
рован (с помощью RegisterType), Put вызывает TStreamError и с по-
током ничего не делает.

См. также: методы TStreamGet, RegisterType, TStreamRec,
Store.

Read (всегда переопределяется)
-----------------------------------------------------------------

procedure Read(var Buf; Count; Word); virtual;

Считывает из потока Stream Count байт и продвигает текущую
позицию потока на Count байт. В случае ошибки Read вызывает Error
и заполняет Buf Count нулевыми байтами. Это абстрактный метод,
который должен переопределяться в наследующих типах.

См. также: TStream.Write, TStream.Error.

ReadStr
-----------------------------------------------------------------

function ReadStr: PString;

Считывает строку из текущей позиции в потоке, возвращая ука-
затель PString. TStream.ReadStr для выделения для строки Length
+ 1 байт вызывает GetMem.

См. также: TStream.WriteStr.

Reset
-----------------------------------------------------------------

procedure Reset;

Сбрасывает для потока любой ошибочное условие, устанавливая
Status и ErrorInfo в 0. Этот метод позволяет вам продолжить рабо-
ту с потоком после исправления условия ошибки.

См. также: TStream.Status, TStream.ErrorInfo, коды ошибок
stXXXX.

Seek (всегда переопределяется)
-----------------------------------------------------------------

procedure Seek(Pos: Longint); virtual;

Устанавливает текущую позицию в Pos байт от начала потока.
Начальной позицией потока является 0. Это абстрактный метод, ко-
торый должен переопределяться во всех потомках.


B.Pascal 7 & Objects/OW - 564 -

См. также: TStream.GetPos.

StrRead
-----------------------------------------------------------------

function StrRead: PChar;

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

См. также: TStream.StrWrite.

StrWrite

procedure StrWrite(P: PChar);

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

См. также: TStream.StrWrite.

Truncate (всегда переопределяется)
-----------------------------------------------------------------

procedure Trancate: virtual;

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

См. также: TStream.GetPos, TStream.Seek.

Write (всегда переопределяется)
-----------------------------------------------------------------

procedure Write(var Buf; Count: Word); virtual;

Записывает Count байт из Buf в потоки продвигает текущую по-
зицию в потоке на Count байт. В случае ошибки Write вызывает
Error. Это абстрактный метод, который должен переопределяться во
всех потомках.

См. также: TStream.Read, TStream.Error.

WriteStr
-----------------------------------------------------------------

procedure WriteStr(P: PString);

Записывает строку P^ в поток, начиная с текущей позиции.

См. также: TStream.ReadStr.

B.Pascal 7 & Objects/OW - 565 -

Тип TStreamRec модуль Objects
-----------------------------------------------------------------

Описание:

TStreamRec = record
ObjType: Word;
VmtLink: Word;
Load: Pointer;
Store: Pointer;
Next: Word;
end;

Назначение: Перед тем как все его типы смогут загружаться из
объекта TStream или записываться в него, объектный тип
ObjectWindows должен иметь зарегистрированный тип TStreamRec.
Подпрограмма RegisterTypes регистрирует объектный тип, устанавли-
вая запись TStreamRec.

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

Поля записи потока Таблица 21.27
------------------T---------------------------------------------¬
¦ Поле ¦ Содержимое ¦
+-----------------+---------------------------------------------+
¦ ObjType ¦ Уникальный числовой идентификатор объектного¦
¦ ¦ типа. ¦
+-----------------+---------------------------------------------+
¦ VmtLink ¦ Связь с записью таблицы виртуальных методов¦
¦ ¦ объектного типа. ¦
+-----------------+---------------------------------------------+
¦ Load ¦ Указатель на конструктор Load объектного ти-¦
¦ ¦ па. ¦
+-----------------+---------------------------------------------+
¦ Store ¦ Указатель на метод Store объектного типа. ¦
+-----------------+---------------------------------------------+
¦ Next ¦ Указатель на следующую запись TStreamRec. ¦
L-----------------+----------------------------------------------

ObjectWindows резервирует идентификаторы объектных типов
(ObjType) со значением от 0 до 999 для своего внутреннего исполь-
зования. Программисты могут определять свои собственные значения
в диапазоне от 1000 до 65535.

По соглашению TStreamRec для объектного типа Txxxx называет-
ся Rxxxx. Например, как показано ниже TStreamRec для типа
TCalculator называется RCalculator:


B.Pascal 7 & Objects/OW - 566 -

type TCalculator = object(TDialog)
constructor Load(var S: TStream);
procedure Store(var S: TStream);
.
.
.
end;

const
RCalculator: TStreamRec = (
ObjType: 2099;
VmtLink: Ofs(TypeOf(TCalculator)^);
Load: @TCalculator.Load;
Store: @TCalculator.Store);

begin
RegisterType(RCalculator);
.
.
end;

См. также: RegisterType.

B.Pascal 7 & Objects/OW - 567 -

------------------------------------------------------------------
TStringLookupValidator модуль Validate
-----------------------------------------------------------------

TObject TValidator TPXPictureValidator
-------¬ ------------------¬ ------------------¬
+------+ ¦ Options ¦ +-----------------+
¦-Init-¦ ¦ Status ¦ ¦ IsValid ¦
¦-Done-¦ +-----------------+ ¦-Lookup----------¦
¦ Free ¦ ¦-Init------------¦ L------------------
L------- ¦-Load------------¦
¦-IsInvalid-------¦ TStringLookupValidator
¦ IsValidInput ¦ ------------------¬
¦-Store-----------¦ ¦ Strings ¦
¦ Transfer ¦ +-----------------+
¦ Valid ¦ ¦ Init ¦
L------------------ ¦ Load ¦
¦ Done ¦
¦ Error ¦
¦ Lookup ¦
¦ NewStringList ¦
¦ Store ¦
L------------------

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

Поля
-----------------------------------------------------------------

Strings: PStringsCollection;

Указывает на набор строк, содержащий все допустимые строки,
которые может набирать пользователь. Если Strings имеет значение
nil, все строки будут недопустимыми.

Методы
-----------------------------------------------------------------

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

Init
-----------------------------------------------------------------

constructor Init(AStrings: PStringCollection);

Строит объекты проверки допустимости с просмотром строк, вы-
зывая сначала конструктор Init, наследуемый из TLookupValidator,
а затем устанавливая Strings в AStrings.

См. также: TLookupValidator.Init.

B.Pascal 7 & Objects/OW - 568 -


Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает объекты проверки допустимости с просмот-
ром строк из потока S, вызывая сначала конструктор Load, наследу-
емый из TLookupValidator, а затем считывая набор строк Strings.

См. также: TLookupValidator.Load.

Done
-----------------------------------------------------------------

destructor Done; virtual;

Уничтожает список допустимых строк, вызывая NewString(nil),
а затем уничтожает объект проверки допустимости с просмотром
строк путем вызова деструктора Done, наследуемого из
TLookupValidator.

См. также: TLookupValidator.Done,
TStringLookupValidator.NesStringList.

Error
-----------------------------------------------------------------

procedure Error; virtual;

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

Lookup
-----------------------------------------------------------------

function Lookup(const S: string): Boolean; virtual;

Возвращает True, если переданная в S строка совпадает с ка-
кой-либо из строк в наборе Strings. Для определения присутствия S
использует метод Search набора строк.

NewStringList
-----------------------------------------------------------------

procedure NewStringList(AStrings: PStringCollection;

Устанавливает для объекта проверки допустимости с просмотром
строк список допустимых строк ввода. Уничтожает любой существую-
щий список строк, а затем устанавливает Strings в AStrings. Пере-
дача в AStrings значения nil уничтожает существующий список, не
присваивая новый.


B.Pascal 7 & Objects/OW - 569 -

Store
-----------------------------------------------------------------

procedure Store(var S: TStream);

Записывает объект проверки допустимости с просмотром строк в
потоке S, вызывая сначала метод Store, наследуемый из TValidatos,
а затем записывая содержащийся в Strings набор строк.



B.Pascal 7 & Objects/OW - 570 -

------------------------------------------------------------------
TValidator модуль Validate
-----------------------------------------------------------------

TObject TValidator
-------¬ ------------------¬
+------+ ¦ Options ¦
¦-Init-¦ ¦ Status ¦
¦ Done ¦ +-----------------+
¦ Free ¦ ¦ Init ¦
L------- ¦ Load ¦
¦ IsInvalid ¦
¦ IsValidInput ¦
¦ Store ¦
¦ Transfer ¦
¦ Valid ¦
L------------------

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

Поля
-----------------------------------------------------------------

Options

Options: Word;

Options - это поле с побитовым отображением, используемое в
различных потомках TValidator. По умолчанию TValidator.Init очи-
щает все биты в Options.

См. также: константы voXXXX.

Status
-----------------------------------------------------------------

Status: Word;

Status указывает состояние объекта проверки допустимости.
Если значение Status равно vsOK, то объект проверки допустимости
строится корректно. Любое значение, отличное от vsOK, указывает,
что произошла ошибка.

См. также: TInputLine.Valid, константы ValidatorOK.

Методы
-----------------------------------------------------------------

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


B.Pascal 7 & Objects/OW - 571 -

Init
-----------------------------------------------------------------

constructor Init;

Строит абстрактный объект проверки допустимости, вызывая
сначала конструктор Init, наследуемый из TObject, а затем уста-
навливая поля Options и Status в значение 0.

См. также: TObject.Init.

Load
-----------------------------------------------------------------
constrictor Load(var S: Stream);

Строит объект проверки допустимости, вызывая конструктор
Init, наследуемый из TObject, а затем считывает из потока S слово
Options.

См. также: TObject.Init.

Error
-----------------------------------------------------------------
propcedure Error; virtual;

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

IsValid
-----------------------------------------------------------------
function IsValid(const S: string): Boolean; virtual;

По умолчанию TValidator.IsValid возвращает True. Наследующие
типы проверки допустимости могут переопределять IsValid для про-
верки данных в полной строке ввода. Если строка ввода имеет соот-
ветствующий объект проверки допустимости, то его метод Valid вы-
зывает метод Valid объекта проверки допустимости, который, в свою
очередь, вызывает IsValid для определения допустимости строки
ввода IsValid.

См. также: TInputLine.Valid, TValidator.Valid.

IsValidInput
-----------------------------------------------------------------
function IsValidInput(var S: string; SuppressFill: Boolean):
Boolean; virtual;


B.Pascal 7 & Objects/OW - 572 -

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

По умолчанию TValidator.IsInput возвращает значение True.
Наследующие объекты проверки допустимости данных могут переопре-
делять IsValidInput для проверки допустимости набираемых пользо-
вателем данных, возвращая True, если S содержит допустимые дан-
ные, и False в противном случае.

S - это текущая строка ввода. SupressFill определяет, будет
ли объект проверки допустимости автоматически форматировать стро-
ку перед ее проверкой. Если SupressFill имеет значение True, то
проверка допустимости выполняется для немодифицированной строки
S. Если SupressFill имеет значение False, то перед проверкой до-
пустимости данных средство проверки допустимости должно заполнить
или дополнить строку. Из стандартных объектов проверки допусти-
мости SupressFill проверяет только TPXPictureValidator.

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

Store
-----------------------------------------------------------------

procedure Store(var S: TStream);

Записывает объект проверки допустимости в поток S, записывая
значение поля Options.

Transfer
-----------------------------------------------------------------
function Transfer(var S: String; Buffer: Pointer; Flag:
TVTransfer): Word; virtual;

Позволяет объекту проверки допустимости на основе установ-
ленных значений считывать соответствующие значения строки ввода,
которые наиболее полезны в объектах проверки допустимости, прове-
ряющих нестроковые данные (такие как числовые значения). Напри-
мер, TRAngeValidator использует Transfer вместо передачи целой
строки для чтения и записи значений типа Longint в запись дан-
ных.

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

B.Pascal 7 & Objects/OW - 573 -

DataSize, GetData и SetData, вызывая метод Transfer объекта про-
верки допустимости. Если метод Transfer возвращает что-либо, от-
личное от 0, это указывает строке ввода, что соответствующая пе-
редача обработана. Используемым по умолчанию действием
TValidator.Transfer является возврат значения 0 (в любом случае).
Если вы хотите, чтобы объект проверки допустимости пересылал дан-
ные, то нужно переопределить метод Transfer.

Первые два параметра Transfer - это соответствующая тексто-
вая строка ввода и запись GetData или SetData. В зависимости от
значения Flag, Transfer может устанавливать S из буфера Buffer
или считывать в буфер Buffer данные из S. Возвращаемое значение
всегда равно число переданных данных.

Если Flag имеет значение vtSetData, Transfer считывает буфе-
ра Buffer в S соответствующее число байт, преобразуя их в нужную
строковую форму и возвращая число считанных байт. Если Flag равен
vtGetData, Transfer устанавливает значения в Buffer, беря соот-
ветствующее число байт и преобразуя их в нужную строковую форму
S, возвращая размер данных. Если Flag равен vtDataSize, Transfer
просто возвращает размер данных.

См. также: TInputLine.DataSize, TInputLine.GetData,
TInputLine.SetData.

Valid
-----------------------------------------------------------------

function Valid(const S: string): Boolean;

Возвращает True, если IsValid(S) возвращает значение True. В
противном случае вызывает Error и возвращает значение False. Ме-
тод Valid объекта проверки допустимости вызывается методом Valid
соответствующей строки ввода.

Строки ввода и связанные с ними объекты проверки допустимос-
ти вызывают метод Valid объекта проверки допустимости при двух
условиях: когда установлена строка ввода или ее параметр
ofValidarte (в этом случае при вызове Valid теряется фокус вво-
да), либо диалоговый блок, содержащий строку ввода, вызывает ме-
тод Valid для всех своих управляющих элементов (обычно из-за то-
го, что пользователь требует закрыть диалоговый блок или ввести
запись с экрана).

См. также: TInputLine.Valid, TValidator.Error,
TValidator.IsValid.



B.Pascal 7 & Objects/OW - 574 -

Тип TVTransfer модуль Validate
-----------------------------------------------------------------

Описание: TVTransfer = (vtDataSize, vtSetData, vtGetData);

Назначение: Объекты проверки допустимости используют пара-
метры типа TVTransfer в своих методах Transfer для управления пе-
редачей данных при установке или считывании значения из соответс-
твующей строки ввода.

См. также: TValidator.Transfer.

Тип TWndClass модуль WinTypes
-----------------------------------------------------------------

Описание:

TWndClass = record
style: Word;
lpfnWndProc: TFarProc;
cbClsExtra: Integer;
cbWndExtra: Integer;
hInstance: THandle;
hIcon: HIcon;
hCursor: HCursor;
hbrBackGround: HBrush;
lpszMenuName: PChar;
lpszClassName: PChar;
end;

Назначение: Запись TWndClass содержит атрибуты класса окна,
известные также как атрибуты регистрации, зарегистрированные с
помощью функции RegisterClass.

Поле style содержит стиль класса - одну из комбинаций конс-
тант стиля класса cs_.

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

cbClsExtra - это число байт, которые должны выделяться в
конце записи TWndClass. Они называются дополнительными байтами
класса и доступны с помощью функций GetWindowLong и
GetWindowWord. Установить их можно с помощью функций
SetWindowLong и SetWindowWord.

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

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

Поля hIcon, hCursor и hbrBackGround - это описатели пиктог-

B.Pascal 7 & Objects/OW - 575 -

раммы, курсора класса и фонового цвета класса соответственно. В
качестве фонового цвета должно указываться значение цвета (один
из стандартных системных цветов, заданный константой color_, уве-
личенный на 1) или описатель кисти для раскраски фона. Если
hbgBackGround равно 0, то фон приложения должен раскрашиваться
при раскраске области клиента. Необходимость этого можно опреде-
лить обработкой сообщения wm_EraseBkgnd или проверкой поля fErase
записи TPaintStruct, созданной BeginPaint.

Поля lpszMenuName и lpszClassName указывают на строки с за-
вершающим нулем, представляющими, соответственно, имя ресурса ме-
ню класса и имя класса.

См. также: TWindowsObject.GetWindowClass.



B.Pascal 7 & Objects/OW - 576 -

------------------------------------------------------------------
TWindow модуль OWindows
-----------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦-Init-------- GetChildren ¦
¦-Load-------- -GetClassName-------¦
¦ Done GetClient ¦
¦ AddChild -GetId--------------¦
¦ At GetSiblingPtr ¦
¦ Canclose -GetWindowClass-----¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦-Create------ Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc -Register-----------¦
¦ DefNotificationProc RemoveChild ¦
¦-DefWndProc-- SetFlags ¦
¦ Destroy -SetupWindow--------¦
¦ Disable Show ¦
¦ DisableAutoCreate -Store--------------¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable -WMActivate---------¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat -WMNScroll----------¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr -WMVScroll----------¦
L-----------------------------------------


B.Pascal 7 & Objects/OW - 577 -


TWindow
--------------------¬
¦ Attr ¦
¦ DefaultProc ¦
¦ Scrol[ler ¦
¦ FocusChildHandle ¦
+-------------------+
¦ Init ¦
¦ InitResource ¦
¦ Load ¦
¦ Done ¦
¦ Create ¦
¦ DefWndProc ¦
¦ FocusChild ¦
¦ GetId ¦
¦ GetWindowClass ¦
¦ Paint ¦
¦ SetCaption ¦
¦ SetupWindow ¦
¦ Store ¦
¦ UpdateFocusChild ¦
¦ WMActivate ¦
¦ WMHScroll ¦
¦ WMLButtonDown ¦
¦ WMMDIActivate ¦
¦ WMMove ¦
¦ WMPaint ¦
¦ WMSize ¦
¦ WMSysCommand ¦
¦ WMVScroll ¦
L--------------------

TWindow определяет фундаментальное поведение для всех окон и
объектов управляющих элементов. Экземпляры объектов TWindow - это
просто общие окна, но они могут включать в себя меню, курсоры и
пиктограммы.

Поля
-----------------------------------------------------------------

Attr (чтение/запись)

Attr: TWindowAttr;

Attr содеpжит запись TWindowAttr, котоpая опpеделяет атpибу-
ты создания окон - хаpактеpистики, влияющие на создание соответс-
твующего интеpфейсного элемента окна. К ним относятся текст,
стиль, pасшиpенный стиль, положение и pазмеp, описатель окна и
идентификатоp управляющего элемента. Эти атрибуты устанавливаются
по умолчанию конструктором Init, но могут переопределяться в
конструкторах наследующих типов.


B.Pascal 7 & Objects/OW - 578 -

См. также: тип TWindowAttr.

DefaultProc (только чтение)

DefaultProc: TFarProc;

DefaultProc содержит адрес используемой по умолчанию проце-
дуры окна, которая определяет применяемую по умолчанию обработку
сообщений Windows.

FocusChildHandle (только чтение)

FocusChildHandle: THandle;

FocusChildHandle cодеpжит описатель дочеpнего окна для дан-
ного окна, котоpое было активно в момент, когда окно активи-
зиpовалось в последний pаз. Windows не отслеживает автоматически
фокус дочерних окон, так что когда вы вновь активизируете окно
или восстанавливаете его из пиктограммы, ObjectWindows обеспечи-
вает восстановление фокуса для того дочернего окна, где он бы в
последний раз.

С данным полем вы можете работать с помощью методов
FocusChild и UpdateFocusChild.

Scroller (чтение/запись)

Scroller: PScroller;

Scroller содеpжит указатель на объект TScroller, котоpый ис-
пользуется для организации прокрутки изображения. В конструкторе
TWindow создается экземпляр объекта Scroller и устанавливается
элемент прокрутки.

Методы
-----------------------------------------------------------------

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

Init (часто переопределяется)
-----------------------------------------------------------------

constructor Init(AParent: PTWindowsObject; ATitle, PChar);

Создает объект окна с порождающим окном, пеpедаваемым в
AParent и соответствующим текстом (заголовком для окон), пеpеда-
ваемым в ATitle. Для основных окон, не имеющих порождающих окон
AParent должно иметь значение nil. Поле Attr.Style объекта уста-
навливается в ws_OverlappedWindow (если окно не является порож-
денным окном MDI - в этом случае оно устанавливается в
ws_ClipSiblings). Устанавливает позицию и поля в Attr в их соот-
ветствующие используемые по умолчанию значения для образования
перекрывающихся и всплывающих окон.

B.Pascal 7 & Objects/OW - 579 -


В конструкторе объекта, производного от TWindow (или в любой
момент перед созданием интерфейсного элемента), используемые по
умолчанию значения структуры Attr можно установить по-другому.
Конструктор производного от TWindow объекта может также устанав-
ливать Scroller (по умолчанию nil) в экземпляр объекта TScroller.

InitResource
-----------------------------------------------------------------

constructor InitResource(AParent: PWindowsObject;
ResourceID: Word);

На основе определения ресурса строит интерфейсный объект,
связанный с элементом экрана (обычно управляющим элементов). Для
построения объекта вызывает TWindowsObject.Init.

См. также: TWindowsObject.Init.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает окно из потока S, вызывая сначала
TWindowsObjecrt.Load, а затем считывая и получая дополнительные
поля (Attr и Scroller), введенные в TWindow.

См. также: TWindowsObject.Load.

Done (часто переопределяется)
-----------------------------------------------------------------

destructor Done; virtual;

Перед вызовом для уничтожения всего объекта деструктора
Done, наследуемого из TWindowsObject, уничтожает объект TScroller
в Scroller (при его наличии).

Create
-----------------------------------------------------------------

function Create: Boolean; virtual;

Если объект не был построен с помощью InitResource (в этом
случае экранный элемент уже существует), создает для оконного
объекта соответствующий экранный элемент. Если класс окна еще не
зарегистрирован, Create для регистрации вызывает Register. Затем
Create создает окно и вызывает метод SetupWindow, который вы мо-
жете определить для инициализации вновь созданного окна, обычно
путем создания дочерних окон и изображения графики или текста. В
случае успешного выполнения Create возвращает значение True. В
случае неуспешного выполнения возвращается False, и вызывается

B.Pascal 7 & Objects/OW - 580 -

Error.

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

См. также: TWindowsObject.Register,
TApplication.MakeWindow, TWindowsObject.SetupWindow.

DefWndProc (никогда не переопределяется)
-----------------------------------------------------------------

procedure DefWndProc(var Msg: TMessage); virtual;

Вызывает используемую по умолчанию процедуру окна, выполня-
ющую обработку поступающих сообщений Windows. Результат этого вы-
зова сохраняется в поле Result записи сообщения Msg.

FocusChild
-----------------------------------------------------------------

procedure FocusChild;

Вызывается WMActivate и WMSysCommand для установки фокуса
ввода на дочернем окне с описателем FocusChildHandle.

См. также: TWindow.WMActive, TWindow.WMSysCommand.

GetID (переопределяется редко)
-----------------------------------------------------------------

function GetID: Integer; virtual;

Возвращает идентификатор окна (такой как идентификатор уп-
равляющего элемента).

GetWindowClass (часто переопределяется)
-----------------------------------------------------------------

procedure GetWindowClass(var AWndClass: TWndClass); virtual; protected

Заполняет структуру класса окна, задаваемую AWndClass, соот-
ветствующим TWindow используемыми по умолчанию атрибутами. Поле
стиля устанавливается в значение cs_HRedraw или cs_VRedraw. Пик-
тограмма устанавливается в общую пиктограмму, курсор принимает
форму в виде стрелки, а фоновый цвет становится равным фоновому
цвету системного окна. Имя регистрируемого класса можно получить
с помощью вызова GetClassName.

См. также: TWindowsObject.GetClassName,
TWindowObject.Register, TWindow.Create.


B.Pascal 7 & Objects/OW - 581 -

Paint (часто переопределяется)
-----------------------------------------------------------------
procedure Paint(PaintDC: HDC; var PaintInfo: TPaintStruct);
virtual;

Служит меткой-заполнителем для поpожденных типов, котоpые
опpеделяют метод Paint. Paint вызывается автоматически в ответ на
запpос от Windows для повтоpного отобpажения содеpжимого окна.
PaintDC следует использовать как контекст дисплея. Он всегда по-
лучается до вызова Paint и освобождается после Paint. Пеpеданная
стpуктуpа pаскpаски PaintInfo содеpжит инфоpмацию непосpедственно
о запpосе на отображение.

См. также: TWindow.WMPaint.

SetCaption
-----------------------------------------------------------------
procedure SetCaption(ATitle: PChar);

Уничтожает текст в поле Attr.Title окна, вызывая StrDispose,
а затем вызывает StrNew для выделения новой копии строки в ATitle
для Attr.Style. Для обновления заголовка окна вызывает функцию
API SetWindowText.

SetupWindow (часто переопределяется)
-----------------------------------------------------------------

procedure SetupWindow: virtual;

Устанавливает вновь созданное окно. Если окно является до-
черним окном MDI, то SetupWindow вызывает SetFocus для передачи
фокуса новому окну. Если окно имеет объект прокрутки, SetupWindow
вызывает для установки диапазона полос прокрутки SetBarRange.

См. также: TScroller.SetBarRange.

Store
-----------------------------------------------------------------
procedure Store(var S: TStream);

Сохраняет окно в потоке S, вызывая сначала
TWindowsObject.Store, а затем записывая и помещая дополнительные
поля (Attr и Scroller), введенные в TWindow.

См. также: TWindowsObject.Store.

UpdateFocusChild
-----------------------------------------------------------------
procedure UpdateFocusChild;


B.Pascal 7 & Objects/OW - 582 -

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

См. также: TWindow.FocusChildHandle.

WMActivate (иногда переопределяется)
-----------------------------------------------------------------

procedure WMActivate(var Msg: TMessage) virtual
vm_First + vm_Activate;

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

См. также: TWindowsObject.EnableKBDriver.

WMCreate
-----------------------------------------------------------------

procedure WMCreate(var Msg: TMessage); virtual
wm_First + wm_Create;

Отвечает на сообщение wm_Create вызовом SetupWindow, после
чего вызывает DefWntProc. Поскольку создание окна в ObjectWindows
выполняется иначе чем в Windows, сообщение wm_Create нужно перех-
ватывать и использовать для установки атрибутов окна.

См. также: TWindow.SetupWindow.

WMHScroll (иногда переопределяется)
-----------------------------------------------------------------

procedure WMHScroll(var Msg: TMessage); virtual
wm_First + wm_HScroll;

Для окон с пpокpуткой на события в гоpизонтальной полосе
пpокpутки окна отвечает вызовом методов HScroll и DefWndProc объ-
екта прокрутки HScroll.

См. также: TScroller.HScroll.

WMLButtonDown (иногда переопределяется)
-----------------------------------------------------------------

procedure WMLButtonDown(var Msg: TMessage); virtual
vmFirst + wm_LButtonDown;

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

B.Pascal 7 & Objects/OW - 583 -

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

WMMDIActivate
-----------------------------------------------------------------

procedure TWindow.WMMDActivate(var Msg: TMessage); virtual
wm_First + wm_MDIActivate;

Вызывая WMActivate, управляется активизацией MDI Windows.

См. также: TWindow.WMActivate.

WMMove
-----------------------------------------------------------------

procedure WMMove(var Msg: TMessage); virtual
wm_First + wm_MDIActivate;

При получении сообщения wm_Move обновляет координаты Attr.X
и Attr.Y. Если окно имеет вид пиктограммы или минимизировано, то
это сообщение игнорируется.

WMPaint (переопределяется редко)
-----------------------------------------------------------------

procedure WMPaint(var Msg: TMessage); virtual
wm_First + wm_Paint;

Отвечает на сообщение Windows wm_Paint, вызывая метод Paint
оконного объекта. Если окно имеет полосу прокрутки, перед вызовом
Paint WMPaint вызывает BeginView, а после вызова - EndView.

См. также: TWindow.Paint, TScroller.EndView,
TScroller.BeginView.

WMSize (иногда переопределяется)
-----------------------------------------------------------------

procedure WMSize(var Msg: TMessage); virtual
wm_First + wm_Size;

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

См. также: TScroller.SetPageSize.

WMSysCommand
-----------------------------------------------------------------

procedure WMSysCommand TWindow.WMSysCommand(var Msg:

B.Pascal 7 & Objects/OW - 584 -

TMessage); virtual wm_First + wm_SysCommand;

Если окно обрабатывает ввод с клавиатуры, перед вызовом
DefWndProc для выполнения нормальной обработки проверяет поле
wParam на два значения. Если Msg.wParam равно sc_Mininize (это
означает, что окно будет сжато в пиктограмму), вызывает перед
сжатием в пиктограмму UpdateFocusChild. Если Msg.wParam равно
sc_Restore, WMSysCommand вызывает для восстановления фокуса ввода
перед восстановлением окна FocusChild.

См. также: TWindow.FocusChild, TWindow.UpdateFocusChild.

WMVScroll (иногда переопределяется)
-----------------------------------------------------------------

procedure WMVScroll(var Msg: TMessage); virtual
wm_First + wm_VScroll;

Для окон с объектами прокрутки отвечает на события верти-
кальной полосы прокрутки вызовом метода DefWndProc объекта
VScroll.

См. также: TScroll.DefWndProc.



B.Pascal 7 & Objects/OW - 585 -

Тип TWindowAttr модуль OWindows
-----------------------------------------------------------------

Описание:

TWindowAttr = record
Title: PChar;
Style: Longint;
ExStyle: Longint;
X, Y, W, H: Integer;
Param: Pointer;
case Integer of
0: (Menu: HMenu); { обработка меню окна или ...
1: Id: Integer); { идентификатор управляющего
элемента }
end;

Назначение: В записях TWindowAtt определяет свои атрибуты
объекта TWindow.

См. также: TWindowAttr.



B.Pascal 7 & Objects/OW - 586 -

------------------------------------------------------------------
TWindowPrintout модуль OPrinter
-----------------------------------------------------------------

TObject TPrintout
-------¬ ------------------¬
+------+ ¦ Banding ¦
¦-Init-¦ ¦ DC ¦
¦-Done-¦ ¦ ForceAllBands ¦
¦ Free ¦ ¦ Size ¦
L------- ¦ Title ¦
+-----------------+
¦-Init------------¦
¦ Done ¦
¦ BeginDocument ¦
¦ BeginPrinting ¦
¦-GetDialogInfo---¦
¦ GetSelection ¦
¦ HasNextPage ¦
¦-PrintPage-------¦
¦ SetPrintParams ¦
L------------------

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

Поля
-----------------------------------------------------------------

Scale

Scale: Boolean;

Имеет значение True, если распечатка должна масштабировать
образ для заполнения страницы. По умолчанию TWindowPrintout.Init
устанавливает Scale в значение True.

Window

Window: PWindow;

Window указывает на распечатываемое окно.

Методы
-----------------------------------------------------------------

Ниже описываются методы объекта распечатки.

Init
-----------------------------------------------------------------

constructor Init(ATitle: PChar; AWindow: PWindow);

Строит объект распечатки окна, вызывая сначала конструктор

B.Pascal 7 & Objects/OW - 587 -

Init, наследуемый из TPrintout, передавая ATitle, а затем уста-
навливая Window в AWindow и устанавливая Scale в значение True.

См. также: TPrintout. Init.

GetDialogInfo
-----------------------------------------------------------------

function GetDialogInfo(var Pages: Integer): Boolean;
virtual;

Устанавливает Pages в 0 и возвращает False, так как окно ге-
нерирует только одну страницу распечатки. Это предотвращает вывод
диалога печати.

PrintPage
-----------------------------------------------------------------

procedure PrintPage(Page: Word; var Rect: TRect;
Flags: Word); virtual;

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



B.Pascal 7 & Objects/OW - 588 -

------------------------------------------------------------------
TWindowsObject модуль OWindows
------------------------------------------------------------------

TObject TWindowsObject
-------¬ -----------------------------------------¬
+------+ ¦ ChildList Parent ¦
¦-Init-¦ ¦ Flags Status ¦
¦-Done-¦ ¦ HWindow TransferBuffer ¦
¦ Free ¦ ¦ Instance ¦
L------- +----------------------------------------+
¦ Init GetChildren ¦
¦ Load GetClassName ¦
¦ Done GetClient ¦
¦ AddChild GetId ¦
¦ At GetSiblingPtr ¦
¦ Canclose GetWindowClass ¦
¦ ChildWithId IndexOf ¦
¦ CloseWindow IsFlagSet ¦
¦ CMExit Next ¦
¦ Create Previous ¦
¦ CreateChildren PutChildPtr ¦
¦ CreateMemoryDC PutChildren ¦
¦ DefChildProc PutSiblingPtr ¦
¦ DefCommandProc Register ¦
¦ DefNotificationProc RemoveChild ¦
¦ DefWndProc SetFlags ¦
¦ Destroy SetupWindow ¦
¦ Disable Show ¦
¦ DisableAutoCreate Store ¦
¦ DisableTransfer Transfer ¦
¦ DispatchScroll TransferData ¦
¦ Enable WMActivate ¦
¦ EnableAutoCreate WMClose ¦
¦ EnableKBHandler WMCommand ¦
¦ EnableTransfer WMDestroy ¦
¦ FirstThat WMNScroll ¦
¦ Focus WMNCDestroy ¦
¦ ForEach WMNQueryEndSession ¦
¦ GetChildPtr WMVScroll ¦
L-----------------------------------------

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

Поля
-----------------------------------------------------------------

ChildList (только чтение)

B.Pascal 7 & Objects/OW - 589 -


ChildList: PWindowsObject;

ChildList - это связанный список всех объектов дочерних окон
интерфейсного объекта, таких как всплывающие окна, диалоговые
блоки и управляющие элементы. ChildList всегда указывает на пос-
ледний добавленный объект.

Flags (чтение/запись)

Flags: Byte;

Flags - это байт данных, биты которого используются для за-
писи следующих атрибутов окна: обработки клавиатуры, автоматичес-
кого создания, передачи, статуса MDI и создания ресурса. Flags
содержит одну или более констант wb_ (которые описываются в дан-
ной главе).

См. также: TWindowsObject.SetFlags,
TWindowsObject.ISFlagSet.

HWindow (только чтение)

HWindow:; HWnd;

HWindow содержит описатель связанного с интерфейсным объек-
том интерфейсного элемента. Если HWindow содержит 0, то значение
является недопустимым описателем. HWindow устанавливается в опи-
сатель связанного интерфейсного элемента при его создании
(Create) и обнуляется при уничтожении интерфейсного элемента
(WMNCDestroy).

Parent (только чтение)

Parent: TPWindowsObject;

PWindowsObject указывает на интерфейсный объект, который
служит порождающим окном для данного интерфейсного объекта. Нап-
ример, выводимое в оконном объекте поле Parent объекта управляю-
щего элемента будет указывать на своего предка - оконный объект.

Status (чтение/запись)

Status: Integer;

Status используется, чтобы сообщить об ошибке в инициализа-
ции интерфейсного объекта. Ненулевое значение Status указывается,
что инициализация объекта не выполнена успешно, отрицательное
свидетельствует о неудаче. Производные от TWindowsObject объекты,
включая TWindow и TDialog, проверяют Status перед созданием соот-
ветствующих элементов. Используйте Status в коде наследующих объ-
ектных типов, чтобы отметить ошибку инициализации.


B.Pascal 7 & Objects/OW - 590 -

Возможные значения ошибки, определенные в TWindowsObject,
включают в себя em_InvalidWindow (недопустимое окно),
em_InvalidClient (недопустимый пользователь), em_InvalidChild
(недопустимое порожденное окно) и em_InvalidMainWindow (недопус-
тимое основное окно).

TransferBuffer (чтение/запись)

TransferBuffer: Pointer;

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

Методы
-----------------------------------------------------------------

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

Init (часто переопределяется)
-----------------------------------------------------------------

constructor Init(AParent: PWindowsObject);

Строит и инициализирует интерфейсный объект. Конструктор
наследующих типов должен вызывать TWindowsObject.Init. Вызывает
EnableAutoCreate, так что дочерние окна будут по умолчанию созда-
ваться и выводиться наряду с их порождающими окнами. Кроме того,
добавляет к списку дочерних окон объекта порождающего окна интер-
фейсный объект.

См. также: TWindowsObject.EnableAutoCreate,
TWindowsObject.AddChild.

Load
-----------------------------------------------------------------

constructor Load(var S: TStream);

Строит и загружает интерфейсный объект из потока S, считывая
Status, другие атрибуты и размер ChildList, а затем загружая
каждое дочернее окно.

Done (часто переопределяется)
-----------------------------------------------------------------

destructor Done; virtual;

Уничтожает интерфейсный объект, уничтожая сначала соответс-
твующий интерфейсный элемент (если он имеется), а затем вызывая
наследуемый из TObject деструктор Done. Уничтожает все свои до-
черние окна и удаляет себя из списка дочерних окон своего порож-
дающего окна. Деструкторы всех наследующих типов должны включать

B.Pascal 7 & Objects/OW - 591 -

в себя вызов TWindowsObject.Don.

AddChild
-----------------------------------------------------------------

procedure AddChild(AChild: PWindowsObject);

Добавляет Achild с списку дочерних окон.

At
-----------------------------------------------------------------

function At(I: Integer): PWindowsObject;

Возвращает указатель на I-ое дочернее окно в списке дочерних
окон объекта. Список дочерних окон циклический, так что если I
больше числа дочерних окон, то At выполняет переход к началу
списка.

CanClose (иногда переопределяется)
-----------------------------------------------------------------

function CanClose: Boolean; virtual

Для каждого дочернего окна вызывает метод CanClose и возвра-
щает False, если возвращает False какое-либо дочернее окно, ука-
зывая, что закрыть интерфейсный элемент нельзя (не OK). Если ме-
тоды CanClose всех дочерних окон возвращают True, то CanClose
также возвращает True.

ChildWithID (никогда не переопределяется)
-----------------------------------------------------------------

ChildWithid(Id: Integer): PWindowsObject; virtual;

Возвpащает указатель на окно с пеpеданным идентификатоpом в
списке дочеpних окон. Если дочеpнего окна с указанным идентитфи-
катором Id нет, ChildWithid возвpащает значение nil. Если Id рав-
но -1, то ChildWithID возвращает первый неуправляющий объект в
списке дочерних окон.

CloseWindow
-----------------------------------------------------------------

procedure CloseWindow;

Чтобы увидеть, готово ли окно к закрытию, вызывает CanClose.
Если метод CanClose возвращает значение True, CloseWindow уничто-
жает объект и уничтожает соответствующий оконный элемент.

См. также: TWindowObject.CanClose.


B.Pascal 7 & Objects/OW - 592 -

CMExit
-----------------------------------------------------------------
procedure CMExit(var Msg: TMessage); virtual
cm_First + cm_Exit;

Если CanCLose возвращает True, отвечает на командное сообще-
ние cm_Exit, прекращая выполнение приложения. Сообщение cm_Exit
обычно посылается основному окну приложения.

Create (никогда не переопределяется)
-----------------------------------------------------------------
function Create: Boolean; virtual;

Создает соответствующий экранный элемент интерфейсного объ-
екта. Это абстрактный метод, переопределяемый в наследующих ти-
пах.

CreateChildren
-----------------------------------------------------------------

function CreateChildren: Boolean;

Вызывает Create для всех дочерних окон. CreateWindow вызыва-
ется SetupWindow, так что вам не нужно обычно вызывать этот метод
непосредственно. CreateChildren требуется вызывать только после
GetChildren для получения визуальных элементов для дочерних окон-
ных объектов, загружаемых из потока.

См. также: TWindowsObject.GetChildren.

CreateDCMemory

function CreateDCMemory(var Msg: TMessage); virtual;

Создает контекст устройства памяти (DC), совместимый с кон-
текстом дисплея окна. Значения DC необходимы для поразрядного
отображения.

DefChildProc (иногда переопределяется)
-----------------------------------------------------------------
procedure DefChildProc(var Msg: TMessage); virtual

Выполняет стандаpтную обpаботку для поступающего сообщения,
базиpующегося на идентификатоpе дочеpнего окна, устанавливая по-
ле Result в Msg в 0 (это указывает, что сообщение обработано не
было).

DefCommandProc (иногда переопределяется)
-----------------------------------------------------------------
procedure DefCommandProc(var Msg: TMessage); virtual;

B.Pascal 7 & Objects/OW - 593 -


Выполняет стандаpтную обpаботку для поступающего сообщения,
базиpующегося на команде, устанавливая поле Result в Msg в 0 (это
указывает, что сообщение обработано не было).

DefNotificationProc (иногда переопределяется)
-----------------------------------------------------------------

procedure DefNotificationProc(var Msg: TMessage); virtual;

Выполняет стандаpтную обpаботку для поступающего уведомляю-
щего сообщения, устанавливая поле Result в Msg в 0 (это указыва-
ет, что сообщение обработано не было).

DefWndProc
-----------------------------------------------------------------

procedure DefWndProc(var Msg: TMessage); virtual;

Эта используемая по умолчанию оконная процедура не выполняет
никаких операций и обычно переопределяется. Она полагает, что по-
ле Result в Msg остается нулевым (это указывает, что сообщение не
обработано). TWindow переопределяет DefWndProc для вызова предус-
мотренных в Windows стандартной реакции на сообщения Windows.

См. также: TWindow.DefWndProc.

Destroy (никогда не переопределяется)
-----------------------------------------------------------------

procedure Destroy; virtual;

Вызывает уничтожение связанного элемента интеpфейсного объ-
екта, удаляя его с экрана, вызывая получение оконным объектом со-
общения wm_Destroy. Destroy вызывает также для любого созданного
дочернего окна метод EnableCreate. Это обеспечивает, что при пов-
торном создании объект будет выглядеть как в момент уничтожения.

См. также: TWindowsObject.WMDestroy,
TWindowsObject.EnableAutoCreate.

Disable
-----------------------------------------------------------------

procedure Disable;

Вызывая DisableWindow, запрещает связанный с интерфейсным
объектом экранный элемент. Запрещенный экранный элемент обычно
выводится серым и не реагирует в Windows на ввод с клавиатуры или
от "мыши". Все экранные элементы по умолчанию разрешены, но могут
запрещаться вызовом Disable.

См. также: TWindowsObject.Enable.

B.Pascal 7 & Objects/OW - 594 -

DisableAutoCreate
-----------------------------------------------------------------

procedure DisableAutoCreate;

Запpещает возможность, котоpая позволяет интеpфейсному объ-
екту, как дочеpнему окну, создаваться и отобpажаться наряду с его
порождающим окном. Вызывайте DisableAutoCreate для всплывающих
окон и управляющих элементов в том случае, если вы хотите, чтобы
они создавались и отобpажались позднее, чем их порождающие окна.

См. также: TWindowsObject.EnableAutoCreate.

DisableTransfer
-----------------------------------------------------------------

procedure DisableTransfer;

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

DispatchScroll (никогда не переопределяется)
-----------------------------------------------------------------

procedure DispatchScroll(var Msg: TMessage); virtual;

Вызывается WMHScroll и WMVScroll для диспетчеризации сообще-
ний прокрутки окон соответствующих объектов.

См. также: TWindowsObejct.WMHScroll,
TWindowsObject.WMVScroll.

Enable
-----------------------------------------------------------------

procedure Enable;

Вызывая EnableWindow, разрешает связанный с интерфейсным
объектом экранный элемент. Реагировать на ввод с клавиатуры или
от "мыши" может только разрешенный экранный элемент (и, следова-
тельно, объект). Все экранные элементы по умолчанию разрешены,
поэтому вам нужно вызывать Enable только после запрещения элемен-
та.

См. также: TWindowsObject.Disable.

EnableAutoCreate
-----------------------------------------------------------------

procedure EnableAutoCreate;


B.Pascal 7 & Objects/OW - 595 -

Обеспечивает, чтобы интеpфейсный класс, как дочеpнее окно,
создавался и отобpажался наряду с его порождающим окном. Эта воз-
можность pазpешена, по умолчанию, для окон и управляющих элемен-
тов, но запpещена для диалоговых блоков. Вызывайте
EnableAutoCreate в том случае, если вы хотите, чтобы диалоговый
блок создавался и отобpажался вместе с его порождающими окнами.

См. также: TWindowsObject.DisableAutoCreate.

EnableKBHandler
-----------------------------------------------------------------

procedure EnableKBHandler;

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

См. также: TWindowsObject.WMActive,
TApplication.SetKBHandler.

EnableTransfer
-----------------------------------------------------------------

procedure EnableTransfer;

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

FirstThat
-----------------------------------------------------------------

function FirstThat(Test: Pointer): PWindowsObject;

Пpоходит итеративно по списку дочеpних окон и вызывает бу-
левскую функцию Test, пеpедавая поочередно в качестве аpгумента
каждое дочеpнее окно списка. Если при вызове Test возвращается
значение True, итерация останавливается, и FirstThat возвращает
указатель объект дочернего окна, который передавался в Test. В
противном случае FirstThat возвращает значение nil.

Напpимеp, вы можете написать метод GetFirstChecked, котоpый
использует FirstThat для получения указателя на первую кнопку с
независимой фиксацией в выбранном состоянии:

function MyWindow.GetFirstChecked: PWindowsObject;

function IsThisOneChecked(ABox: PWindowsObject); Boolean;
far;
begin

B.Pascal 7 & Objects/OW - 596 -

IsThisOneChecked := ABox^.GetCheck <> 0;
end;

begin
GetFirstChecked := FirstThat(@IsThisOneChecked);
end;

Focus
-----------------------------------------------------------------

procedure Focus;

Сообщает Windows о передаче фокуса ввода связанному с объек-
том экранному элементу.

ForEach
-----------------------------------------------------------------

procedure ForEach(Action: Pointer);

Пpоходит итеративно по списку дочеpних окон и для каждого
дочеpнего окна вызывает процедуру, указываемую Action, и пеpедает
ей поочередно в качестве аpгумента объект дочеpнего окна.

В следующем примере CheckAllBoxes вызывает ForEach, анализи-
руя все блоки проверки в списке порожденных окон:

function MyWindow.CheckAllBoxes;

procedure CheckTheBox(ABox: PWindowsObject); far;
begin
PCheckBox(ABox)^.Check;
end;

begin
ForEach(@CheckTheBox);
end;

GetChildPtr
-----------------------------------------------------------------

procedure GetChildPtr(var S: TStream; var P);

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

См. также: TWindowsObject.GetSiblingPtr,
TWindowsObject.PutSiblingPtr, TWindowsObject.PutChildPtr.

GetChildren
-----------------------------------------------------------------


B.Pascal 7 & Objects/OW - 597 -

procedure GetChildren(var S: TStream);

Считывает дочерние окна из указанного потока и помещает их в
список дочерних окон. GetChildren предполагает, что список дочер-
них окон ChildList первоначально пуст: указатели на дочерние ок-
на, добавленные перед вызовом GetChildren, будут потеряны.

См. также: TWindowsObject.CreateChildren,
TWindowsObject.PutChildren.

GetClassName (иногда переопределяется)
-----------------------------------------------------------------

function GetClassName: PChar; virtual

Возвращает используемое по умолчанию имя класса окна -
'TurboWindow'.

GetClient (никогда не переопределяется)
-----------------------------------------------------------------

function GetClient: PMDIClient; virtual;

Возвращает NULL для всех интеpфейсных объектов, не относя-
щихся к MDI, котоpые не имеют окон пользователя MDI. TMDIWindows
переопределяет этот метод для обеспечения своих окон клиента MDI.

GetId (переопределяется редко)
-----------------------------------------------------------------

function GetId: Integer; virtual;

В общем случае возвращает идентификатор окна. По умолчанию
GetId просто возвращает -1. GetId переопределяется потомками
TControl для возврата идентификатора управляющего элемента объек-
та. Все другие интерфейсные объекты не имеют идентификаторов уп-
равляющих элементов.

См. также: TControl.GetId.

GetSiblingPtr
-----------------------------------------------------------------

procedure GetSiblingPtr(var S: TStream; var P);

Загpужает указатель P "бpатского" окна из указанного потока.
"Бpатское" окно - это окно с тем же порождающим окном, что и дан-
ное, напpимеp, окно TGroupBox объекта TCheckBox является "бpатс-
ким" для TCheckBox. GetSiblingPtr должен использоваться только
внутри конструкторов Load для чтения значений указателей, которые
были записаны в PutSibling из метода Store. Значение, загpуженное
в P, не становится допустимым до тех поp, пока pодитель окна не
закончит свою опеpацию Load; таким образом, разыменование указа-

B.Pascal 7 & Objects/OW - 598 -

теля братского окна в конструкторе Load не дает корректного ре-
зультата.

См. также: TWindowsObject.PutSiblingPtr,
TWindowsObject.GetChildPtr, TWindowsObject.PutChildPtr.

GetWindowClass (иногда переопределяется)
-----------------------------------------------------------------

procedure GetWindowClass(var AWndClass: TWndClass); virtual;

Используется для подстановки в наследующих типах для опреде-
ления записи класса окна и возврата ее в AWndClass. Данная проце-
дура GetWndClass не выполняет никаких действий.

IndexOf
-----------------------------------------------------------------

function IndexOf(P: PWindowsObject): Integer;

Возвращает порядковую позицию P в списке дочерних окон объ-
екта. Первое дочернее окно в списке имеет номер 1. Если P отсутс-
твует в списке дочерних окон, возвращает 0.

IsFlagSet
-----------------------------------------------------------------

function IsFlagSet(Mask: Byte); Boolean;

Возвращает состояние битового флага, маска которого указыва-
ется в Mask. Если битовый флаг установлен, возвращает значение
True, в противном случае возвращается значение False.

См. также: TWindowObject.SetFlag.

Next
-----------------------------------------------------------------

function Next: PWindowsObject;

Возвpащает указатель на следующую окно в списке дочеpних
окон порождающего окна.

См. также: TWindowsObject.Previous.

Previous
-----------------------------------------------------------------

function Previous: PTWindowsObject;

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


B.Pascal 7 & Objects/OW - 599 -

См. также: TWindowsObject.Next.

PutChildPtr
-----------------------------------------------------------------

procedure PutChildPtr(var S: TStream;
var P: PTWindowsObject);

Записывает дочернее окно в указанный поток S. PutChildPtr
следует вызывать только в методе Store для записи значений указа-
телей, которые позднее можно считать с помощью GetChildPtr в
конструкторе Load.

См. также: TWindowsObject.GetSiblingPtr,
TWindowsObject.GetSiblingPtr, TWindowsObject.PutChildPtr.

PutChildren
-----------------------------------------------------------------

PutChildren(var S: TStream);

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

См. также: TWindowsObject.GetChildren.

PutSiblingPtr
-----------------------------------------------------------------

PutSiblingPtr(var S: TStream; P: PWindowsObject);

Записывает указатель P "бpатского" окна в указанный поток.
"Бpатское" окно - это окно с тем же порождающим окном, что и дан-
ное. PutSiblingPtr должна использоваться только в методе Store
для записи значений указателей, которые позднее можно считать с
помощью GetSiblingPtr в конструкторе Load.

См. также: TWindowsObject.GetSiblingPtr,
TWindowsObject.GetChildPtr, TWindowsObject.PutChildPtr.

Register (никогда не переопределяется)
-----------------------------------------------------------------

function Register: Boolean; virtual;

Регистрирует оконный класс, определенный в методе объкта
GetWindowClass и именует его в методе GetClassName (если он еще
не зарегистрирован). Register возвращает значение True, если
класс успешно зарегистрирован.


B.Pascal 7 & Objects/OW - 600 -

См. также: TWindowsObject.GetClassName,
TWindowsObject.GetWindowClass.

RemoveChild
-----------------------------------------------------------------

procedure RemoveChild(AChild: PWindowsObject); protected

Удаляет из списка дочерних окон объекта заданное окно
AChild.

SetFlags
-----------------------------------------------------------------

procedure SetFlags(Mask: Byte; OnOff: Boolean);

Включает или выключает битовый флаг в зависимости от значе-
ния OnOff. Если OnOff имеет значение True, биты в Mask устанавли-
ваются. В пpотивном случае, биты сбpасываются. Mask может быть
любой константой wb_ или их комбинацией.

См. также: TWindowsObject.IsFlagSet.

SetupWindow (часто переопределяется)
-----------------------------------------------------------------

procedure SetupWindow; virtual;

Выполняет инициализацию вновь созданного интеpфейсного эле-
мента. Путем итерации списка дочерних окон пытается создать свя-
занный интерфейсный элемент для каждого объекта дочернего окна,
для которого разрешено автоматическое создание. (По умолчанию ав-
томатическое создание разрешается для окон и управляющих элемен-
тов и запрещается для диалогов.) Если дочернее окно создать нель-
зя, то Status устанавливается в значение em_InvalidChild. Затем
SetupWindow для копирования данных в новые дочерние окна вызывает
TransferData. Для выполнения специальной инициализации в произ-
водных объектах этот метод можно переопределить.

Show (никогда не переопределяется)
-----------------------------------------------------------------

procedure Show(ShowCmd: Integer); virtual;

Show отобpажает интеpфейсный элемент на экpане таким
обpазом, как указано значением, пеpеданным в ShowCmd. ShowCmd мо-
жет содеpжать следующие значения:

Значения параметров метода Show Таблица 21.28
-------------------------T----------------------------------¬
¦ Значение ¦ Описание ¦
+------------------------+----------------------------------+
¦ sw_Hide ¦ Скрыто ¦

B.Pascal 7 & Objects/OW - 601 -

¦ sw_Show ¦ В текущем положении и с текущим ¦
¦ ¦ pазмеpом окна ¦
¦ sw_ShowMaximized ¦ Максимизиpовано и активно ¦
¦ sw_ShowMinimized ¦ Минимизиpовано и активно ¦
¦ sw_ShowNornal ¦ Восстановлено и активно ¦
L------------------------+-----------------------------------

Store
-----------------------------------------------------------------

procedure Store(var S: TStream);

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

Transfer (иногда переопределяется)
-----------------------------------------------------------------

procedure Transfer(DataPtr: Pointer; TransferFlag: Word):
Word; virtual;

Возвращает 0. Transfer переопределяется в потомках TControl
для передачи их данных о состоянии в буфер передачи и из него.
Возвращаемое из Transfer значение представляет собой число пере-
данных байт.

TransferData (иногда переопределяется)
-----------------------------------------------------------------

procedure TransferData(Direction: Word); virtual;

Если установкой TransferBuffer в запись передачи разрешен
механизм передачи, передает данные и в буфер или из него и участ-
вующих в pаботе дочеpних окон интеpфейсного объекта. Для каждого
участвующего дочернего окна TransferData вызывает метод Transfer,
передавая указатель на пересылаемые данные, а также направление,
заданное в параметре Direction (tf_SetData или tf_GetData).

См. также: TWindowsObject.EnableTransfer,
TWindowsObject.DisableTransfer, TWindowsObject.SetupWundow.

WMActivate (иногда переопределяется)
-----------------------------------------------------------------

procedure WMActivate(var Msg: TMessage); virtual
wm_Fist + wm_Activate;

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


B.Pascal 7 & Objects/OW - 602 -

См. также: TApplication.SetKeyBoardHandler.

WMClose (иногда переопределяется)
-----------------------------------------------------------------

WMClose(var Msg: TMessage); virtual wm_First + wm_Close;

Отвечает на запpос о закpытии окна вызовом метода
CloseWindow данного объекта или метода CanClose объекта приложе-
ния в случае, если данный объект является основным окном приложе-
ния. Если CanClose возвращает True, данный интерфейсный элемент
уничтожается вызовом Destroy.

См. также: TWindowsObject.Destroy.

WMCommand (переопределяется редко)
-----------------------------------------------------------------

procedure WMCommand(var Msg: TMessage); virtual
wm_First + wm_Command;

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

WMDestroy (переопределяется редко)
-----------------------------------------------------------------

procedure WMDestroy(var Msg: TMessage); virtual
wm_First + wm_Destroy;

Отвечает на приходящее сообщение wm_Destroy. Если данный
объект - это основное окно, отвечает на это уничтожение интер-
фейсных элементов и посылает для завершения прикладной программы
сообщение выхода wm_Quit (информируя, таким образом, Windows).
Если объект не является основным окном приложения, то вызывается
поведение окна, используемое по умолчанию.

См. также: TWindowsObject.DispatchScroll.

WMHScroll (переопределяется редко)
-----------------------------------------------------------------

procedure WMHScroll(var Msg: TMessage); virtual
wm_First + wm_Destroy;

Перехватывает поступающие сообщения горизонтальной прокрут-
ки, вызывая DispatchScroll.

См. также: TWindowsObject.DispatchScroll.

WMNCDestroy (никогда не переопределяется)
-----------------------------------------------------------------

B.Pascal 7 & Objects/OW - 603 -


procedure WMNCDestroy(var Msg: TMessage); virtual
wm_First + wm_QueryEndSession;

Отвечает на последнее сообщение интерфейсного элемента, по-
лученное перед его уничтожением, установкой HWindow в 0.

WMQueryEndSession
-----------------------------------------------------------------

procedure WMQueryEndSession(var Msg: TMessage); virtual
wm_First + wmQueryEndSession;

Если окно является основным окном приложения, то отвечает на
сообщение wm_QueryEndSession вызовом Application^.CanClose и, ес-
ли этот метод возвращает значение True, устанавливает Msg.Result
в 1. В противном случае Msg.Result устанавливается в 0.

WMVScroll (переопределяется редко)
-----------------------------------------------------------------

procedure WMVScroll(var Msg: TMessage); virtual
wm_First + wm_VScroll;

Перехватывает сообщения вертикального окна полосы прокрутки
и вызывает DispatchScroll.

См. также: TWindowsObject.DispatchScroll.

------------------------------------------------------------------
Тип TWordArray модуль Objects
-----------------------------------------------------------------

Описание: TWordArray = array[0..1683] of Word;

Назначение: Тип массива с элементами размером в слово для
общего использования.

B.Pascal 7 & Objects/OW - 604 -

Константы voXXXX модуль Validate
-----------------------------------------------------------------

Назначение: Константы, начинающиеся с vo, представляют в
слове Options с побитовым отображением в объектах проверки допус-
тимости.

Значения: Биты Ooptions объекта проверки допустимости опре-
делены следующим образом:

----T---T---T---T---T---T---T---T---T---T---T---T---T---T---T---¬
¦msb¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦lsb¦
L---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+----
L-------------T---------------- L---+---+---+---+---¬ ¦ ¦
не определены ¦ ¦ ¦
voReserved = $00FC ¦ ¦
¦ ¦
voTransfer = $0002 ¦
¦
voFill = $0001

Рис. 21.1 Флаги параметров объекта проверки допустимости
(msb - старший бит, lsb - младший бит).

Флаги параметров объекта проверки допустимости Таблица 21.29
------------------T--------------T------------------------------¬
¦ Константа ¦ Значение ¦ Смысл ¦
+-----------------+--------------+------------------------------+
¦ voFill ¦ $0001 ¦ Используется в средствах про-¦
¦ ¦ ¦ верки допустимости по трафа-¦
¦ ¦ ¦ рету для указания заполнения¦
¦ ¦ ¦ набираемыми пользователем ли-¦
¦ ¦ ¦ теральными символами. ¦
+-----------------+--------------+------------------------------+
¦ voTransfer ¦ $0002 ¦ Объект проверки допустимости¦
¦ ¦ ¦ обрабатывает передачу данных¦
¦ ¦ ¦ для строки ввода. В данное¦
¦ ¦ ¦ время используется средством¦
¦ ¦ ¦ проверки допустимости по диа-¦
¦ ¦ ¦ пазону. ¦
+-----------------+--------------+------------------------------+
¦ voReserved ¦ $00FC ¦ Биты в данной маске, зарезер-¦
¦ ¦ ¦ вированные Borland. ¦
L-----------------+--------------+-------------------------------

B.Pascal 7 & Objects/OW - 605 -

Константы vsXXXX модуль Validate
-----------------------------------------------------------------

Назначение: Объекты строки ввода используют vsOK для провер-
ки и правильного построения соответствующих объектов проверки до-
пустимости. При вызове с командным параметром или cmValid метод
Valid объекта строки ввода проверяет поле Status своего объекта
проверки допустимости. Если Status равно vsOK, то метод Valid
строки ввода возвращает значение True, указывая, что объект про-
верки допустимости можно использовать.

Единственное значение, определенное для поля Status и отлич-
ное от vsOK - это vsSyntax, используемое в TPXPictureValidator
для указания, что невозможно интерпретировать переданную строку
трафарета. Если вы создаете собственные объекты проверки допусти-
мости, то можете определить коды ошибок и возвратить их в поле
Status.

Значения: Модуль Validate определяет две константы, исполь-
зуемые в объектах проверки допустимости для сообщения о своем
состоянии.

Константы состояния объекта проверки допустимости Таблица 21.30
--------------------T-------------T-----------------------------¬
¦ Константа ¦ Значение ¦ Смысл ¦
+-------------------+-------------+-----------------------------+
¦ vsOK ¦ 0 ¦ Объект проверки допустимости¦
¦ ¦ ¦ построен правильно. ¦
+-------------------+-------------+-----------------------------+
¦ vsSyntax ¦ 1 ¦ Ошибка синтаксиса в трафаре-¦
¦ ¦ ¦ те шаблона объекта проверки.¦
L-------------------+-------------+------------------------------

См. также: TValidator.Status.

B.Pascal 7 & Objects/OW - 606 -

Константы wb_XXXX модуль OWindows
-----------------------------------------------------------------

Назначение Поле Glags в TWindowsObject - это поле с побито-
вым отображением. К битам можно обращаться с помощью констант,
начинающихся с wb_.

Значения: Определены следующие значения констант:

Константы поля с
побитовым отображением TWindowsObject Таблица 21.31
-----------------------T---------T------------------------------¬
¦ Константа ¦Значение ¦ Смысл в случае установки ¦
+----------------------+---------+------------------------------+
¦ wb_KeyboardHandler ¦ $01 ¦ Окно обрабатывает события¦
¦ ¦ ¦ клавиш как диалог. ¦
+----------------------+---------+------------------------------+
¦ wb_FromResource ¦ $02 ¦ Диалог был загружен из ресур-¦
¦ ¦ ¦ са. ¦
+----------------------+---------+------------------------------+
¦ wb_AutoCreate ¦ $04 ¦ Окно создается при создании¦
¦ ¦ ¦ его порождающего окна. ¦
+----------------------+---------+------------------------------+
¦ wb_MDIChild ¦ $08 ¦ Окно является дочерним окном¦
¦ ¦ ¦ MDI. ¦
+----------------------+---------+------------------------------+
¦ wb_Transfer ¦ $10 ¦ Окно участвует в механизме¦
¦ ¦ ¦ передачи Transfer. По умолча-¦
¦ ¦ ¦ нию этот бит устанавливается¦
¦ ¦ ¦ InitResource и очищается¦
¦ ¦ ¦ Init. ¦
L----------------------+---------+-------------------------------

См. также: TWindowsObject.Flag.

Константы wm_XXXX модуль OWindows
-----------------------------------------------------------------

Назначение: ObjectWindows определяет несколько констант,
связанных со стандартными сообщениями Windows и определяющими за-
резервированные для Windows диапазоны сообщений.

Значения: Определены следующие константы:

Константы сообщений Windows Таблица 21.23
----------------T-----------T--------------------------¬
¦ Константа ¦ Значение ¦ Смысл ¦
+---------------+-----------+--------------------------+
¦ wm_First ¦ $0000 ¦ Начало сообщений Windows.¦
¦ wm_Count ¦ $8000 ¦ Число сообщений Windows. ¦
L---------------+-----------+---------------------------

B.Pascal 7 & Objects/OW - 607 -


------------------------------------------------------------------
Тип WordRec модуль Objects
-----------------------------------------------------------------

Описание:

WordRec = record
Lo, Hi: Byte;
end;

Назначение: Рабочая запись, позволяющая обращаться к старшим
(Hi) и младшим (Lo) байтам слова.

См. также: LongRec.



B.Pascal 7 & Objects/OW - 608 -

Стили окна ws_XXXX модуль WinTypes
-----------------------------------------------------------------

Вы можете использовать эти константы для установки атрибутов
создания интерфейсных объектов путем комбинирования их в поле
Attrr.Style объекта перед созданием объектом его экранного эле-
мента. Вы можете также использовать их для задания стилей окна
при создании окон, диалоговых блоков и управляющих элементов с
CreateWindow или CreateWindowEx.

Стили окна Таблица 21.33
-------------------------T--------------------------------------¬
¦ Константа ¦ Смысл ¦
+------------------------+--------------------------------------+
¦ ws_Borded ¦ Окно имеет рамку. Не допускается с¦
¦ ¦ ws_DlgFrame. ¦
+------------------------+--------------------------------------+
¦ ws_Caption ¦ Окно имеет строку заголовка и рам-¦
¦ ¦ у. ws_Caption и ws_DlgFrame не могут¦
¦ ¦ использоваться вместе. ws_Caption¦
¦ ¦ предполагает включение ws_Border. ¦
+------------------------+--------------------------------------+
¦ ws_Child ¦ Окно является дочерним окном.¦
¦ ¦ ws_Child и ws_Popup не могут исполь-¦
¦ ¦ зоваться вместе. ¦
+------------------------+--------------------------------------+
¦ ws_ChildWindow ¦ То же, что ws_Child. ¦
+------------------------+--------------------------------------+
¦ ws_ClipChildren ¦ Окно не включает области, перекрытые¦
¦ ¦ при отображении дочерними окнами. ¦
+------------------------+--------------------------------------+
¦ ws_ClipSibling ¦ Окно при отображения обрезает все¦
¦ ¦ "братские" окна. Это означает, что¦
¦ ¦ отображаемые области в каждой области¦
¦ ¦ клиента дочерних окон одного порожда-¦
¦ ¦ ющего окна не будут перекрываться. ¦
+------------------------+--------------------------------------+
¦ ws_Disables ¦ Окно первоначально запрещено. ¦
+------------------------+--------------------------------------+
¦ ws_DlgFrame ¦ Окно имеет двойную рамку и не имеет¦
¦ ¦ заголовка. Не допускается с¦
¦ ¦ ws_Borded. ¦
+------------------------+--------------------------------------+
¦ ws_Group ¦ Окно - это управляющий элемент, ко-¦
¦ ¦ торый является первым элементом в¦
¦ ¦ группе, и пользователь может получать¦
¦ ¦ к нему доступ с помощью клавиш стре-¦
¦ ¦ лок. Каждый последующий управляющий¦
¦ ¦ элемент, определенный без ed_Group,¦
¦ ¦ принадлежит к группе, начинающейся с¦
¦ ¦ последнего управляющего элемента с¦
¦ ¦ ws_Group. ¦
+------------------------+--------------------------------------+

B.Pascal 7 & Objects/OW - 609 -

¦ ws_HScroll ¦ Окно имеет горизонтальную полосу¦
¦ ¦ прокрутки. ¦
+------------------------+--------------------------------------+
¦ ws_Iconic ¦ То же, что ws_Mininize. ¦
+------------------------+--------------------------------------+
¦ ws_Maximize ¦ Окно занимает весь экран (максимизи-¦
¦ ¦ ровано). ¦
+------------------------+--------------------------------------+
¦ ws_MaximizeBox ¦ Окно имеет блок максимизации. ¦
+------------------------+--------------------------------------+
¦ ws_Overlapped ¦ Окно является перекрывающимся окном.¦
¦ ¦ Перекрывающееся окно имеет заголовок¦
¦ ¦ и рамку. ¦
+------------------------+--------------------------------------+
¦ ws_OverlappedWindow ¦ То же, что комбинация ws_Overlapped,¦
¦ ¦ ws_Caption, ws_SysMenu,¦
¦ ¦ ws_ThickFrame, ws_MinimizeBox и¦
¦ ¦ ws_MaximizeBox. ¦
+------------------------+--------------------------------------+
¦ ws_Popup ¦ Окно является всплывающим окном. ¦
+------------------------+--------------------------------------+
¦ ws_PopupWindow ¦ То же, что комбинация ws_Border,¦
¦ ¦ ws_ws_Popup и ws_SysMenu. Блок управ-¦
¦ ¦ ляющего меню выводится только если¦
¦ ¦ используется также стиль ws_CAption. ¦
+------------------------+--------------------------------------+
¦ ws_SizeBox ¦ То же, что ws_ThickFrame. ¦
+------------------------+--------------------------------------+
¦ ws_SysMenu ¦ Окно содержит в строке заголовка блок¦
¦ ¦ управляющего меню. Применяется только¦
¦ ¦ к окнам со строкой заголовка. ¦
+------------------------+--------------------------------------+
¦ ws_TabStop ¦ Окно представляет собой управляющий¦
¦ ¦ элемент диалогового блока в списке¦
¦ ¦ управляющих элементов, по которым¦
¦ ¦ пользователь может циклически переме-¦
¦ ¦ щаться с помощью клавиши Tab. ¦
+------------------------+--------------------------------------+
¦ ws_ThickFrame ¦ Окно имеет жирную рамку, которую¦
¦ ¦ пользователь может перемещать (букси-¦
¦ ¦ ровать) для изменения размера окна. ¦
+------------------------+--------------------------------------+
¦ ws_Tiled ¦ То же, что ws_Overlapped. ¦
+------------------------+--------------------------------------+
¦ ws_TiledWindow ¦ То же, что ws_OverlappedWindow. ¦
+------------------------+--------------------------------------+
¦ ws_Visible ¦ Окно первоначально является видимым. ¦
+------------------------+--------------------------------------+
¦ ws_VScroll ¦ Окно имеет вертикальную полосу про-¦
¦ ¦ рутки. ¦
L------------------------+---------------------------------------

См. также: TWindow.Attr.



Назад


Новые поступления

Украинский Зеленый Портал Рефератик создан с целью поуляризации украинской культуры и облегчения поиска учебных материалов для украинских школьников, а также студентов и аспирантов украинских ВУЗов. Все материалы, опубликованные на сайте взяты из открытых источников. Однако, следует помнить, что тексты, опубликованных работ в первую очередь принадлежат их авторам. Используя материалы, размещенные на сайте, пожалуйста, давайте ссылку на название публикации и ее автора.

281311062 © il.lusion,2007г.
Карта сайта