95 в двух томах Том I


Глава 4 Главное о графике



Pdf просмотр
страница7/41
Дата27.11.2016
Размер4.32 Mb.
Просмотров7810
Скачиваний0
ТипРеферат
1   2   3   4   5   6   7   8   9   10   ...   41
Глава 4
Главное о графике
Графический интерфейс устройства (GDI) — подсистема Windows 95, отвечающая за отображение графики
(включая текст) на видеотерминалах и принтерах. Как можно догадаться, GDI — очень важная компонента
Windows. Не только приложения, разрабатываемые вами, активно используют GDI для отображения информации, но и Windows сама очень активно использует его для отображения элементов пользовательского интерфейса, таких как меню, полосы прокрутки, значки и курсоры мыши.
Вероятно, программисты, работающие с MS DOS и ранними версиями Windows по принципу "делаю, что хочу", часто пользовались возможностью работать, минуя GDI, и записывать информацию непосредственно в видеопамять. Пожалуйста, никогда не помышляйте об этом. Это может доставить вам много головной боли, привести к конфликтам с другими программами Windows 95, сделать ваши программы несовместимыми с будущими версиями операционной системы.
В отличие от некоторых новых особенностей Windows 95, GDI практически не менялся с самого начала.
Внутренне Windows 1.0, в основном, состояла из трех динамически подключаемых библиотек, KERNEL (ядро — обработка задач, управление памятью, файловый ввод/вывод), USER (интерфейс пользователя) и GDI. В более поздние версии Windows были включены дополнительные функциональные возможности GDI, сохраняя в основном совместимость с существующими программами, но основа GDI осталась без изменений.
Конечно, полное описание GDI потребовало бы отдельной книги. Но это не наша задача. В этой главе вам будут даны достаточные знания о GDI для понимания программ из этой книги, использующих графику, и, некоторая другая информация, которая может вам оказаться полезной.
Концепция GDI
Графика в 32-битной Windows реализуется, в основном, функциями, экспортируемыми из GDI32.DLL, динамически подключаемой библиотеки, которая часто использует 16-битную динамически подключаемую библиотеку GDI.EXE. (Динамически подключаемые библиотеки в ранних версиях Windows чаще имели расширение EXE, а не DLL). Эти модули обращаются к различным функциям драйверов отображения — .DRV файлу для видеомониторов и, возможно, к одному или нескольким .DRV файлам драйверов принтеров или плоттеров. Видеодрайвер осуществляет доступ к аппаратуре видеомонитора или преобразует команды GDI в коды или команды, воспринимаемые различными принтерами. Разные видеоадаптеры и принтеры требуют различных файлов драйверов.
Поскольку к IBM PC совместимым компьютерам может быть подключено множество различных устройств отображения, одной из основных задач GDI является поддержка аппаратно-независимой графики. Программы для
Windows должны нормально работать на любых графических устройствах отображения, которые поддерживаются
Windows. GDI выполняет эту задачу, предоставляя возможность отделить ваши программы от конкретных характеристик различных устройств отображения.
Все графические устройства отображения делятся на две больших группы: растровые устройства и векторные устройства. Большинство устройств, подключаемых к PC — растровые устройства, т. е. они представляют графические образы как шаблон точек. Эта группа включает видеоадаптеры, матричные принтеры и лазерные принтеры. Группа векторных устройств, отображающих графические образы с использованием линий, в основном, состоит из плоттеров.
Большинство традиционных графических программ работает исключительно с векторами. Это значит, что программа, использующая один из таких графических языков, абстрагируется от особенностей оборудования.
Устройство отображения оперирует пикселями для создания графических образов, тогда как программа при связи с интерфейсом не использует понятие пикселя. Несмотря на то, что Windows GDI — это высокоуровневая

