Gdi windows что это

Обновлено: 03.07.2024

GDI+: графика нового поколения

Что же такое GDI+? Официальная документация скромно называет ее Class-based API, то есть основанным на классах интерфейсе прикладных программ. Так как она встроена в Windows XP и .NET Server, ее называют частью этих операционных систем. Часто встречается также определение "библиотека" или "библиотека классов". В действительности, предоставляемый GDI+ набор классов является тонкой оболочкой над множеством обычных функций, реализованных в одной динамической библиотеке GdiPlus.dll . В общем, имея все это в виду, будем для краткости далее называть ее просто библиотекой.

Итак, GDI+ - это библиотека, призванная заменить существующий уже больше 11 (или 18 - как считать) лет интерфейс GDI, являющийся графическим ядром предыдущих версий Windows. Она сочетает в себе (по крайней мере, по замыслу) все достоинства своего предшественника и предоставляет множество новых мощных возможностей. Кроме того, при ее проектировании заранее ставилась цель наименее болезненного переноса приложений на 64-битные платформы. Следовательно, хотя существующие GDI-приложения будут выполняться на новых версиях Windows, для новых проектов следует использовать GDI+.

Заглянем "под капот"

Что новенького?

Далее мы еще будем рассматривать специфические (и такие эффектные!) возможности GDI+. Здесь же только опишем основные новшества.

Достоинства C++ - реализации:

  • Объектно-ориентированный интерфейс: благодаря поддержке компилятора C++ мы "бесплатно" получаем контроль над типами и временем жизни объектов.
  • Прозрачное управление памятью: объекты ядра GDI+ создаются в куче с помощью собственного менеджера памяти прозрачно для программиста.
  • Использование перегрузки имен функций: функции одного назначения различаются только по своим параметрам.
  • Собственное пространство имен: позволяет использовать понятные имена типов - такие, как Rect, Pen и Matrix - без конфликтов с другими библиотеками.
  • Перегрузка операторов: предоставляет удобные операции '+' и '-' для таких типов, как Point и Size.

Архитектурные новинки библиотеки:

  • Аппаратная абстракция: как уже было замечено, упрощается перенос на 64-битные платформы.
  • Новый дизайн графических функций/объектов: теперь можно не бояться "оставить выбранной кисть в контексте перед удалением" - такая типичная для GDI ошибка!
  • Разделение функций закраски и отрисовки: предоставляет большую гибкость в рисовании, например, позволяет заливать незамкнутые фигуры.
  • Появление графических контейнеров: контейнеры позволяют "сцепить" вместе несколько операций и использовать как одну команду.
  • Увеличившаяся поддержка путей (paths) и их взаимодействия с регионами: теперь пути являются полноправными объектами вне контекста рисования и могут легко трансформироваться в регионы.

Новые технологии и возможности (задержите дыхание):

  • Градиентная закраска: позволяет заливать сложные фигуры оттенками с различными законами распределения цвета, рисовать векторные примитивы (например, линии) с градиентной окраской.
  • Поддержка прозрачности: можно создавать кисти и растры с прозрачными и полупрозрачными областями, заливать области полупрозрачным цветом, назначать Color Key для растрового изображения и работать с его альфа-каналом, а также рисовать полупрозрачные (!) векторные примитивы и текст.
  • Режимы улучшения изображения: позволяют значительно улучшить пользовательское восприятие за счет сглаживания контурных неровностей (antialiasing) и префильтрации растровых изображений.
  • Сплайны: кроме уже существующих в GDI кривых Безье, поддерживается новый вид кривых - так называемые сплайны, которые имитируют поведение натянутой и изогнутой стальной полосы. Сплайны являются гладкими кривыми.
  • Пути: как уже говорилось, пути теперь существуют независимо от контекста рисования и представляют собой мощное средство создания сложных векторных объектов. Кроме того, появилась возможность выравнивать (flatten) пути, то есть преобразовывать их к набору отрезков прямых.
  • Координатные преобразования: объект Matrix позволяет осуществлять операции поворота, переноса, масштабирования и отражения объектов GDI+.
  • Регионы: в отличие от GDI, регионы теперь не привязаны к координатам устройства и подчиняются координатным преобразованиям.
  • Работа с растрами: теперь можно практически все! Поддерживается отрисовка растров с наложением внешнего альфа-канала, масштабированием, растяжением, искажением и поворотом растров. При этом можно установить режимы отображения отдельных пикселей - от простого переноса до префильтрации (наилучшее качество изображения). Стало возможным рисовать векторные примитивы, залитые текстурами (!).
  • Поддержка популярных форматов графических файлов: необычайно приятное новшество для всех программистов, имеющих дело с разными графическими форматами. Поддерживаются форматы BMP , GIF , TIFF , JPEG , Exif (расширение TIFF и JPEG для цифровых фотокамер), PNG , ICON , WMF и EMF . Декодеры различных форматов выполнены с учетом их специфики, так что Вы сможете, например, отобразить анимационный GIF или добавить комментарий к TIFF -файлу. Загруженный, созданный или модифицированный файл может быть сохранен на диск в одном из подходящих форматов. Существует возможность написания собственных декодеров.
  • Формат EMF+ : разумеется, все это великолепие не могло уместиться в тесные рамки старого Enhanced Metafile. Для описания новых возможностей был создан новый формат метафайла EMF+, который позволяет сохранить на диск и затем проиграть последовательность графических команд. Существует возможность записать "дуальный" метафайл, понятный старым GDI-программам. Новые программы будут читать из него GDI+ - информацию.

