GDI предоставляет очень интересные возможности по преобразованию координат, но только в Windows NT/2000/XP; в Windows 9x/ME они не поддерживаются. С помощью функции
SetWorldTransform
можно задать произвольную матрицу преобразования координат, и все дальнейшие графические операции будут работать в новой координатной системе. Матрица позволяет описать такие преобразования координат, как поворот, сдвиг начала координат и масштабирование, т.е. возможности открываются очень широкие. Также существует менее гибкая, но тоже полезная функция преобразования координат —
SetMapMode
, которая поддерживается во всех версиях Windows. С ее помощью можно установить такую систему координат, чтобы во всех функциях задавать координаты, например, в миллиметрах, а не пикселах. Это позволяет использовать один и тот же код для вывода на устройства с разными разрешениями.
Некоторые возможности GDI, которым нет аналогов в
TCanvas
, демонстрируются примером GDI Draw.
Для задания
цвета в GDI предусмотрен тип
COLORREF
(в модуле Windows определен также его синоним для Delphi —
TColorRef
). Это 4-байтное беззнаковое целое, старший байт которого определяет формат представления цвета. Если этот байт равен нулю (будем называть этот формат нулевым), первый, второй и третий байты представляют собой интенсивности красного, зеленого и синего цветов соответственно. Если старший байт равен 1, два младших байта хранят индекс цвета в текущей палитре устройства, третий байт не используется и должен быть равен нулю. Если старший байт равен 2, остальные байты, как и в нулевом формате, показывают интенсивность цветовых составляющих.
Тип
TColorRef
позволяет менять глубину каждого цветового канала от 0 до 255, обеспечивая кодирование 16 777 216 различных оттенков (это соответствует режиму
TrueColor
). Если цветовое разрешение устройства невелико, GDI подбирает ближайший возможный цвет из палитры. Если старший байт
TColorRef
равен нулю, цвет выбирается из текущей системной палитры (по умолчанию эта палитра содержит всего 20 цветов, поэтому результаты получаются далекими от совершенства). Если же старший байт равен 2, то GDI выбирает ближайший цвет из палитры устройства. В этом случае результаты получаются более приемлемыми. Если устройство имеет большую цветовую глубину и не задействует палитру, разницы между нулевым и вторым форматом
COLORREF
нет.
Примечание
Хотя режимы HighColor (32 768 или 65 536 цветов) не обладают достаточной цветовой глубиной, чтобы передать все возможные значения
TColorRef
, палитра в этих режимах не используется и ближайший цвет выбирается не из палитры, а из всех цветов, которые способно отобразить устройство. Поэтому выбор нулевого формата в этих режимах дает хорошие результаты.
В Windows API определены макросы (а в модуле
Windows
, соответственно, одноименные функции)
RGB
,
PaletteIndex
и
PaletteRGB
.
RGB
принимает три параметра — интенсивности красного, зеленого и синего компонентов и строит из них значение типа
TColorRef
нулевого формата.
PaletteIndex
принимает в качестве параметра номер цвета в палитре и на его основе конструирует значение первого формата. Макрос
PaletteRGB
эквивалентен
RGB
, за исключением того, что устанавливает старший байт возвращаемого значения равным двум. Для извлечения интенсивностей отдельных цветовых компонентов из значения типа
TColorRef
можно воспользоваться функциями
GetRValue
,
GetGValue
и
GetBValue
.
В системе определены два специальных значения цвета:
CLR_NONE
(
$1FFFFFFF
) и
CLR_DEFAULT
(
$20000000
). Они используются только в списках рисунков (image lists) для задания фонового и накладываемого цветов при выводе рисунка.
CLR_NONE
задаёт отсутствие фонового или накладываемого цвета (в этом случае соответствующий визуальный эффект не применяется).
CLR_DEFAULT
— установка цвета, заданного для всего списка.
В VCL для передачи цвета предусмотрен тип
TColor
, определенный в модуле
Graphics
. Это 4-байтное число, множество значений которого является множеством значений типа
TColorRef
. К системным форматам 0, 1 и 2 добавлен формат 255. Если старший байт значения типа
TColor
равен 255, то младший байт интерпретируется как индекс системного цвета (второй и третий байт при этом не учитываются). Системные цвета — это цвета, используемые системой для рисования различных элементов интерфейса пользователя. Конкретные RGB-значения этих цветов зависят от версии Windows и от текущей цветовой схемы. RGB-значение системного цвета можно получить с помощью функции
GetSysColor
. 255-й формат TColor освобождает от необходимости явного вызова данной функции.
Для типа TColor определен ряд констант, облегчающих его использование. Некоторые из них соответствуют определенному RGB-цвету (
clWhite
,
clBlack
,
clRed
и т.п.), другие — определенному системному цвету (
clWindow
,
clHighlight
,
clBtnFace
и т.п.). Значения RGB-цветов определены в нулевом формате. Это не приведет к потере точности цветопередачи в режимах
с палитрой, т.к. константы определены только для 16-ти основных цветов, которые обязательно присутствуют в системной палитре. Значениям
CLR_NONE
и
CLR_DEFAULT
соответствуют константы
clNone
и
clDefault
. Они служат (помимо списков рисунков) для задания прозрачного цвета в растровом изображении. Если этот цвет равен
clNone
, изображение считается непрозрачным, если
clDefault
, в качестве прозрачного цвета берется цвет левого нижнего пиксела.
Везде, где требуется значение типа TColor, можно подставлять
TColorRef
, т.е. всем свойствам и параметрам методов класса
TCanvas
, имеющим тип
TColor
можно присваивать те значения
TColorRef
, которые сформированы функциями API. Обратное неверно: API-функции не умеют обращаться с 255-м форматом
TColor
. Преобразование из
TColor
в
TColorRef
осуществляется с помощью функции
ColorToRGB
. Значения нулевого, первого и второго формата, а также
clNone
и
clDefault
она оставляет без изменения, а значения 255-го формата приводит к нулевому с помощью функции
GetSysColor
. Эту функцию следует использовать при передаче значении типа
TColor
в функции GDI.
Применение кистей, перьев и шрифтов в GDI принципиально отличается от того, как это делается в VCL. Класс
TCanvas
имеет свойства
Pen
,
Brush
, и
Font
, изменение свойств которых приводит к выбору того или иного пера, кисти, шрифта. В GDI эти объекты самостоятельны, должны создаваться, получать свой дескриптор, "выбираться" в нужный контекст устройства с помощью функции
SelectObject
и уничтожаться после использования. Причем удалять можно только те объекты, которые не выбраны ни в одном контексте. Есть также несколько стандартных объектов, которые не нужно ни создавать, ни удалять. Их дескрипторы можно получить с помощью функции
GetStockObject
. Для примера рассмотрим фрагмент программы, рисующей на контексте с дескриптором DC две линии: синюю и красную (листинг 1.18). В этом фрагменте используется то, что функция
SelectObject
возвращает дескриптор объекта, родственного выбираемому, который был выбран ранее. Так, при выборе нового пера она вернет дескриптор того пера, которое было выбрано до этого.
Листинг 1.18. Рисование разными перьями с использованием GDI
Дескрипторы объектов GDI имеют смысл только в пределах того процесса, который их создал, передавать их между процессами нельзя. Тем не менее изредка можно встретить утверждения, что такая передача возможна. Источник этой ошибки в том. что дескрипторы объектов GDI можно было передавать между процессами в старых, 16-разрядных версиях Windows, так что все утверждения о возможности такой передачи просто основываются на устаревших сведениях.
Для хранения растровых изображений в Windows существуют три формата: DDB, DIB и DIB-секция. DDB — это Device Dependent Format, формат, определяемый графическим устройством, на которое идет вывод. DIB — это Device Independent Bitmap, формат, единый для всех устройств. Формат DIB — это устаревший формат, который не позволяет использовать графические функции GDI для модификации картинки, модифицировать изображение можно, только одним способом: вручную изменяя цвета отдельных пикселов. В 32-разрядных версиях появился еще один формат — DIB-секция. По сути дела это тот же самый DIB, но дополненный возможностями рисовать на нем с помощью GDI-функций. Все различия между этими тремя форматами можно прочитать в замечательной книге [1]; мы же здесь ограничимся только кратким их обзором.
Формат DDB поддерживается самой видеокартой (или другим устройством вывода), поэтому при операциях с таким изображением задействуется аппаратный ускоритель графики. DDB-изображение хранится в выгружаемом системном пуле памяти (Windows NT/2000/XP) или в куче GDI (Windows 9x/ME). При этом размер DDB-растра не может превышать 16 Мбайт в Windows 9x/ME и 48 Мбайт в Windows NT/2000/XP. Формат DDB не переносим с одного устройства на другое, он должен использоваться только в рамках одного устройства. Прямой доступ к изображению и его модификация вручную невозможны, т.к. формат хранения изображения конкретным устройством непредсказуем. Модифицировать DDB можно только с помощью функций GDI. Цветовая глубина DDB-изображений определяется устройством.