70 векторная система рисования, она также может применяться и для относительно низкоуровневых манипуляций с пикселями.
С этой точки зрения, Windows GDI это такой же традиционный графический язык, как C — язык программирования. Язык C — хорошо известен своей высокой степенью переносимости относительно разных операционных систем и сред. C также хорошо известен тем, что дает программисту возможность выполнять низкоуровневые системные функции, что часто недоступно в других языках программирования высокого уровня.
Также как C иногда называют "ассемблером высокого уровня", так можно считать, что GDI — это высокоуровневый интерфейс для аппаратных средств графики.
Как уже было сказано выше, по умолчанию Windows использует систему координат, основанную на пикселях.
Большинство традиционных графических языков используют "виртуальные" системы координат, с границами 0 и
32767 для горизонтальной и вертикальной осей. Хотя некоторые графические языки не дают вам возможности использовать пиксельную систему координат, Windows GDI позволяет применять обе системы (также как дополнительные координатные системы на базе физических единиц измерения). Вы можете работать с виртуальной системой координат и абстрагировать вашу программу от аппаратуры или использовать систему координат устройства и приблизиться вплотную к аппаратуре.
Некоторые программисты думают, что как только начинается работа в терминах пикселей, нарушается аппаратурная независимость. В главе 3 мы уже видели, что это не всегда верно. Хитрость состоит в использовании пикселей в аппаратно-независимых образах. Это требует, чтобы язык графического интерфейса давал программе возможность определить аппаратные характеристики устройства и выполнить соответствующее согласование.
Например, в программе SYSMETS мы использовали размер символа стандартного системного шрифта в пикселях для расчета пробелов в тексте на экране. Этот подход позволил программе работать на различных дисплейных адаптерах с разной разрешающей способностью, размерами текста и коэффициентом искажения. В этой главе будут показаны другие методы определения размеров дисплея.
Когда-то работа под Windows с монохромным дисплеем была нормой. Даже еще совсем недавно дисплеи переносных компьютеров были ограничены оттенками серого. Поэтому GDI был разработан так, что можно писать программу, не беспокоясь по поводу цветов — Windows может преобразовать цвета в оттенки серого. И сегодня видеомониторы, используемые с Windows 95, имеют различные цветовые возможности (16 цветов, 256 цветов,
"полноцветные"), а большинство пользователей работают с монохромными принтерами. Можно применять эти устройства вслепую, но ваша программа вполне способна определить, сколько цветов доступно на конкретном дисплее, а затем наилучшим образом воспользоваться устройством.
Есть вероятность, что в то самое время когда вы пишете программы на C и мастерски решаете проблемы переносимости с компьютера на компьютер, в ваши программы для Windows, естественно непреднамеренно, будут включены аппаратно-зависимые фрагменты. Это часть цены за то, что вы не полностью изолированы от аппаратуры. Мы рассмотрим некоторые из этих аппаратно-зависимых аспектов в данной главе.
Также следует упомянуть об ограничениях Windows GDI. GDI не в состоянии (в настоящее время) сделать все, что вы можете пожелать. Несмотря на то, что существует возможность перемещения графических объектов по экрану,
GDI, в основном, статическая система отображения с ограниченной поддержкой анимации. В реализации Windows
95 GDI не обеспечивает трехмерных представлений или возможности вращения объектов. Например, при рисовании эллипса, его оси должны быть параллельны горизонтальной и вертикальной осям. Несмотря на то, что некоторые графические языки используют числа с плавающей точкой для представления виртуальных координат,
Windows 95 из соображений производительности всегда использует 16-разрядные знаковые целые. Это особенность Windows 95. Windows NT поддерживает 32-разрядные координаты.
Структура GDI
С точки зрения программиста GDI состоит из нескольких сотен функций и нескольких связанных с ними типов данных, макросов и структур. Но прежде, чем рассматривать некоторые из этих функций подробно, следует остановиться на общей структуре GDI .
Типы функций
В основном, функции GDI могут быть разбиты на несколько крупных групп. Это группы не имеют четких границ и частично перекрываются. Все они, тем не менее, перечислены ниже:

Функции, которые получают (или создают) и освобождают (или уничтожают) контекст устройства.
Как уже указывалось в главе 3, вам для рисования необходим описатель контекста устройства. Функции
GetDC и ReleaseDC позволяют вам сделать это внутри обработчиков сообщений, отличных от
WM_PAINT. Функции BeginPaint и EndPaint (хотя технически — это часть подсистемы USER в Windows) используются в теле обработчика сообщения WM_PAINT для рисования. Некоторые другие функции, относящиеся к работе с контекстом устройства, мы рассмотрим ниже.

71

Функции, которые получают информацию о контексте устройства. Вспомним, в программе SYSMETS в главе 3 мы использовали функцию GetTextMetrics для получения информации о размерах выбранного в контексте устройства шрифта. Далее в этой главе мы рассмотрим программу DEVCAPS1, с помощью которой можно получить самую общую информацию о контексте устройства.

Функции рисования. Очевидно, из всех предварительно рассмотренных функций — это одна из самых важных. В главе 3 мы использовали функцию TextOut для отображения текста в рабочей области окна. Как мы увидим далее, другие функции GDI позволяют рисовать линии, залитые области, растровые образы.

