В ранних ПК и операционных системах, аппаратная и программная части отображения информации были реализованы таким образом, что вывод на экран [монитора] мог осуществляться напрямую любой исполняющейся в данный момент программой (кодом). При дальнейшем развитии технологий, в частности эволюции многозадачных операционных систем семейства Windows, с целью сохранения целостности/контроля ОС, возможность прямого неконтролируемого вывода на экран (как это было во времена MSDOS) убрали. По причине того, что современные ОС являются многозадачными, то есть в них [псевдо]параллельно выполняются сразу множество процессов, отображение информации должно быть подчинено строгому регламенту. С целью обеспечения возможности вывода на устройство (экран, принтер, память) одновременно от множества источников (процессов/приложений), в Windows был разработан специализированный механизм под названием контекст устройства (device context, DC) и подмножество обеспечивающих его работу функций. Указанные функции определяют размер клиентской области, шрифт, цвета и другие GDI-атрибуты и возвращают (предоставляют) приложению так называемый дескриптор контекста устройства (Device Context Descriptor). Поскольку контекст устройства является одним из основополагающих понятий в понимании механизмов вывода информации на устройство, я постараюсь дать некоторое количество определений для погружения в тему:
- Контекст устройства - логическое устройство вывода, посредством которого осуществляется вывод информации на устройство вывода (дисплей, принтер, память).
- Контекст устройства - структура данных, описывающая устройство отображения информации.
В операционной системе Windows существует несколько типов контекстов устройства, а именно:
- Контекст устройства отображения (display);
- Контекст устройства печати (printer);
- Контекст устройства памяти (memory, CompatibleDC);
- Контекст информационного устройства (information);
Таким образом:
- если приложение создает/получает собственный контекст для отрисовки в собственном окне, такой контекст называется контекстом устройства отображения.
- если приложению необходимо выполнить операцию ввода-вывода на аппаратное устройство (экран, принтер, память), такой контекст называется контекстом устройства печати, контекстом устройства памяти или контекстом информационного устройства.
Нас же в рамках данной статьи интересует контекст устройства отображения:
Существует несколько типов контекста отображения:
- Контекст отображения класса окна (class display context);
- Общий контекст отображения (common display context);
- Личный контекст отображения (private display context);
- Контекст отображения окна (window display context);
- Родительский контекст отображения (parent display context);
Соответственно, методы получения (освобождения) контекста отображения различны для контекстов описанных типов. И где же он непосредственно используется? В процессе изучения функционала GDI становится очевидным, что во многих WinAPI-функциях вывода графических примитивов в Windows одним из входных параметров является указатель на контекст устройства отображения.
Дескриптор (описатель) контекста отображения, возвращаемый функциями WinAPI, это своеобразный указатель, предоставляемый системой пользовательскому уровню приложения, посредством которого приложение получает доступ к устройству вывода (например, экран).
Каждое приложение в случае необходимости экранного вывода получает в свое распоряжение собственный (уникальный) контекст и осуществляет посредством него вывод изображения. Поэтому, более интуитивно дескриптор контекста устройства отображения воспринимается в качестве указателя на некую системную структуру в памяти ядра, через параметры которой системе задаются критерии вывода данных на физическое устройство отображения.
Структура контекста устройства
Надо учитывать, что контекст устройства является структурой, состоящей, в свою очередь, из описателей объектов графических примитивов (характеристик), используемых при работе с контекстом:
Атрибут контекста | Значение по умолчанию | Функция для изменения | Функция для получения |
---|---|---|---|
Режим отображения (Mapping mode) | MM_TEXT | SetMapMode |
GetMapMode |
Начало координат окна (Window origin) | (0,0) | SetWindowOrgEx |
GetWindowOrgEx |
Начало координат области вывода (Viewport Origin) | (0,0) | SetViewportOrgEx |
GetViewportOrgEx |
Протяженность окна (Window extent) | (1,1) | SetWindowExtEx |
GetWindowExtEx |
Протяженность области вывода (Viewport extent) | (1,1) | SetViewportExtEx , SetMapMode |
GetViewportExtEx |
Перо (Pen) | BLACK_PEN | SelectObject |
SelectObject |
Кисть (Brush) | WHITE_BRUSH | SelectObject |
SelectObject |
Шрифт (Font) | SYSTEM_FONT | SelectObject |
SelectObject |
Битовый образ (Bitmap) | NOT | SelectObject |
SelectObject |
Текущая позиция пера (Current pen position) | (0,0) | MoveToEx , LineTo , PolylineTo , PolyBezierTo |
GetCurrentPositionEx |
Режим фона (Background mode) | OPAQUE | SetBkMode |
GetBkMode |
Цвет фона (Background color) | Обычно Белый (по Панели управления) | SetBkColor |
GetBkColor |
Цвет текста (TextColor) | Обычно Черный (по Панели управления) | SetTextColor |
GetTextColor |
Режим рисования (Drawing mode) | R2_COPYPEN | SetROP2 |
GetROP2 |
Режим растяжения (Stretching mode) | BLACKONWHITE | SetStrethBltMode |
GetStrethBltMode |
Режим закрашивания многоугольников (Polygon filling mode) | ALTERNATE | SetPolyFillMode |
GetPolyFillMode |
Межсимвольный интервал (Intercharacter spacing) | 0 | SetTextCharacterExtra |
GetTextCharacterExtra |
Начало координат кисти (Brush origin) | (0,0) | SetBrushOrgEx |
GetBrushOrgEx |
Область отсечения (Clipping region) | Not. Окно (рабочая область) с обновляемым регионом обрезается. | SelectObject , SelectClipRgn
|
GetClipBox |
Обычно данная структура содержит значения по умолчанию, определенные разработчиками из Microsoft.
Вы имеете возможность менять указанные атрибуты по собственному желанию уже после того, как получили дескриптор контекста устройства отображения. Но не надо забывать, что когда пользовательскому приложению требуется изменить какой-либо элемент структуры контекста устройства, оно должно производить эти действия исключительно через предназначенные для этого функции WinAPI, поскольку напрямую элементы структуры контекста устройства для изменения не доступны. Все описанные выше инструменты (и их параметры) доступны для выбора и переназначения, поскольку функции GDI используют только выбранные в контекст устройства параметры и инструменты рисования.
Помимо связывания функций вывода WinAPI с конкретным устройством, контекст устройства решает проблему чрезмерной нагрузки на систему при интенсивном вызове GDI-функций. Ведь если разобраться, то становится очевидным, что параметры в контексте устройства присутствуют для снижения нагрузки на подсистемы ядра от необходимости постоянной передачи одних и тех же атрибутов при каждом вызове GDI-функций.
Любой контекст устройства должен ассоциироваться с каким-либо аппаратным устройством (видеоадаптер, принтер, память). Например, для случая вывода текста в окно приложения, контекст устройства отображения для пользовательского приложения ассоциируется с областью окна приложения (не со всем экраном) и видеоадаптером/монитором.
Сопряжение логического изображения с определенным видеоадаптером осуществляется уже на уровне ядра операционной системы на основе установленных в системе драйверов видеоадаптера. Контекст устройства дополнительно решает еще и задачу абстракции (независимости) от конкретной аппаратной архитектуры, позволяющей приложению записывать данные в аппаратное устройство, абсолютно не заботясь о том, правильно или неправильно будет представлена информация на огромном количестве существующих или перспективных аппаратных устройств, имеющих свою специфику. Таким образом обеспечивается идентичность изображения на всех конфигурациях, на которых работает операционная система Windows.
Спасибо за статью