Контекст устройства в Windows программах.
Работа с контекстом устройства (DC-Device Context) начинается с получения контекста устройства для того окна, в котором будет выводиться графическая информация. Если в качестве устройства вывода используется экран монитора, то для получения контекста можно применять функцию BeginPaint().
HDC hdc; //идентификатор контекста устройства
PAINTSTRUCT ps; //структура для работы контекста
Окно приложения имеет идентификатор hwnd. (handle of window). Выбранный контекст устройства имеет идентификатор hdc (handle of device context). Функция BeginPaint() связывает выбранный контекст hdc с окном приложения hwnd. Кроме того, функция BeginPaint() заполняет структуру PAINTSTRUCT.
После рисования нужно освободить контекст устройства. Для освобождения контекста нужно использовать функцию EndPaint(). Таким образом, для работы с контекстом окна на экране монитора используется пара функций BeginPaint() и EndPaint(). Схему применения этих функций можно представить в виде.
Важное замечание, пара функций BeginPaint() и EndPaint() должна использоваться только во время обработки сообщения WM_PAINT. Во всех остальных случаях для работы с контекстом экрана монитора надо использовать другую пару функций GetDC() и ReleaseDC().Схему применения этих функций можно представить в виде.
Проведите эксперимент. Запустите программу GraphWin.exe, и меняйте размеры окна приложения, или перемещайте окно по экрану монитора. Вы заметите, что изображение нарисованного графика не исчезает. Это связано с тем, что на все ваши действия с окном, система посылает окну сообщение WM_PAINT. Ваша программа в ответ рисует график снова и снова. При использовании функций GetDC() и ReleaseDC() такого не происходит.
Контекст устройства содержит по умолчанию перо и кисть с заданными параметрами. Если программист решит выбрать перья и кисти с другими параметрами, то нужно провести следующие действия. Разберем эти действия на примере функции Line_OnPaint().
Сначала создаем кисть с помощью функции CreateSolidBrush().
hbrush = CreateSolidBrush(RGB(0, 0, 200));
Созданная кисть имеет идентификатор hbrush (handle of brush). Кисть hbrush имеет следующие параметры: стиль — сплошной, цвет — синий.
Далее выбираем кисть hbrush в контекст устройства hdc. После этого в контексте устройства будет находиться новая кисть. Чтобы сохранилась информация о старой кисти, необходимо использовать для старой кисти свой идентификатор hbrushOld.
hbrushOld = (HBRUSH)SelectObject(hdc, hbrush);
После этого можно рисовать в контексте hdc, используя выбранную кисть hbrush. Важно то, что, создавая новое перо или кисть, надо позаботиться об уничтожении их после использования. Кисть (перо) есть объект GDI, для него выделяется специальная область памяти. Кисть (перо) существует до тех пор, пока его не уничтожить. Завершение работы функции, в которой создавалась кисть или перо не приводит к автоматическому уничтожению объектов GDI и освобождению памяти. Своевременное уничтожение неиспользуемых объектов GDI возлагается на программиста.
Уничтожение созданной кисти hbrush выполняется функцией DeleteObject(). Перед уничтожением новой кисти hbrush, надо восстановить в контексте hdc кисть по умолчанию hbrushOld. Схему создания и уничтожения кисти можно представить в виде.
hbrush = CreateSolidBrush(RGB(0, 0, 200));
Какие функции можно использовать для получения контекста устройства
Отображение элементов графического пользовательского интерфейса в операционной системе Windows осуществляется библиотекой GDI, которая является частью API. В ней реализовано большое количество функций для вывода на экран (в окна) простейших графических примитивов, а также самих элементов графического пользовательского интерфейса (элементов окон, элементов управления). Библиотека MFC обеспечивает осуществление графического вывода на основе объектно-ориентированного подхода.
Всю информацию о моделируемом объекте обычно трудно отобразить только в стандартных элементах управления. Программистам необходимо самим отображать (рисовать) объекты моделирования, графики, характеризующие их параметры и т.п. Операционная система делает всё, чтобы этот процесс был простым. В частности, графический вывод осуществляется унифицированно в независимости от устройства вывода (принтер или экран). Это достигается благодаря понятию контекст устройства (DC, Device Context). Контекст устройства связывает универсальный графический вывод с конкретным устройством, определяет систему координат и режимы графического вывода.
Базовый класс для работы с конекстом устроейства — CDC . Именно в нем инкапсулирована информация о параметрах графического вывода. Контекст устройства предоставляет средства для рисования, а также позволяет менять инструменты рисования (перья, кисти и т.п.)
Окно — основной объект графического пользовательского интерфейса, и при выводе информации на экран графический вывод осуществляется именно в окна. В каждый момент времени только одно окно является устройством вывода. Для получения контекста окна как устройства для графического вывода можно воспользоваться функцией GetDC() класса CWnd , которая возвращает указатель на контекст устройства для рисования в окне. При рисовании в окнах можно воспользоваться услугами наследников класса CDC .
Для орагнизации стандартной процедуры рисования в клиентской области окна при обработке события WM_PAINT можно использовать экземпляр класса CPaintDC . Для извещения о перерисовке в его конструкторе вызывается функция BeginPaint , а в деструкторе EndPaint . Класс CClientDC не выполняет эти функции автоматически, а предосталяет пользователю полную свободу в организации процедуры рисования. При использовании класса CWindowDC рисование может выполняться не только в клиентской области, но и в служебных областях окна (поверх заголовка, рамки или меню). Библиотека MFC предоставляет также контекст CMetaFileDC , который связан с метафайлом, в котором в специальном формате сохраняются команды для вызова фунций GDI.
Контекст устройства отображения
В ранних ПК и операционных системах, аппаратная и программная части отображения информации были реализованы таким образом, что вывод на экран [монитора] мог осуществляться напрямую любой исполняющейся в данный момент программой (кодом). При дальнейшем развитии технологий, в частности эволюции многозадачных операционных систем семейства Windows, с целью сохранения целостности/контроля ОС, возможность прямого неконтролируемого вывода на экран (как это было во времена MSDOS) убрали. По причине того, что современные ОС являются многозадачными, то есть в них [псевдо]параллельно выполняются сразу множество процессов, отображение информации должно быть подчинено строгому регламенту. С целью обеспечения возможности вывода на устройство (экран, принтер, память) одновременно от множества источников (процессов/приложений), в Windows был разработан специализированный механизм под названием контекст устройства (device context, DC ) и подмножество обеспечивающих его работу функций. Указанные функции определяют размер клиентской области, шрифт, цвета и другие GDI-атрибуты и возвращают (предоставляют) приложению так называемый дескриптор контекста устройства (Device Context Descriptor). Поскольку контекст устройства является одним из основополагающих понятий в понимании механизмов вывода информации на устройство, я постараюсь дать некоторое количество определений для погружения в тему:
- Контекст устройства — логическое устройство вывода, посредством которого осуществляется вывод информации на устройство вывода (дисплей, принтер, память).
- Контекст устройства — структура данных, описывающая устройство отображения информации.
В операционной системе Windows существует несколько типов контекстов устройства, а именно:
- Контекст устройства отображения (display);
- Контекст устройства печати (printer);
- Контекст устройства памяти (memory, CompatibleDC);
- Контекст информационного устройства (information);
- если приложение создает/получает собственный контекст для отрисовки в собственном окне, такой контекст называется контекстом устройства отображения.
- если приложению необходимо выполнить операцию ввода-вывода на аппаратное устройство (экран, принтер, память), такой контекст называется контекстом устройства печати, контекстом устройства памяти или контекстом информационного устройства.
Все виды контекстов устройств имеют идентичную структуру и содержат одни и те же атрибуты (характеристики).
Нас же в рамках данной статьи интересует контекст устройства отображения:
Контекст устройства отображения — внутренняя структура данных ядра Windows, определяющая набор графических объектов и их атрибутов (режим отображения, начало координат, цвет пера, цвет кисти, тип шрифта, цвет/режим текста/фона, режим вывода/закрашивания и некоторые другие), используемая прикладной программой/системой для задания критериев вывода графических объектов (текст/графика) на экран видеоадаптера.
Существует несколько типов контекста отображения:
- Контекст отображения класса окна (class display context);
- Общий контекст отображения (common display context);
- Личный контекст отображения (private display context);
- Контекст отображения окна (window display context);
- Родительский контекст отображения (parent display context);
Соответственно, методы получения (освобождения) контекста отображения различны для контекстов описанных типов. И где же он непосредственно используется? В процессе изучения функционала GDI становится очевидным, что во многих WinAPI-функциях вывода графических примитивов в Windows одним из входных параметров является указатель на контекст устройства отображения.
В GDI все операции рисования должны выполняться через контекст устройства [отображения].
Дескриптор (описатель) контекста отображения, возвращаемый функциями 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.
Каждый DC имеет текущие параметры: кисть, перо, шрифт и так далее, то есть текущий (рабочий) объект определенного типа. Поэтому могут (к примеру) быть выбраны одновременно перо и кисть, но нельзя выбрать перо дважды.
Вы имеете возможность менять указанные атрибуты по собственному желанию уже после того, как получили дескриптор контекста устройства отображения. Но не надо забывать, что когда пользовательскому приложению требуется изменить какой-либо элемент структуры контекста устройства, оно должно производить эти действия исключительно через предназначенные для этого функции WinAPI, поскольку напрямую элементы структуры контекста устройства для изменения не доступны. Все описанные выше инструменты (и их параметры) доступны для выбора и переназначения, поскольку функции GDI используют только выбранные в контекст устройства параметры и инструменты рисования.
Соответственно, перед использованием того или иного графического объекта в контексте устройства, он должен быть предварительно «выбран» при помощи вышепривиденных (в таблице) функций.
Помимо связывания функций вывода WinAPI с конкретным устройством, контекст устройства решает проблему чрезмерной нагрузки на систему при интенсивном вызове GDI-функций. Ведь если разобраться, то становится очевидным, что параметры в контексте устройства присутствуют для снижения нагрузки на подсистемы ядра от необходимости постоянной передачи одних и тех же атрибутов при каждом вызове GDI-функций.
Факт получения контекста устройства отображения можно воспринимать в виде своего рода негласного разрешения на отрисовку в собственной клиентской области окна. Как только вы получили контекст, то можете начинать рисовать.
Любой контекст устройства должен ассоциироваться с каким-либо аппаратным устройством (видеоадаптер, принтер, память). Например, для случая вывода текста в окно приложения, контекст устройства отображения для пользовательского приложения ассоциируется с областью окна приложения (не со всем экраном) и видеоадаптером/монитором.
Фактически дескриптор контекста устройства представляет собой число, которое является уникальным для каждого окна.
Сопряжение логического изображения с определенным видеоадаптером осуществляется уже на уровне ядра операционной системы на основе установленных в системе драйверов видеоадаптера. Контекст устройства дополнительно решает еще и задачу абстракции (независимости) от конкретной аппаратной архитектуры, позволяющей приложению записывать данные в аппаратное устройство, абсолютно не заботясь о том, правильно или неправильно будет представлена информация на огромном количестве существующих или перспективных аппаратных устройств, имеющих свою специфику. Таким образом обеспечивается идентичность изображения на всех конфигурациях, на которых работает операционная система Windows.
Контекст устройства отображения является критическим для системы ресурсом. Поэтому его необходимо освободить сразу по окончании использования.
Похожие записи:
- Консольное приложение на ассемблере
- Оконное приложение на ассемблере
- Шестнадцатеричное число в строку на ассемблере
- Размер окна приложения на ассемблере
- Генератор случайных чисел на ассемблере
Функции контекста устройства
Следующие функции используются с контекстами устройств.
Функция | Описание |
---|---|
CancelDC | Отменяет все ожидающие операции в указанном контексте устройства. |
ChangeDisplaySettings | Изменяет параметры устройства отображения по умолчанию на указанный графический режим. |
ChangeDisplaySettingsEx | Изменяет параметры указанного устройства отображения на указанный графический режим. |
CreateCompatibleDC | Создает контекст устройства памяти, совместимый с указанным устройством. |
CreateDC | Создает контекст устройства, используя указанное имя. |
CreateIC | Создает контекст сведений для указанного устройства. |
DeleteDC | Удаляет указанный контекст устройства. |
DeleteObject | Удаляет логическое перо, кисть, шрифт, растровое изображение, область или палитру, освобождая все системные ресурсы, связанные с объектом . |
DeviceCapabilities | Извлекает возможности драйвера устройства принтера. |
DrawEscape | Предоставляет возможности рисования указанного видеотрансляции, недоступные напрямую через интерфейс графического устройства. |
EnumDisplayDevices | Извлекает сведения об устройствах отображения в системе. |
EnumDisplaySettings | Извлекает сведения об одном из графических режимов для устройства отображения. |
EnumDisplaySettingsEx | Извлекает сведения об одном из графических режимов для устройства отображения. |
EnumObjects | Перечисляет ручки или кисти, доступные для указанного контекста устройства. |
EnumObjectsProc | Определяемая приложением функция обратного вызова, используемая с функцией EnumObjects . |
GetCurrentObject | Извлекает дескриптор для объекта указанного типа, выбранного в заданном контексте устройства. |
GetDC | Извлекает дескриптор в контекст устройства отображения для клиентской области указанного окна или для всего экрана. |
GetDCBrushColor | Извлекает текущий цвет кисти для указанного контекста устройства. |
GetDCEx | Извлекает дескриптор в контекст устройства отображения для клиентской области указанного окна или для всего экрана. |
GetDCOrgEx | Извлекает окончательный источник преобразования для указанного контекста устройства. |
GetDCPenColor | Извлекает текущий цвет пера для указанного контекста устройства. |
GetDeviceCaps | Извлекает сведения о конкретном устройстве для указанного устройства. |
GetLayout | Извлекает макет контекста устройства. |
GetObject | Извлекает сведения для указанного графического объекта. |
GetObjectType | Извлекает тип указанного объекта. |
GetStockObject | Извлекает дескриптор одного из стандартных перьев, кистей, шрифтов или палитр. |
ReleaseDC | Освобождает контекст устройства, освобождая его для использования другими приложениями. |
ResetDC | Обновления указанный контекст принтера или устройства плоттера, используя указанные сведения. |
RestoreDC | Восстанавливает контекст устройства до указанного состояния. |
SaveDC | Сохраняет текущее состояние указанного контекста устройства, копируя данные, описывающие выбранные объекты и графические режимы, в контекстный стек. |
SelectObject | Выбирает объект в указанном контексте устройства. |
SetDCBrushColor | Задает для текущего цвета контекста устройства указанное значение цвета. |
SetDCPenColor | Задает для текущего цвета пера контекста устройства указанное значение цвета. |
SetLayout | Задает макет для контекста устройства. |
WindowFromDC | Возвращает дескриптор окна, связанного с контекстом устройства. |
Обратная связь
Были ли сведения на этой странице полезными?