Функции, которые устанавливают и получают атрибуты контекста устройства. Атрибут контекста устройства определяет различные особенности работы функции рисования. Например, вы используете функцию SetTextColor для задания любого текста, выводимого с использованием функции TextOut (или любой другой функции вывода текста). В программах SYSMETS в главе 3 мы использовали функцию
SetTextAlign для того, чтобы сообщить GDI, что начальное положение текстовой строки при вызове функции TextOut должно быть справа, по умолчанию — левое начальное положение. Все атрибуты контекста устройства имеют значение по умолчанию, которое устанавливается, при получении контекста устройства. Для всех функций Set есть функции Get, позволяющие получить текущее значение атрибута контекста устройства.

Функции, которые работают с объектами GDI. Именно эти функции вносят в GDI некоторый беспорядок. Сначала пример: по умолчанию любые линии, которые вы рисуете, используя GDI, — сплошные и стандартной ширины. Вы хотите изобразить линии более широкими или сделать их штрихпунктирными. Ширина линии и стиль линии не являются атрибутами контекста устройства. Это характеристики "логического карандаша". Вы можете создать логический карандаш, указав данные характеристики в функциях CreatePen, CreatePenIndirect, ExtCreatePen. Эти функции возвращают описатель логического карандаша. (Хотя считается, что эти функции являются частью GDI, в отличие от большинства функций GDI они не требуют описателя контекста устройства.) Для использования логического карандаша вы "выбираете" описатель в контекст устройства. С этого момента все рисуемые линии будут отображаться с использованием этого карандаша. Затем вы отменяете выбор объекта "карандаш" и уничтожаете его. Кроме карандашей, вы также используете объекты GDI для создания кистей, которыми зарисовываются замкнутые области для создания шрифтов, растровых образов и других объектов GDI, о которых будет рассказано в этой главе.
Примитивы GDI
Типы графических объектов, выводимых на экран или принтер, которые могут быть разделены на несколько категорий, часто называют "примитивами". Это:

Прямые (отрезки) и кривые. Прямые — основа любой векторной графической системы. GDI поддерживает прямые линии, прямоугольники, эллипсы (включая окружности), дуги, являющиеся частью кривой эллипса, и сплайны Безье. Все они будут рассмотрены в этой главе. Более сложные кривые могут быть изображены как ломаные линии, которые состоят из очень коротких прямых, определяющих кривые.
Линии рисуются с использованием карандаша, выбранного в контексте устройства.

Закрашенные области. Если набор прямых и кривых линий ограничивает со всех сторон некоторую область, то она может быть закрашена с использованием объекта GDI "кисть", выбранного в контексте устройства. Эта кисть может быть сплошной, штриховой (состоящей из горизонтальных, вертикальных или диагональных штрихов) или шаблонной, заполняющей область горизонтально и вертикально.

Битовые шаблоны (растровые шаблоны, растровые образы). Битовые шаблоны — это двумерный массив битов, соответствующий пикселям устройства отображения. Это базовый инструмент в растровой графике.
Битовые образы используются, в основном, для отображения сложных (часто из реального мира) изображений на дисплее или принтере. Битовые образы также используются для отображения маленьких картинок, таких как значки, курсоры мыши, кнопки панели инструментов программ, которые нужно быстро нарисовать. GDI поддерживает два типа битовых образов или шаблонов — старые, но все еще используемые, аппаратно-зависимые, являющиеся объектами GDI, и новые (начиная с версии Windows
3.0) аппаратно-независимые (Device Independent Bitmap, DIB), которые могут быть сохранены в файлах на диске.

Текст. Текст отличается от других математических объектов компьютерной графики. Типов текста бесконечно много. Это известно из многолетней истории типографского дела, которое многие считают искусством. Поэтому поддержка текста часто наиболее сложная часть в системах компьютерной графики, и, вместе с тем, наиболее важная. Структуры данных, используемые для описания объектов GDI — шрифтов, а также для получения информации о них — самые большие среди других структур данных в
Windows. Начиная с версии Windows 3.1, GDI поддерживает шрифты TrueType, основанные на закрашенных контурах, которыми могут манипулировать другие функции GDI. Windows 95 из

72 соображений совместимости и экономии памяти по-прежнему поддерживает старые шрифты, основанные на битовых массивах (такие как системный шрифт по умолчанию).
Другие аспекты
Другие аспекты GDI не так легко классифицируются. Это:

