Ниже обсуждаются реквизиты и объекты окон реквизита. Функционально реквизиты аналогичны управляющим элементам - они используются для получения информации от пользователя или ее вывода. Однако реквизиты реализуются по-другому. В отличие от большинства других интерфейсных элементов, реквизиты не являются окнами: они не имеют описателей окна, не получают событий и сообщений и не базируются на TWindow. Реквизиты ограничиваются окном реквизита, которое управляет их представлением, обрабатывает все сообщения и т.д. Реквизит получает команды и указания от этого окна.
Ниже обсуждаются классы реквизитов.
Все реквизиты основываются на классе TGadget. Класс TGadget содержит базовые функции, необходимые для всех реквизитов, включая управление обрамлением реквизита и его стилем, установку размера реквизита, его разрешение и запрещение и т.д.
В параметрах конструктора реквизита указывает номер его идентификатора (произвольное значение) и стиль (None, Plain, Raised, Recessed или Embossed). Деструктор TGadget описывается как virtual и удаляет реквизит из окна реквизита.
Для получения идентификатора вы можете идентифицировать реквизит с помощью функции GetId, которая не имеет параметров и возвращает целочисленный идентификатор. Идентификатор реквизита имеет несколько областей применения:
Вы можете проверять и изменять ширину полей, обрамления и стиль обрамления реквизита. Для этого используются функции SetBorder, GetBorders, SetMargins, GetMargins, SetBorderStyle, GetBorderStyle.
Границей является внешнее обрамление реквизита. Используемая совместно с функциями SetBorders и GetBorders структура TBorder имеет 4 элемента данных (Left, Right, Top и Bottom), содержащие ширину соответствующей границы реквизита.
Полями называется область между обрамлением реквизита и внутренним прямоугольником реквизита. С функциями SetMargins и GetMargins используется структура TMargins с 4 элементами данных: Top, Bottom, Right и Left.
Ограничивающий прямоугольник реквизита - это область, занимаемая реквизитом. Она содержится в структуре TRect и состоит из относительных координат X и Y верхнего левого и нижнего правого углов реквизита в окне реквизита. Окно реквизита использует ограничивающий прямоугольник реквизита для его размещения. Он имеет также важное значение для определения нажатия кнопки "мыши" на реквизите. Для нахождения и задания ограничивающего прямоугольника реквизита используются функции SetBounds (которая для отслеживания изменения и обновления внутреннего состояния реквизита в производном классе должна переопределяться) и GetBounds.
Функция SetShrinkWrap позволяет автоматически настраивать размер реквизита в зависимости от размеров окна. Это избавляет вас от необходимости вычислять размер ограничивающего прямоугольника реквизита вручную. Автоматическую настройку горизонтального и вертикального размера определяют параметры shrinkWrapWidth и shrinkWrapHeight.
Размером реквизита является размер его ограничивающего прямоугольника. С помощью функции SetSize вы можете настроить размер реквизита, не изменяя его положение. Для получения размера реквизита используется функция GetDesiredSize. В процессе разметки окна реквизитов могут изменять желаемый размер реквизита.
Для улучшения интерфейса с пользователем вы можете реализовать функцию SysColorChange. Окно реквизита вызывает функцию SysColorChange каждого содержащегося в окне реквизита, когда окно получает сообщение WM_SYSCOLORCHANGE. Заданная по умолчанию версия SysColorChange никаких действий не выполняет. Если вы хотите, чтобы на реквизите отражались изменения системных цветов, нужно реализовать эту функцию. При этом убедитесь в том, что вы удаляете и перераспределяете все ресурсы, зависящие от установок системных цветов.
Общедоступные элементы данных TGadget Clip и WideAsPossible указывают, должен ли перед изображением реквизита примеряться отсекающий прямоугольник, и нужно расширять реквизит до заполнения в окне всего доступного пространства.
С помощью функций SetEnabled и GetEnabled вы можете разрешить и запретить реквизит. Запрещенный реквизит не стирается. В производном классе вы можете переопределить это поведение.
Функцию CommandEnable можно переопределить в производном классе для разрешения команд. Заданная по умолчанию версия никаких действий не выполняет.
TGadget предусматривает ряд функций protected, которые вы можете использовать для создания производных классов, а также пару виртуальных функция для инициализации и очистки реквизита Inserted и Remove. Inserted вызывается после включения реквизита в оно реквизитов, a Removed вызывается перед удалением реквизита из окна реквизитов. Заданные по умолчанию версии этих функций никаких действий не выполняют.
Функция PaintBorder рисует границу реквизита. Она реализует стандартные стили границы. Для создания нового стиля нужно переопределить эту функцию. Для использования стандартных стилей нужно также вызывать версию TGadget этой функции.
Функция Paint аналогична функции Paint TWindow. Paint описывается как virtual. Функция PaintGadgets в TGadget при изображении окна реквизита вызывает функцию Paint каждого реквизита. Заданная по умолчанию функция Paint только вызывает функцию PaintBorder. Вам нужно переопределить эту функцию.
При самостоятельном изображении реквизита с помощью функции Paint часто требуется найти область внутри границ и полей реквизита. Эта область называется внутренним прямоугольником. Его можно определить с помощью функции GetInnerRect, которая помещает в передаваемую ей структуру TRect координаты внутреннего прямоугольника.
Как и окно, реквизит можно сделать недопустимым (в этом случае он требуется повторного отображения). Для этого предусмотрены две функции - Invalidate и InvalidateRect, аналогичные соответствующим функциям TWindow. Invalidate работает как соответствующая функция API Windows, но не требуется параметра HWND. Родственной функцией является функция Update, которая пытается обновить реквизит. Она аналогичная функции API Windows UpdateWindow.
Вы можете отслеживать события "мыши", происходящие внутри и вне реквизита. Это делается с помощью псевдообработчиков событий класса TGadget. Эти функции во многом аналогичны стандартным функциям обработки событий ObjectWindows, но имена функций не имеют префикса ev.
Так как реквизит на самом деле не является окном, он не имеет таблиц реакции, как другие классы ObjectWindows. Вся связь реквизита с внешним миром осуществляется через окно реквизитов. Когда в окне реквизитов происходит событие "мыши", окно пытается определить, на какой из реквизитов оно влияет. C этой целью вы можете вызвать функцию PtIn, которая возвращает True, если заданная аргументом точка находится внутри ограничивающего прямоугольника реквизита. Когда "мышь" попадает внутрь ограничивающего прямоугольника реквизита, окно реквизита вызывает функцию MouseEnter, первый аргумент которой содержит ключевую информацию, необходимую для передачи стандартного сообщения ObjectWindows EvMouseMove. Это указывает на нажатие различных виртуальных клавиш.
После того как окно реквизита вызывает функцию реквизита MouseEnter и информирует реквизит, что "мышь" вошла в его область. Реквизит перехватывает перемещения "мыши", вызывая функцию GadgetSetCapture, обеспечивая вызов функции MouseLeave (эта функция вызывается после выхода "мыши" за пределы ограничивающего прямоугольника). Функции LButtonDown и LButtonUp позволяют определить положение левой кнопки "мыши".
ObjectWindows предусматривает ряд классов, производных от TGadget. Эти реквизиты позволяют создавать многосторонние и простые в использовании оконные элементы и новые способы взаимодействия пользователя с приложением. Это классы TSeparatorGadget, TTextGadget, TButtonGadget, TControlGadget и TBitmapGadget.
TSeparatorGadget - это очень простой реквизит-разделитель. Он просто занимает место в окне реквизитов. Вы можете использовать его, наслаивая в окне другие реквизиты, и для обеспечения полей между реквизитами (иначе они будут размещаться в окне вплотную).
Конструктор TSeparatorGadget запрещает сам себя и выключает настройку размера. Параметр Size конструктора используется для задания высоты и ширины реквизита.
TTextGadget используется для вывода в окне реквизитов текстовой информации. Вы можете задать число символов, которые должны выводиться в реквизите, а также выравнивание в нем текста.
В конструкторе TTextGadget задаются идентификатор реквизита, стиль его рамки, выравнивание текста, число выводимых символов и текст реквизита. ~TTextGadget автоматически освобождает занимаемую текстом реквизита память.
Получить и установить текст реквизита вы можете с помощью функций GetText и SetText.
TBitmapGadget - это простой класс, который может выводить на экран массив растровых изображений. Для этого битовые массивы следует разместить в ресурсе рядом друг с другом (они должны быть одной ширины).
В конструкторе TBitmapGadget задаются идентификатор ресурса битового массива, идентификатор реквизита, стиль обрамления реквизита, общее число содержащихся в битовом массиве изображений. Изменить выводимый реквизитом образ можно с помощью функции SetImage, в параметре которой задается индекс массива изображений.
TBitmapGadget реализует функцию SysColorChange, так что битовые массивы отслеживают системные цвета. Она удаляет битовый массив, вызывает функцию MapUIColors и воссоздает массив.
Реквизиты типа командных кнопок TButtonGadget - это единственный тип реквизитов, с которым пользователь может непосредственно взаимодействовать. Управляющие элементы реквизитов также обеспечивают получение данных от пользователя, но делают это через класс управляющего элемента. Реквизит в этом случае действует как посредник между управляющим элементом и окном реквизитов.
Кнопка-реквизит имеет три состояния: вверх, вниз и промежуточное. Кроме того, при нажатии во всех трех состояниях кнопка может подсвечиваться.
Существует три базовых типа кнопок-реквизитов, команд реквизитов и установки реквизитов. Установка реквизитов можете быть исключающей (как у кнопок с зависимой фиксацией) или неисключающей (как у кнопок с независимой фиксацией). Команды могут находиться только в "верхнем" состоянии. Установки могут иметь все три состояния.
После нажатия реквизита он перехватывает перемещения "мыши". Когда "мышь" перемещается вне ограничивающего прямоугольника реквизита без освобождения ее левой кнопки, подсветка отменяется, но перемещения "мыши" для реквизита все равно отслеживаются. Если "мышь" без освобождения кнопки снова перемещается внутрь ограничивающего прямоугольника реквизита, он снова подсвечивается. Если левая кнопка "мыши" освобождается, перемещения "мыши" больше не перехватываются. Если курсор при отпущенной кнопке позиционируется внутрь ограничивающего прямоугольника, то идентификатор реквизита передается окну реквизита в качестве командного сообщения.
В конструкторе TButtonGadget задаются идентификатор ресурса битового массива, выводимого в кнопке (размер которого определяется размерами кнопки), идентификатор реквизита (используется в качестве команды при его нажатии), тип реквизита (командный, исключающий или не исключающий), разрешение реквизита, состояние реквизита, повтор (повтор кнопки при удерживании ее в нажатом состоянии).
Функция ~TBurronGadget удаляет ресурсы битового массива и занимаемую строкой память.
Для доступа к кнопке-реквизиту вы можете использовать ряд функций-элементов. Эти функции позволяют вам устанавливать состояние реквизита (SetButtonState), получать его (GetButtonState), и получать тип кнопки-реквизита (GetButtonType). Модифицировать вид кнопки-реквизита и ее стиль можно с помощью функций SetNotchCorners и SetShadowStyle.
TButtonGadget переопределяет функцию CommandEnabled TGadget. Она инициализирует для реквизита сообщение WM_COMMAND_ENABLE. TButtonGadget реализует функцию SysColorChange, так что битовые массивы отслеживают системные цвета. Изменение системных цветов отражается на новой кнопке-реквизите.
TControlGadget - это достаточно простой класс, который служит интерфейсом между обычным управляющим элементом Windows и окном реквизита. Это позволяет использовать в окне реквизитов стандартные управляющие элементы Windows, такие как полоса прокрутки, строка состояния и др.
В конструкторе TControlGadget задаются управляющий элемент (ссылка на объект ObjectWindows) и стиль обрамления реквизита. Функция ~TControlGadget освобождает занимаемую объектом управляющего элемента память.
Окна реквизитов основываются на производном от TWindow классе TGadgetWindow. Они предназначены для размещения в них реквизитов, задания схемы их расположения и вывода их в другом окне. Окна реквизитов обеспечивают функциональные возможности для включенных в них реквизитов. Так как реквизиты не являются окнами, они не могут выставлять или принимать события, непосредственно взаимодействовать с окнами или вызывать для себя функции Windows. Все, что требуется делать реквизиту, должно выполняться через окно реквизитов.
Реквизит практически не может управлять своим расположением в окне реквизитов. Окно реквизитов отвечает за размещение и расположение всех реквизитов, который оно содержит. Обычно реквизиты располагаются в одну линию (вертикально или горизонтально).
Реквизиты обычно включаются в другое окно. Родительским окном окна реквизитов является как правило декорированное окно-рамка, такое как TDecoratedFrame или TDecoratedMDIFrame, хотя класс TToolBox использует обычно TFloatingFrame.
В конструкторе TGadgetWindow задается указатель на объект родительского окна, направление (горизонтальное и вертикальное), указатель на объект шрифта TFont и параметр TModule базового конструктора (по умолчанию 0). Функция ~TGadgetWindow удаляет каждый из реквизитов окна реквизитов, а затем удаляет объект шрифта.
TGadgetWindow переопределяет заданную по умолчанию функцию-элемент Create. Версия TGadgetWindow этой функции выбирает начальный размер на основе следующих критериев:
Функция Create определяет на основе этих факторов подходящий размер окна, устанавливает размеры атрибутов окна, а затем для создания интерфейсного элемента окна вызывает базовую функцию TWindow::Create.
Чтобы окно реквизитов выполняло полезные функции, оно должно содержать некоторые реквизиты. Чтобы поместить реквизит в окно, используйте функцию Insert, в параметрах которой задаются ссылка на включаемый в окно реквизит, расположение реквизита относительно соседних реквизитов и указатель на братский реквизит.
Если окно реквизитов уже создано, вам нужно после вызова Insert вызвать LayoutSession. Реквизит появится в окне после задания его схемы (LayoutSession).
Чтобы удалить из окна реквизит, используйте функцию Remove. Сам объект реквизита она не удаляет. Чтобы реквизит исчез из окна, нужно вызвать LayoutSession.
Изменить поля и схемы окна можно перед его выводом или после. Для этого используйте функции SetMargins и SetDirection. Обе эти функции устанавливают соответствующие элементы данных, а затем вызывают функцию LayoutSession. Направление вывода реквизитов определяется с помощью функции GetDirection.
По умолчанию функция LayoutSession проверяет создание интерфейсного элемента. Если нет, то функция не выполняет никаких действий. Если элемент окна уже создан, то LayoutSession выводит реквизиты без перекрытия и запрещает модифицированной область. Сеанс задания схемы обычно начинается изменением полей, вставкой или удалением реквизитов или изменением окна реквизитов.
TileGadget определяет необходимое каждому реквизиту пространство и поочередно их размещает. TileGadget вызывает функцию PositionGadget. Это позволяет производным классам настраивать интервалы между реквизитами, что помогает реализовать специальную схему расположения.
Если реквизит изменяет размер, он должен вызывать для окна реквизитов функцию GedgetChangedSize со ссылкой на реквизит с измененным размером. Заданная по умолчанию версия этой функции просто инициализирует сеанс задания схемы.
С помощью функции SetShrinkWrap вы можете задать автоматическую настройку размера окна реквизитов. Автоматическую настройку горизонтального и вертикального размера определяют параметры shrinkWrapWidth и shrinkWrapHeight.
Определить текущий шрифт и его размер можно с помощью функций GetFont и GetFontHeight.
При нажатии в ограничивающем прямоугольнике левой кнопки "мыши" реквизит всегда получает уведомление. После нажатия кнопки, если вы хотите посылать уведомления о перемещении "мыши", вам нужно перехватить нажатие кнопки. Это можно сделать с помощью функций GedgetSetCapture и GadgetReleaseCapture. Эти функции обычно вызываются реквизитом через указатель на окно реквизитов.
Режим подсказки реквизита указывает, будет ли выводиться в родительском окне окна реквизитов информация о реквизите. Этот режим устанавливается с помощью функции SetHintMode, параметр которой может иметь значения NoHints (подсказка не выводится), PressHints (подсказка выводится при нажатии реквизита) и EnterHints (подсказка выводится при перемещении "мыши" на реквизит). Определить текущий режим можно с помощью функции GetHintMode.
Вывод подсказки определяет функция SetHintCommand. Обычно она вызывается реквизитом через указатель на окно реквизитов. Чтобы эта функция правильно работала со стандартными классами ObjectWindows, нужно чтобы:
Для поиска содержащихся в окне реквизитов вы можете использовать функции FirstGadget, NextGadget, GadgetFromPoint, GadgetWidthId.
Создав класс, производный от TGadgetWindow, вы можете создать собственное специализированное окно реквизитов. Как и обычные окна, TGadgetWindow реализует функцию Paint, которая выбирает в контексте устройства шрифт окна и вызывает функцию PaintGadget, выполняющую итерацию по реквизитам окна и запрашивающую отображение каждого из них.
Для определения общего необходимого размера используйте функции GetDesiredSize и GetInnerRect (то есть размер, необходимый для размещения всех рамок, полей и реквизитов наибольшего размера). GetInnerRect вычисляет область внутри рамок и полей и помещает результат в rect.
В окне реквизитов могут использоваться следующие единицы измерения:
Обычно лучше использовать единицы схемы окна, так как они основываются на размере шрифта (вам не нужно будет беспокоиться о масштабировании). Для преобразования этих единиц в элементы изображения используется функция LayoutUnitsToPixels.
TGadgetWindow перехватывает следующие события:
ObjectWindows предусматривает ряд производных от TGadgetWindow классов, которые предусматривают ряд способов для вывода и задания схемы расположения реквизитов. Это классы TControlBar, TMessageBar, TStatusBar и TToolsBox.
Этот класс реализует строку (комплект) инструментальных средств, которые можно найти во многих популярных приложениях. В эту строку вы можете включить любой тип реквизита.
В конструкторе TControlBar задается указатель на родительское окно комплекта инструментальных средств, направление вывода (горизонтальное или вертикальное), шрифт (указатель на TFont) и модуль (TModule или 0).
Класс TMessageBar (строка сообщения) реализует без рамки и один текстовый реквизит размером с окно. Он позиционируется горизонтально по нижней границе родительского окна.
В конструкторе TMessageBar задается указатель на родительское окно, шрифт (указатель на TFont), и модуль (TModule или 0). Функция ~TMessageBar удаляет освобождает память, заданную текстом объекта.
Для задания текста сообщения в текстовом реквизите используется функция SetText, а для вывода подсказки - SetHintText.
Класс TStatusBar (строка состояния) аналогичен TMessageBar. Разница состоит в том, что строка состояния имеет больше возможностей, чем простая строка сообщения, и резервирует пространство для вывода индикаторов режимов клавиатуры (регистр, вставка/замена и др.).
В конструкторе TStatusBar задается указатель на родительское окно, стиль границы, индикаторы режима, шрифт (указатель на TFont) и модуль (TModule для базового конструктора TWindow или 0).
TStatusBar переопределяет заданную по умолчанию функцию Insert. По умолчанию версия TStatusBar добавляет новый реквизит после существующего текстового реквизита, но перед индикатором режима клавиатуры. Однако вы можете это изменить.
Чтобы вывести к строке состояния конкретный индикатор режима, вы должны задать при построении строки состояния индикатор режима. TStatusBar предусматривает ряд функций для модификации индикаторов режима. Вы можете изменить состояние индикатора режима на произвольное состояние. Для этого используется функция SetModeIndicator.
Функция SetSpacing позволяет задавать интервал между реквизитами. В параметре этой функции задается ссылка на объект TSpacing - структуру, определенную в классе TStatusBar.
TToolBox отличается от других классов окон реквизитов ObjectWindows тем, что не упорядочивает реквизиты в одну строку, а располагает их в виде матрицы. Все столбцы матрицы имеют одинаковую ширину (равную ширине максимального реквизита), а строки одинаковую высоту (равную высоте максимального реквизита).
TToolBox можно создавать как клиентное окно в TFloatingFrame для получения инструментального блока типа палитры. Примеры можно найти в подкаталоге EXAMPLES\OWL\OWLAPPS\PAINT.
В конструкторе TToolBox задается указатель на родительское окно объекта, число столбцов и строк в матрице, направление (горизонтальное/вертикальное) и модуль (TModule для базового конструктора TWindow или 0).
Вы можете задать автоматическое определение числа столбцов и строк (AS_MANY_AS_NEEDED).
В данной главе описываются классы ObjectWindows, которые позволяют вам выполнить следующие задачи печати:
Простейший способ создания объекта принтера состоит в описании в оконном объекте TPrinter*, который другие объекты в программе смогут использовать в целях печати (см. пример программы PRINTING.CPP в каталоге OWLAPI\PRINTING).
Основное окно приложения инициализирует объект принтера и использует заданный по умолчанию в WIN.INI. Однако в некоторых случаях вы можете задать другие принтеры. В этом случае постройте объект принтера в конструкторе каждого соответствующего окна. Затем измените устройство принтера. Рекомендуется всегда использовать конструктор по умолчанию, а потом изменять связанное с объектом устройство.
Создание объекта распечатки аналогично написанию функции-элемента Paint для оконного объекта: для генерации нужного образа в контексту устройства используйте графические функции Windows. Объект окна выводит содержимое и управляет взаимодействием с экраном устройства. Контекст устройства объекта распечатки аналогичным образом изолирует вас от устройства печати. Чтобы создать объект распечатки:
Объект распечатки имеет поля, содержащие размер страницы и контекст устройства. Объект принтера устанавливает эти значения вызовом функции-элемента SetPrintParams объекта распечатки. Контекст устройства объекта распечатки вам следует использовать при любых вызовах графических функций Windows.
Простейшим видом генерируемой распечатки является копия окна (оконные объекты состоят из одной страницы и знают, как отображаться в контексте устройства). Чтобы создать объект распечатки окна, постройте объект и передайте строку заголовка и указатель на нужное окно.
Часто требуется, чтобы окно создавало распечатку в ответ на команду меню. Пример вы найдете в программе PRINTING.CPP.
Windows интерпретирует распечатку как последовательность команд, поэтому объект распечатки должен превращать документ в последовательность образов страниц. Объект распечатки должен иметь возможность делать следующее:
Чтобы разрешить разбивку документа на страницы, объект принтера (производный от TPrinter) вызывает две функции объекта распечатки - SetPrintParams и GetDialogInfo. Функция SetPrintParams инициализирует в объекте распечатки переменные размера страницы и контекста устройства. Она может также генерировать всю необходимую для создания распечатки отдельных страниц информации.
После вызова SetPrintParams объект принтера вызывает функцию GetDialogInfo, которая считывает из диалогового окна принтера заданную пользователем информацию о диапазоне страниц. Она может также использоваться для вычисления общего числа страниц на основе информации о размере страницы, установленной SetPrintParams.
После того, как объект принтера дает документу возможность разбивки на страницы, он вызывает для каждой печатаемой страницы функцию-элемент PrintPage объекта распечатки. При написании функций PrintPage нужно учитывать следующее:
Объекты распечатки имеют и несколько других функций-элементов, которые вы можете при необходимости переопределить. BeginPrinting и EndPrinting вызываются перед и после печати каждого документа. Печать страниц выполняется последовательно - для каждой страницы вызывается функция PrintPage. Однако перед первым вызовом PrintPage объект распечатки вызывает BeginDocument, передавая номера первой ли последней печатаемой страницы. Если вашему документу требуется подготовка к печати других страниц (кроме первой), переопределите BeginDocument. После печати последней страницы вызывается EndDocument. При печати нескольких копий пара GebinDocument/EndDocument может вызываться между BeginPrinting и EndPrinting.
В своем приложении вы можете связать объекты распечатки с любым инсталлированным в Windows устройством печати. По умолчанию TPrinter использует принтер, заданный в Windows по умолчанию.
Существует два способа задания альтернативного принтера: непосредственное (в программе) и с помощью диалогового окна. Обычно другой принтер назначается с помощью диалогового окна, которое позволяет вам выбрать из списка инсталлированных устройств печати. TPrinter делает это автоматически при вызове его функции-элемента Setup. Setup выводит диалоговое окно на базе TPrinterDialog.
Одна из командных кнопок в диалоговом окне принтера позволяет пользователю изменить конфигурацию принтера. Кнопка Setup выводит диалоговое окно конфигурации, определенной в драйвере устройства печати.
В некоторых случаях вам может потребоваться назначить своему объекту принтера конкретное устройство печати. Это можно сделать с помощью функции-элемента SetPrinter, которая воспринимает три строковых параметра: имя устройства, имя драйвера и имя порта.
Назад | Содержание | Вперед