Требования к среде выполнения

В его состав входят только инструкция по установке и уже упомянутая динамическая библиотека GdiPlus.dll, которую необходимо скопировать в системный каталог Windows 98/ME, Windows NT SP6 или Windows 2000. При этом возможности, предоставляемые непосредственно ядром Windows XP (в частности, технология ClearType для качественного отображения шрифтов на LCD-мониторах), будут недоступны.

ПРИМЕЧАНИЕ
Я не случайно не упомянул про Windows 95. На сайте Microsoft отсутствует всяческое упоминание о поддержке GDI+ для этой операционной системы. Тем не менее, единственная доступная мне для тестирования машина с Windows 95 OSR2 выполнила тестовое приложение без каких-либо проблем. Но ввиду отсутствия какой-либо официальной поддержки для использования GDI+ крайне рекомендуется обновить систему хотя бы до Windows 98.

Поддерживаемые технологии разработки

Набор заголовочных файлов (headers) и библиотека импорта GdiPlus.lib, необходимые для сборки демонстрационных приложений, входят в состав последнего Platform SDK. Те, кто до сих пор не обновил идущий с Visual Studio 6.0 Platform SDK образца 1998 года, могут загрузить его с сайта Microsoft по адресу:

Минимальный компонент, в состав которого входит GDI+, называется Windows Core SDK и имеет размер около 230 мегабайт.

ПРИМЕЧАНИЕ
Я понимаю, что для многих читателей, имеющих доступ в Интернет через домашний модем, предложение скачать дистрибутив такого размера прозвучит как насмешка. В качестве крайней временной меры можно раздобыть только набор заголовочных файлов GdiPlus*.h, BaseTsd.h и библиотеку импорта GdiPlus.Lib из нового Platform SDK. Но гарантировать работоспособность такого решения во всех ситуациях я не возьмусь. Да и в любом случае, обновить Platform SDK необходимо. Возможно, вам удастся найти его на CD-ROM.

На момент написания этих строк доступна версия Platform SDK за август 2001 г.

Начинаем работу

Иерархия классов GDI+

Типичное рабочее место программиста на C++, как правило, включает в себя стену, на которой гордо красуется Диаграмма классов (неважно каких). Теперь рядом можно наклеить еще один плакат.

Ниже приведена иерархия классов GDI+. Я не включил в нее 8 структур данных и перечисления (enumerations) - около 50 штук.

При первом взгляде на диаграмму видно, что она очень напоминает, например, ту часть библиотеки MFC, которая отвечает за рисование, только классов гораздо больше (40 против 15 у MFC). Это и неудивительно, учитывая фирму, которая разрабатывала эти библиотеки. Основные отличия отражают новые возможности GDI+. Мы подробно рассмотрим их в следующих частях.

Как видим, большинство объектов имеют в корне иерархии класс GdiPlusBase. Вам не понадобится создавать экземпляры этого класса, так как он содержит только средства управления памятью (для него перегружены операторы new/new[] и delete/delete[], которые используют функции GDI+ GdipAlloc и GdipFree ). Все классы, инкапсулирующие работу с ресурсами GDI+, порождены от GdiPlusBase . Это не значит, что их экземпляры нельзя создавать на стеке - напротив, так даже удобнее контролировать время их жизни. Зато такая архитектура позволит, например, передавать указатель на созданный объект GDI+ в модуль, написанный с использованием других средств разработки, и безопасно его удалять в этом модуле.