Режимы масштабирования и преобразования. Хотя, по умолчанию, вывод задается в пикселях, существуют и другие возможности. Режимы масштабирования GDI позволяют вам рисовать, задавая размеры в дюймах (иногда, в долях дюйма), в миллиметрах, или других удобных вам единицах измерения.
(Windows NT также поддерживает привычное "преобразование пространства", задаваемое матрицей 3
×
3. Это дает возможность нелинейно менять размеры и вращать графические объекты. В Windows 95 это преобразование не поддерживается.)

Метафайлы. Метафайл — это набор вызовов команд GDI, сохраненный в двоичном виде. Метафайлы, в основном, используются для передачи изображений векторной графики через буфер обмена (clipboard).

Регионы. Регион — это сложная область, состоящая из любых фигур, и обычно задаваемая как булева комбинация простых регионов. Регионы, как правило, хранятся внутри GDI как ряды скан-линий, независимо от любой комбинации отрезков, которые могут быть использованы для задания регионов.

Пути. Путь — это набор отрезков и кривых, хранящихся внутри GDI. Они могут использоваться для рисования, закрашивания и при отсечении. Пути могут быть преобразованы в регионы.

Отсечение. Рисование может быть ограничено некоторой областью рабочего пространства окна. Это и называется отсечением, область отсечения может быть прямоугольной или любой другой, какую вы можете описать математически как набор коротких отрезков. Отсечение, как правило, задается регионом или путем.

Палитры. Использование привычных палитр обычно ограничено способностью дисплея показывать не более 256 цветов. Windows резервирует только 20 из этих цветов для использования системой. Вы можете изменять другие 236 цветов для точного отображения красок предметов реального мира как битовые образы.

Печать. Несмотря на то, что эта глава посвящена отображению на экране дисплея, все, чему вы научитесь здесь, относится и к принтерам. (Смотри главу 15, где рассматривается печать.)
Контекст устройства
Перед тем, как начать рисовать, рассмотрим контекст устройства более подробно, чем в главе 3.
Если вы хотите рисовать на устройстве графического вывода (экране дисплея или принтере), сначала надо получить описатель контекста устройства (device context, DC). Передавая этот описатель, Windows тем самым дает вам право на использование самого устройства. Затем вы включаете этот описатель как параметр в функции GDI для того, чтобы сообщить Windows, на каком устройстве вы собираетесь рисовать.
Контекст устройства содержит много текущих атрибутов, определяющих поведение функций GDI при работе с устройством. Эти атрибуты позволяют включать в вызовы функций GDI только начальные координаты или размеры, и ничего больше из того, что требуется для отображения объекта на устройстве. Например, когда вы вызываете функцию TextOut, в ее параметрах вам надо указать только описатель контекста устройства, начальные координаты, сам выводимый текст и его длину. Вам не нужно указывать шрифт, цвет текста, цвет фона и межсимвольное расстояние, потому что эти атрибуты являются частью контекста устройства. Когда вы хотите изменить один из этих атрибутов, вы вызываете функцию, изменяющую значение атрибута в контексте устройства.
Последующие вызовы функции TextOut будут использовать измененные значения атрибутов.
Получение описателя контекста устройства
Windows предоставляет несколько методов для получения описателя контекста устройства. Если вы получаете описатель контекста устройства в теле обработчика сообщения, вы должны освободить его (удалить, вернуть системе) перед выходом из оконной процедуры. После того, как вы освободите описатель контекста устройства, его значение теряет смысл.
Наиболее общий метод получения контекста устройства и его освобождения состоит в использовании функций
BeginPaint и EndPaint при обработке сообщения WM_PAINT: hdc = BeginPaint(hwnd, &ps);
[другие строки программы]

EndPaint(hwnd, &ps);

73
Переменная ps — это структура типа PAINTSTRUCT. Поле hdc этой структуры — это описатель контекста устройства, который возвращается функцией BeginPaint. Структура PAINTSTRUCT содержит также структуру типа RECT с именем rcPaint (прямоугольник), определяющую прямоугольную область, содержащую недействительный (требующий перерисовки) регион клиентской области окна. Получив описатель контекста устройства от функции BeginPaint, вы можете рисовать только в пределах этого региона. Функция BeginPaint делает этот регион действительным.
Программы для Windows могут также получать описатель контекста устройства в теле обработчика сообщения, отличного от WM_PAINT: hdc = GetDC(hwnd);
[другие строки программы]

