Хотя некоторым приложений Windows для организации полного интерфейса пользователя нужны только окна, диалоги и управляющие элементы, многим приложениям (например, программам – осциллографам или генераторам функций) требуется наличие графических средств. Эта простейшая графика может быть в форме линий, кривых, фигур, текста и т.д.
Для предоставления приложениям графических функциональных возможностей Windows имеет стандартный набор функций, называемый интерфейсом графических устройств – GDI. Функции GDI предоставляют возможности рисования, которые не зависят от используемого устройства вывода. Например, одни и те же функции можно использовать для организации вывода на дисплей или принтер. Аппаратная независимость реализуется через использование драйверов устройств, которые переводят функции GDI в команды, воспринимаемые используемым устройством вывода. Это означает, что не нужно беспокоиться о том, как конкретное устройство (например, определенная марка принтеров) работает с графическим образом. Подобная абстракция аппаратной части является очень распространенной. Ценой универсальности являются достаточно ограниченные возможности по работе с графикой и невысокое быстродействие графических команд. Насыщенные визуальными данными программы следует разрабатывать с использованием специализированных программных средств: OpenGL, GLES, Direct3D и т.п.
В отличие от традиционных графических программ DOS программы Windows никогда не выводят элементы изображения непосредственно на экран или на принтер, а записывают их в логическую сущность, называемую контекстом устройства. Контекст устройства – это виртуальная поверхность с присущими ей атрибутами, такими как перо, кисть, шрифт, цвет фона, цвет текста и текущая позиция. Для приложения, независимо от того, какое это на самом деле устройство, все контексты устройства выглядят аналогично.
Как правило, приложения выполняют свою работу по рисованию содержимого окна во время обработки сообщения Windows WM_PAINT, хотя часто требуется рисовать и во время обработки других сообщений. В любом случае приложению нужно придерживаться следующей последовательности действий:
1. получение или создание контекста отображения;
2. установка необходимых атрибутов в контексте отображения;
3. выполнение операций рисования;
4. освобождение либо удаление контекста отображения.
Последнее действие (освобождение либо удаление контекста отображения) должно быть обязательно выполнено, так как контекст – очень ресурсоёмкая структура данных. Если создать множество контекстов, а затем не удалить (или не освободить) эти контексты, система станет работать нестабильно из-за нехватки ресурсов, единственным выходом станет ее перезагрузка.
Рассмотрим особенности работы устройств вывода информации на примере программы построения круговой диаграммы, окно которой показано на рисунке 2.2.1.
Рисунок 2.2.1 – Тестовая программа, выполняющая визуализацию данных
Программа основана на примере простейшей программы Windows, рассмотренной ранее. Текст на языке C++ рабочей программы выглядит следующим образом (для удобства новый код выделен жирным шрифтом):