Не путайте управление памятью под экземпляры классов-оберток С++, которое осуществляется перегруженными операторами new/delete, и управление собственно ресурсами GDI+, которое скрыто от разработчиков в недрах соответствующих функций, например, GdipCreateSolidFill .

Ключевым же классом в GDI+ является Graphics (программисты на J++ вздрогнули). Именно он содержит почти две сотни методов, отвечающих за рисование, отсечение и параметры устройства вывода. Напрашивается явная аналогия с контекстом устройства (Device Context) прежнего GDI, и эти понятия действительно тесно связаны. Из четырех конструкторов Graphics два создают его из HDC. Главное отличие заключается в изменении программной модели: теперь вы не работаете с хендлом, а вызываете методы класса. Хотя программистам на MFC эта концепция уже хорошо знакома.

Дальнейшее наследование (например, класс TextureBrush порожден от Brush ) скорее отражает цели разработчиков (скрытие деталей реализации и повторное использование оберточного кода), чем инфраструктуру библиотеки, так как в inline-методах "родственных" классов просто содержатся вызовы различных функций GdiPlus.dll. Можно сказать, что Microsoft в очередной раз спроецировала обычный "плоский" API языка C на объектно-ориентированную библиотеку C++.

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

Инициализация и завершение

Перед тем как начать использовать классы и функции GDI+, необходимо инициализировать эту библиотеку. Для этого где-нибудь в начале своей программы нужно поместить вызов функции GdiplusStartup:

Поля структуры GdiplusStartupInput управляют различными аспектами инициализации: в частности, можно задать функцию, которая будет вызываться при возникновении ошибок, или перехватывать все обращения к функциям GDI+. Эти детали мы рассматривать не будем. К счастью, конструктор по умолчанию структуры GdiplusStartupInput выполняет инициализацию, достаточную в большинстве случаев. При этом в качестве выходного параметра output можно задать NULL.

"Магическое значение", на которое указывает выходной параметр token, необходимо сохранить.

Для завершения работы с библиотекой вызовите функцию GdiplusShutdown:

Здесь в качестве параметра и необходимо передать то самое число, которое возвратила GdiplusStartup в параметре token.

Вы можете вызвать GdiplusStartup и GdiplusShutdown из разных потоков, но необходимо убедиться, что вне этой пары функций никакого обращения к объектам GDI+ не происходит. В частности, будьте осторожны, объявляя глобальными экземпляры классов - ведь их деструкторы выполнятся уже после WinMain. Кроме того, как обычно, нельзя вызывать функции инициализации и очистки из DllMain , поскольку это может привести ко входу в бесконечную рекурсию или другим неприятностям.

Создаем первое приложение

Настало время применить все эти сведения на практике. Для этого создадим в MS Visual C++ базовое WINAPI-приложение, которое послужит полигоном для дальнейших экспериментов. Ниже для этого приведена пошаговая процедура.

Итак, создаем новый проект Win32 Application. Выбираем опцию A typical "Hello, World!" application и нажимаем "Finish". Получившееся приложение необходимо подготовить для использования GDI+. Для этого в файле stdafx.h после строки с комментарием:

добавляем следующие строчки:

и в конце файла stdafx.cpp добавляем строку

Кроме того, в файле stdafx.h необходимо удалить или закомментировать строку

Иначе компилятор выдаст кучу ошибок об отсутствии символов MIDL_INTERFACE, PROPID, IStream и т.д.

Если полученное в результате приложение успешно собралось, значит, мы все сделали правильно. Пойдем дальше.

Найдем в сгенерированном основном .cpp файле нашего проекта функцию WinMain и добавим в начале ее код инициализации:

а в конце, перед оператором return , добавим код очистки:

Теперь где-нибудь перед функцией WndProc создадим функцию OnPaint с кодом рисования:

В результате у нас получится примерно вот что:

Приведенный пример носит только ознакомительный характер. В реальном приложении, для того чтобы нарисовать растр, его, как правило, не нужно каждый раз загружать с дискового файла :). Далее я буду пользоваться созданным макетом программы для создания других демонстрационных приложений. В качестве примера рисования будет приводиться только код функции OnPaint .

