Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
экзамен СП.docx
Скачиваний:
18
Добавлен:
22.04.2019
Размер:
515.86 Кб
Скачать

Х.5 Управление областями вывода и отсечением

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

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

Произвольный регион создается универсальной функцией

ExtCreateRegion(const XFORM* lpXform, DWORD nDataSize, const RGNDATA lpRgnData).

Структура XFORM описывает преобразование региона из мировых координат в экранные. Если данный параметр не задан (равен NULL), координаты считаются идентичными.

Собственно регион описывается структурой RGNDATA, содержащей поля:

– RGNDATAHEADER rdh – структура данных заголовка;

– char Buffer[1] – буфер структур RECT, образующих регион.

В свою очередь, структура RGNDATAHEADER содержит поля:

– DWORD dwSize – размер заголовка в байтах;

– DWORD iType – тип региона, должен быть RGN_RECTANGLES;

– DWORD nCount – количество прямоугольников в буфере;

– DWORD nRgnSize – требуемый размер буфера, если заранее неизвестен, может быть нулевым;

– RECT rcBound – вмещающий прямоугольник для региона.

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

СreateRectRgn(), CreateRectRgnIndirect()

CreateRoundRectRgn

CreateEllipticRgn, CreateEllipticRgnIndirect

CreatePolygonRgn, CreatePolyPolygonRgn

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

Функция GetRgnData() позволяет получить доступ с данным региона по его описателю. Вмещающий прямоугольник для региона может быть получен функцией GetRgnBox().

Функции PtInRegion() и RectInRegion() проверяют соответственно точку и прямоугольник на вхождение их в регион.

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

Х.6 Некоторые аспекты использования графической подсистемы

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

– изображение строится однократно, причем в невидимом ("теневом") контексте, не связанном с видимым окном, но совместимом с его контекстом;

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

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

В Приложении приведен текст программы, иллюстрирующей описанный подход.

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

Во-первых, вызывается CreateDC со следующим набором параметров:

– lpszDriver = NULL (игнорируемый параметр);

– lpszDevice = <имя_принтера> (имя устройства, как оно зарегистрировано в системе);

– lpszOutput = NULL;

– lpInitData = lpDevMode (данные инициализации) или NULL (инициализация по умолчанию).

Структура DEVMODE с данными инициализации содержит много полей различного назначения, в данном случае заполняются функцией DocumentProperties().

Формат функции:

LONG DocumentProperties(

HWND hWnd, HANDLE hPrinter, LPTSTR pDeviceName,

DEVMODE* pDevModeOut, DEVMODE* pDevModeIn,

DWORD fMode

);

Действие: модифицирует структуру данных инициализации или вызывает диалог настроек.

Возвращаемое значение: необходимый размер буфера, если флаги режима не заданы (0); константы IDOK или IDCANCEL как признак результата вызванного диалога если вызывался диалог; IDOK, если диалог не вызывался и выполнение успешно; отрицательное значение, если произошла ошибка.

Параметры:

hWnd – описатель окна для родителя окна – диалога настроек принтера.

hPrinter – описатель используемого принтера, возвращается функцией OpenPrinter().

pDeviceName – имя используемого принтера.

pDevModeOut – указатель на заполняемую функцией структуру.

pDevModeIn – указатель на модифицируемую структуру, если установлен флаг DM_IN_BUFFER (см. ниже); в остальных случаях игнорируется.

fMode – флаг режима выполнения функции, комбинация по ИЛИ следующих значений: DM_IN_BUFFER (дополнение стандартных для данного принтера настроек информацией из "входной" структуры), DM_IN_PROMPT или DM_PROMPT (вызов стандартного диалога настроек принтера), DM_OUT_BUFFER или DM_COPY (запись всех настроек принтера в выходную структуру).

Во-вторых, вызывается функция StartDoc().

Формат функции:

Int StartDoc(HDC hDC, const DOCINFO* lpDocInfo);

Действие функции: начало сеанса работы принтера (print job).

Возвращаемое значение: положительный идентификатор сеанса или признак ошибки.

Параметры:

hDC – контекст устройства (принтера).

lpDocInfo – структура DOCINFO, содержащая информацию о принтере. Основное назначение структуры – специфицировать имя устройства (перекрывает имя, заданное в CreateDC()) и имя документа.

Открытый сеанс закрывается функцией EndDoc(HDC hDC). Воздействовать на находящиеся в очереди сеансы можно функциями SetJob(), GetJob(), AddJob(), ScheduleJob().