ReleaseDC(hwnd, hdc);
Полученный контекст устройства с описателем hwnd относится к клиентской (рабочей) области окна. Основная разница между использованием этих функций и комбинации функций BeginPaint и EndPaint состоит в том, что вы можете рисовать в пределах всей рабочей области окна, используя описатель контекста устройства, возвращенный функцией GetDC. Кроме того, функции GetDC и ReleaseDC не делают действительным (не требующим перерисовки) ни один недействительный регион клиентской области окна.
Программы для Windows могут также получать описатель контекста устройства, относящийся ко всему окну программы, а не только к его клиентской области: hdc = GetWindowDC(hwnd);
[другие строки программы]

ReleaseDC(hwnd. hdc);
Этот контекст устройства включает заголовок окна, меню, полосы прокрутки и рамку окна в дополнение к клиентской области. Функция GetWindowDC редко используется в приложениях. Если вы хотите поэкспериментировать с ней, то вам следует обработать сообщение WM_NCPAINT ("nonclient paint", рисование неклиентской области), которое генерируется Windows для перерисовки неклиентской области окна.
Функции BeginPaint, GetDC и GetWindowDC получают контекст устройства, связанный с конкретным окном на экране. Более общая функция для получения описателя контекста устройства — это функция CreateDC: hdc = CreateDC(pszDriver, pszDevice, pszOutput, pData);
[другие строки программы]

DeleteDC(hdc);
Например, вы можете получить описатель контекста устройства всего дисплея так: hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
Запись вне вашего окна обычно не принята, но это удобно для некоторых редко используемых приложений. (Хотя это и не документировано, вы можете получить описатель контекста устройства для экрана дисплея посредством вызова функции GetDC с параметром NULL.) В главе 15 мы будем использовать эту функцию для получения описателя контекста устройства принтера.
Иногда вам нужно только получить некоторую информацию о контексте устройства, и не надо ничего рисовать. В этих случаях вы можете получить описатель так называемого "информационного контекста" (information context), используя функцию CreateIC. Параметры этой функции такие же, как у функции CreateDC, например: hdcInfo = CreateIC("DISPLAY", NULL, NULL, NULL);
[другие строки программы]

DeleteDC(hdcInfo);
Вы не можете осуществлять вывод на устройство, используя информационный контекст.
При работе с битовыми образами иногда может быть полезно получить "контекст памяти" (memory device context): hdcMem = CreateCompatibleDC(hdc);
[другие строки программы]

DeleteDC(hdcMem);
Это достаточно общая концепция. Главное, что вам надо сделать, это выбрать битовый образ в контекст памяти, а затем вызвать функцию GDI для рисования битового образа. Мы обсудим это позднее в данной главе и используем рассмотренную методику в программе GRAFMENU из главы 10.
Как уже упоминалось раньше, метафайл — это набор вызовов GDI в двоичном виде. Вы можете создать метафайл, получая контекст метафайла: hdcMeta = CreateMetaFile(pszFilename);
[другие строки программы]

hmf = CloseMetaFile(hdcMeta);

74
Пока контекст метафайла действителен вызов GDI, который вы осуществляете, используя hdcMeta, не вызывает вывода на устройство, а записывается в метафайл. Когда вы вызываете CloseMetaFile, описатель контекста становится недействительным. Функция возвращает описатель метафайла (hmf

).
Получение информации из контекста устройства
Контекст устройства обычно описывает такие физические устройства как видеотерминалы или принтеры. Часто вам необходимо получить информацию об одном из этих устройств, такую как размер экрана (в терминах пикселей и физических единицах измерения) и его цветовые возможности. Вы можете получить эту информацию посредством вызова функции GetDeviceCaps: iValue = GetDeviceCaps(hdc, iIndex);
Параметр iIndex — один из 28 идентификаторов, определенных в заголовочном файле Windows. Например, значение iIndex равное HORZRES заставляет функцию GetDeviceCaps вернуть ширину устройства в пикселях; значение VERTRES — высоту устройства в пикселях. Если hdc является описателем контекста устройства дисплея, то эту же информацию вы можете получить от функции GetSystemMetrics. Если hdc является описателем контекста устройства принтера, то тогда уже функция GetDeviceCaps возвращает высоту и ширину рабочей области принтера в пикселях.
Вы можете также использовать функцию GetDeviceCaps для определения возможностей устройства по обработке различных типов графики. Это неважно для видеомониторов, но становится очень важным при работе с принтерами. Например, большинство плоттеров не способны отображать битовые образы, и GetDeviceCaps сообщит вам об этом.



Поделитесь с Вашими друзьями:
1   2   3   4   5   6   7   8   9   10   ...   41


База данных защищена авторским правом ©nethash.ru 2019
обратиться к администрации

войти | регистрация
    Главная страница


загрузить материал