Пример WinForms - приложения с использованием GDI+

Замечу, что здесь приведен полный текст программы, аналогичной по возможностям той, что мы создали в предыдущем разделе. Сравните объем исходных текстов этих двух примеров. NO COMMENTS.

Если вы запустите приведенный пример, то увидите, что текст отрисовывается без сглаживания, характерного для предыдущего примера. Это связано с тем, что WinForms по умолчанию отключает улучшенный режим отрисовки шрифтов - и без этого причин для торможения достаточно :)

Несколько замечаний о компиляции и сборке проектов

Хочется указать на несколько "подводных камней", которые могут сбить с толку при первой попытке откомпилировать и собрать проект, использующий GDI+. В основном здесь упомянуты те проблемы, с которыми сталкиваются (и постоянно спрашивают о них в различных форумах) начинающие.

Где взять GdiPlus.h?

Как я уже сказал, все заголовочные файлы, библиотека импорта и документация к библиотеке входят в состав последнего Platform SDK. Они не идут в составе Visual С++ 6.0 и его сервис паков.

Почему выдается ошибка о типе ULONG_PTR?

Похоже, что компилятор находит старый заголовочный файл basetsd.h - например, из комплекта VC++. Измените пути поиска заголовочных файлов так, чтобы вначале были найдены файлы Platform SDK.

Почему компилятор не дает создать объект GDI+ при помощи new?

Такое поведение возможно при попытке откомпилировать MFC-приложение с использованием GDI+ в Debug-конфигурации.

В начале файла программы, видимо, имеется следующий фрагмент:

Не забудьте про пространство имен Gdiplus и библиотеку импорта

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

Если это решение не подходит (например, в проекте уже существуют классы с такими именами), то перед именами классов необходимо ставить префикс пространства имен, например

Также, если по каким-то соображениям директива

не устраивает, в опциях компоновщика нужно явно указать библиотеку импорта gdiplus.lib .

На этом пока все. В следующей части мы рассмотрим богатые возможности, которые GDI+ предоставляет для работы с растровыми изображениями.

В 2016 году, когда большинство программ выполняются в песочницах, из которых даже самый некомпетентный разработчик не сможет навредить системе, странно сталкиваться с проблемой, о которой дальше пойдет речь. Если честно, я надеялся, что она ушла в далекое прошлое вместе с Win32Api, но недавно я с ней столкнулся. До этого я лишь слышал жуткие байки старых более опытных разработчиков, что такое может быть.

Проблема

Утечка или использование слишком большого числа GDI объектов.

Симптомы:

Почему?

Как исправлять?

Если Вы живете в аккуратном управляемом CLR’ом мире, то вероятность 9 из 10, что у Вас в приложении обычная утечка памяти. Проблема хоть и неприятная, зато довольно обыденная и есть по меньшей мере дюжина отличных инструментов для ее поиска. Подробно останавливаться на этом не буду. Вам лишь будет нужно использовать любой профилировщик, чтобы посмотреть, не увеличивается ли число объектов-оберток над GDI ресурсами, это: Brush, Bitmap, Pen, Region, Graphics. Если это действительно так, то Вам повезло, можете закрывать вкладку со статьей.

Если не нашлась утечка объектов-оберток, то значит у Вас в коде есть прямое использование функций GDI и сценарий, при котором они не удаляются.

Что Вам будут советовать другие?

Официальное руководство от Microsoft или другие статьи по этому поводу, которые Вы найдете в интернете, будут советовать примерно следующее:

Найти все Create%SOME_GDI_OBJECT% и узнать, есть ли соответствующий ему DeleteObject(или ReleaseDC для HDC-объектов), а если и есть, то, возможно, существует сценарий, при котором он не вызовется.

Есть еще чуть улучшенная версия этого метода, она содержит дополнительный первый шаг:


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

Что предложу я?

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


После чего запустил процесс на отладку в Visual Studio, а здесь выбрал его в дереве процессов. Первая точка останова сработала мгновенно:


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


Задача: Найти те вызовы функций GDI, которым не соответствует удаление. В логи присутствует все необходимое: список вызовов функций в хронологическом порядке, их возвращаемые значения и параметры. Получается, что мне нужно взять возвращаемое значение функции Create%SOME_GDI_OBJECT% и найти вызов DeleteObject с этим значением в качестве аргумента. Я выделил все записи в Api Monitor, вставил в текстовый файл и получил что-то вроде CSV с разделителем TAB. Запустил VS, где думал написать программу, чтобы попарсить это, но, прежде чем она загрузилась, мне пришла в голову идея получше: экспортировать данные в базу и написать запрос, чтобы выгрести то, что меня интересует. Это был правильный выбор, потому что позволил очень быстро задавать вопросы и получать на них ответы.

Есть множество инструментов, чтобы импортировать данные из CSV в базу, потому не буду на этом останавливаться (mysql, mssql, sqlite).

У меня получилась вот такая таблица:


Написал функцию mysql, чтобы получать дескриптор удаляемого объекта из вызова апи:


И наконец запрос, который найдет все текущие объекты:

(Строго говоря, он просто найдет все вызовы Delete на все вызовы Create)



На рисунке сразу видны вызовы, на которые так и не нашлось ни одного Delete.

Остался последний вопрос: Как найти откуда вызываются эти методы в контексте моего кода? И здесь мне помог один хитрый трюк:

  1. Запустить приложение на отладку в VS.
  2. Найти его в Api Monitor и выбрать.
  3. Выбрать нужную функцию Api и поставить точку останова.
  4. Терпеливо нажимать “Далее”, пока она не вызовется с интересующими параметрами. (Как же не хватала conditional breakpoints из vs
  5. Когда дойдете до нужного вызова, перейти в VS и нажать break all.
  6. Отладчик VS будет остановлен в месте, где создается утекающий объект и останется лишь найти, почему он не удаляется.

Резюме:

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

Вот он, для тех кому было лень читать или кто уже забыл с чего все начиналось, пока читал:

GDI (Graphics Device Interface) — один из трёх основных компонентов или «подсистем», вместе с ядром и Windows API, составляющих пользовательский интерфейс (оконный менеджер GDI) Microsoft Windows.

GDI — это интерфейс Windows для представления графических объектов и передачи их на устройства отображения, такие, как мониторы и принтеры.

GDI отвечает за отрисовку линий и кривых, отображение шрифтов и обработку палитры. Он не отвечает за отрисовку окон, меню и т. п., эта задача закреплена за пользовательской подсистемой, располагающейся в user32.dll и основывающейся на GDI. GDI выполняет те же функции, что и QuickDraw в Mac OS.

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

Простые игры, которые не требуют быстрой графики, могут использовать GDI. Однако GDI не обеспечивает качественной анимации, поскольку в нём нет возможности синхронизации с кадровым буфером. Также в GDI нет растеризации для отрисовки 3D-графики. Современные игры используют DirectX или OpenGL, что даёт программистам доступ к большему количеству аппаратных возможностей. [Источник 1]

Содержание

Поддерживаемые операции

GDI поддерживает следующие операции рисования:

  1. установку определенного цвета в конкретном пикселе;
  2. рисование линии с учетом характеристик толщины, шаблона, цвета и стиля кисти;
  3. рисование дуги;
  4. рисование эллипса (окружности);
  5. рисование прямоугольника, прямоугольника со скругленными углами или многоугольника;
  6. рисование замкнутых фигур, заполненных сплошным цветом или шаблоном;
  7. рисование текста с указанным шрифтом, цветом и размером;
  8. перемещение прямоугольника по экрану, возможно, с изменением размеров;
  9. ограничение операций рисования или операций перемещения в определенной области, чтобы не затрагивать изображение за пределами этой области. [Источник 2]

Контекст устройства

Контекст устройства (Device context) - это то место, куда рисуется графика, плюс средства рисования графики. Можно получить контекст устройства окна и после этого рисовать что-то в этом окне. Можно получить контекст устройства принтера и рисовать фигуры на печатаемой странице. Контекст устройства позволяет использовать кисти (brushes), перья (pens), картинки (bitmaps) для вывода графики.

Получение контекста устройства окна

Для получения контекста устройства окна используется описатель окна (HWND). Контекст устройства представлен в программе переменной типа HDC - переопределённый указатель на void. Для получения контекста устройства окна используется функция getDC:

После этого можно использовать переменную hDC для рисования в окне hWnd. После завершения рисования, нужно "отпустить" контекст устройства с помощью функции ReleaseDC .

Функция Rectangle принимает следующие аргументы: контекст устройства, координаты левого верхнего угла, координаты правого нижнего угла.

Функция TextOut принимает аргументы: контекст устройства, координаты левого верхнего угла текста, текстовая строка, количество символов в текстовой строке.

Функция Release принимает аргументы: окно, контекст устройства.

Вывод графики в нескольких окнах

Когда заполняется структура WNDCLASS, чтобы зарегистрировать класс окна программы в Windows, заполняется поле style:

Данное поле задаёт стиль класса окон. Значение CS_OWNDC говорит, что для каждого окна данного класса будет создан свой контекст устройства. [Источник 3]

Типы контекста устройства

В GDI существуют пять типов контекста устройства:

  • связанный с дисплеем (Display DC)
  • принтером (Printer DC)
  • контекст виртуального устройства в памяти (Memory DC)
  • контекст Metafile DC
  • специальный вид контекста - информационный (Information DC).

Первые четыре типа контекста устройства - display, printer, memory и metafile предоставляют унифицированный интерфейс для вывода графической информации на разнотипные устройства, освобождая приложение (и его разработчика) от необходимости заботится о том, куда именно производится вывод графики. Информационный контекст для вывода графики не используется, он служит исключительно для получения информации о параметрах и поддерживаемых режимах устройства, с которым связан.

В чем отличие первых четырех типов контекста? Это можно понять из их названий - Display DC служит для вывода на экран, Printer DC для печати на принтер или графопостроитель, Memory DC служит для создания растровых изображений в памяти с возможностью быстрого их копирования в другие типы контекстов (и обратно), Metafile DC нужен для вывода графики в метафайл. Метафайл - это хранилище последовательности команд GDI, каждая из которых описывает одну графическую функцию. В отличие от растровых файлов, хранящих графическую информацию непосредственно в виде массива пикселов, метафайл ее хранит в виде последовательности команд, которая создает результирующий рисунок. [Источник 4]

Регионы Windows

Для повышения эффективности работы Windows оперирует с несколькими типами регионов. Идея заключается в том, чтобы рисовать именно в той части окна, которая требует обновления, а не перерисовывать все окно. Также регионы позволяют отсекать вывод той части графической информации, которая не может быть отображена в данный момент. Вообще полное изучение всей иерархии регионов и их взаимодействия является непростой задачей, требующей пространного из ложения1. В то же время приведенное ниже упрощенное описание достаточно для понимания работы большинства функций Win32 GDI.

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

Видимый регион (visible region) — та часть окна, которую в данный момент видит пользователь. Система изменяет видимый регион окна и в том случае, когда окно изменяет размеры, и в том случае, когда перемещение другого окна либо закрывает часть данного окна, либо открывает закрытую прежде часть.

Регион отсечения (clipping region) ограничивает область, внутри которой система разрешает отображение графической информации. Когда приложение получает контекст устройства при помощи функции BeginPaint, система устанавливает регион отсечения путем пересечения видимого региона и обновляемого региона. Приложение может ужесточить регион отсечения и ввести дополнительные ограничения при помощи вызова функции SetWindowRgn, SelectClipPath или SelectClipRgn.

Если при создании окна функцией CreateWindow был использован стиль WS_CLIPCHILDREN или WS_CLIPSIBLINGS, то это вносит дополнительные правила в определение видимого региона, исключая из него любое дочернее или любые «сестринские» окна. Благодаря этому рисование не затрагивает отображаемые области таких окон.

GDI принтеры

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

Non-GDI принтеры требуют аппаратные средства, оборудование и память для рендеринга страницы; принтер GDI использует ЭВМ для этого, что делает его дешевле в производстве, чем подобные Non-GDI принтеры. Некоторые производители выпускают, по сути, один и тот же принтер в версиях, совместимых с языком управления принтера, такие как PCL или PostScript, и дешевле GDI-only версия.

Принтер с собственным языком управления может принимать входные данные от любого устройства с подходящим драйвер; для принтера GDI требуется ПК с операционной системой Windows. В общем принтеры GDI не совместимы с аппаратными принт-серверами, хотя некоторые серверы имеют встроенные возможности обработки, что делает их совместимыми с принтерами GDI. [Источник 5]

Применение кода GDI+ для прорисовки графики - это более медленный процесс, чем использование файла статического изображения. Однако этот метод обеспечивает значительно большую свободу и предоставляет несколько возможностей, которые были недоступны (или являлись недопустимо сложными) в предшествующих платформах разработки веб-приложений, таких как классическая ASP. Например, можно генерировать графические элементы, которые используют специфичную для пользователя информацию, и визуализировать диаграммы и графики в соответствии с записями базы данных. [Источник 6]

GDI+ является улучшенной средой для 2D-графики, в которую добавлены такие возможности, как сглаживание линий (antialiasing), использование координат с плавающей точкой, градиентная заливка, возможность работы изнутри с такими графическими форматами, как JPEG и PNG, куда лучшая реализация регионов отсечения с возможностью использовать в них координаты с плавающей точкой (а не 16-битные целые) и применения к ним World Transform, преобразования двумерных матриц и т. п. GDI+ использует ARGB-цвета. Эти возможности используются в пользовательском интерфейсе Windows XP, а их присутствие в базовом графическом слое облегчает использование систем векторной графики, таких, как Flash или SVG.

Динамические библиотеки GDI+ могут распространяться вместе с приложениями для использования в предыдущих версиях Windows.

GDI+ схож с подсистемой Quartz 2D у Apple и библиотеками с открытым кодом libart и Cairo.

GDI+ есть не более чем набор обёрток над обычной GDI. В Windows 7 появился новый API Direct2D, который есть примерно то же, но реализован «сверху донизу» вплоть до драйвера видеокарты (точнее, использует некие возможности Direct3D в этом драйвере), и может использовать аппаратное ускорение — то есть видеопроцессор трёхмерной графики для рисования некоторых двухмерных объектов (antialiasing и т. д.)

Уязвимости

14 сентября 2004 года была обнаружена уязвимость в GDI+ и других графических API, связанная с ошибкой в коде библиотеки JPEG. Эта ошибка позволяла выполнить произвольный код на любой системе Windows. Патч для исправления уязвимости был выпущен 12 октября 2004 года. [Источник 7]

Наиболее значительными преимуществами GDI по сравнению с более прямыми методами доступа к оборудованию, возможно, являются его возможности масштабирования и абстрактное представление целевых устройств. Используя GDI, можно рисовать на нескольких устройствах, таких как экран и принтер, и ожидать надлежащего воспроизведения в каждом случае. Эта возможность лежит в основе большинства приложений Microsoft Windows « Что видишь, то и получаешь ».

Простые игры, не требующие быстрой отрисовки графики, могут использовать GDI. Однако GDI относительно сложно использовать для расширенной анимации, в нем отсутствует понятие синхронизации с отдельными видеокадрами на видеокарте и отсутствует аппаратная растеризация для 3D. Современные игры обычно используют DirectX , Vulkan или OpenGL .

СОДЕРЖАНИЕ

Технические подробности

В GDI контекст устройства (DC) определяет атрибуты текста и изображений для устройства вывода, например экрана или принтера. GDI поддерживает актуальный контекст. Для генерации вывода требуется дескриптор контекста устройства (HDC). После генерации вывода ручку можно было отпустить.

GDI использует алгоритм рисования линий Брезенхэма для рисования линий с псевдонимом.

История версий

Ранние версии

GDI присутствовал в первом выпуске Windows. Программы MS-DOS до сих пор управляли графическим оборудованием, используя программные прерывания (иногда через Video BIOS ) и напрямую управляя видеопамятью . Код, написанный таким образом, предполагает, что это единственный пользователь видеопамяти, что было неприемлемо в многозадачной среде , такой как Windows. Журнал BYTE в декабре 1983 года обсуждал планы Microsoft относительно системы вывода графики на принтеры и мониторы с одним и тем же кодом в предстоящем первом выпуске Windows.

Windows XP

Хотя GDI + входит в состав Windows XP и более поздних версий, динамическая библиотека GDI + также может поставляться с приложением и использоваться в более старых версиях Windows.

Из-за дополнительных возможностей обработки текста и независимости от разрешения в GDI + центральный процессор выполняет рендеринг текста. Результат на порядок медленнее, чем GDI с аппаратным ускорением . Крис Джексон опубликовал несколько тестов, показывающих, что написанный им фрагмент кода визуализации текста может отображать 99 000 глифов в секунду в GDI, но тот же код, использующий GDI +, отображает 16 600 символов в секунду.

GDI + похож (по назначению и структуре) на подсистему Apple QuickDraw GX , а также библиотеки libart и Cairo с открытым исходным кодом .

Виндоус виста

В Windows Vista все приложения Windows, включая приложения GDI и GDI +, запускаются в новом механизме композитинга, Desktop Window Manager (DWM), который имеет аппаратное ускорение. Таким образом, GDI больше не имеет аппаратного ускорения. Из-за характера операций композиции перемещение окон может быть более быстрым или более быстрым, поскольку приложение не требует повторной визуализации базового содержимого.

Windows 7

Windows 7 включает аппаратное ускорение GDI для операций копирования в Windows Display Driver Model v1.1 . Это улучшает производительность GDI и позволяет DWM использовать локальную видеопамять для компоновки, тем самым уменьшая объем системной памяти и повышая производительность графических операций. Большинство примитивных операций GDI по-прежнему не имеют аппаратного ускорения, в отличие от Direct2D . GDI + продолжает полагаться на программный рендеринг в Windows 7.

Принтеры GDI

Принтер GDI или Winprinter (аналог Winmodem ) - это принтер, предназначенный для приема вывода с главного компьютера под управлением Windows. Главный компьютер выполняет всю обработку печати: GDI отображает страницу как растровое изображение, которое драйвер принтера получает, обрабатывает и отправляет на связанный принтер. Комбинация GDI и драйвера является двунаправленной; они получают информацию от принтера, например, готов ли он к печати или закончилась бумага.

Принтеры, которые не полагаются на GDI, требуют оборудования, микропрограмм и памяти для рендеринга страниц, в то время как принтер GDI использует для этого главный компьютер. Однако принтер с собственным языком управления может принимать ввод от любого устройства с подходящим драйвером, в то время как для принтера GDI требуется ПК под управлением Windows. Принтеры GDI можно сделать доступными для компьютеров в сети, если они подключены как общие принтеры на компьютере, который включен и работает под управлением Windows. pnm2ppa Были написаны некоторые "общие" драйверы GDI ; они стремятся сделать принтеры GDI совместимыми с операционными системами, отличными от Windows, такими как FreeBSD , но они не могут поддерживать все принтеры.

Чтобы упростить создание драйверов для Winprinters, был создан универсальный драйвер принтера Microsoft . Это позволяет поставщикам принтеров писать «минидрайверы» общего описания принтера (GPD), которые описывают возможности принтера и набор команд в виде открытого текста, вместо того, чтобы заниматься разработкой драйверов для режима ядра.

Microsoft отошла от этой модели печати с помощью спецификации Open XML Paper .

Ограничения

Каждое окно потребляет объекты GDI. По мере увеличения сложности окна с дополнительными функциями, такими как кнопки и изображения, также увеличивается использование его объекта GDI. Когда используется слишком много объектов, Windows не может рисовать больше объектов GDI, что приводит к некорректной работе программного обеспечения и зависанию и зависанию работы программы. Многие приложения также неправильно закодированы и не могут освободить объекты GDI после использования, что еще больше усугубляет проблему. Общее количество доступных объектов GDI варьируется от одной версии Windows к другой: Windows 9x имела ограничение в 1200 общих объектов; Windows 2000 имеет ограничение в 16 384 объекта; и Windows XP и более поздние версии имеют настраиваемый предел (через реестр), который по умолчанию составляет 10 000 объектов на процесс (но теоретический максимум 65 536 для всего сеанса). Windows 8 и более поздние версии увеличивают ограничение объекта GDI до 65 536 за сеанс входа в систему.

Более ранние версии Windows, такие как Windows 3.1 и Windows 98, включали программу Resource Meter, позволяющую пользователю отслеживать, какая часть общих ресурсов GDI системы используется. Этот счетчик ресурсов сам потреблял объекты GDI. Более поздние версии, такие как Windows 2000 и Windows XP, могут сообщать об использовании объекта GDI для каждой программы в диспетчере задач, но они не могут сообщить пользователю общую доступную емкость GDI.

Переполнение емкости GDI может повлиять на саму Windows, препятствуя открытию новых окон, отображению меню и появлению окон предупреждений. Ситуация может быть трудной для устранения и потенциально может потребовать принудительного сброса системы, поскольку это препятствует работе основных системных программ. В Windows 8 и 8.1 вместо перезагрузки происходит принудительный выход из системы в результате переполнения емкости GDI.

Читайте также: