В системе определены два специальных значения цвета:
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-изображений определяется устройством.
DIB-секция может храниться в любой области памяти, ее размер ограничивается только размером доступной приложению памяти, функции GDI для рисования на таком изображении используют чисто программные алгоритмы, никак не задействуя аппаратный ускоритель. DIB-секция поддерживает различную цветовую глубину и прямой доступ к области памяти, в которой хранится изображение. DIB-секция переносима с одного устройства на другое. BMP-файлы хранят изображение как DIB.
Скорость работы с изображением в формате DIB-секции зависит только от производительности процессора, памяти и качества реализации графических алгоритмов системой (а они, надо сказать, реализованы в Windows очень неплохо). Скорость работы с изображением в формате DDB зависит еще и от драйвера и аппаратного ускорителя видеокарты. Во-первых, аппаратный ускоритель и драйвер могут поддерживать или не поддерживать рисование графических примитивов (в последнем случае эти примитивы рисует система: то, какие операции поддерживает драйвер, можно узнать с помощью функции
GetDeviceCaps
). До недавнего времени была характерной ситуация, когда рисование картинки на DDB-растре и вывод такого растра на экран были заметно (иногда — в два-три раза) быстрее, чем аналогичные операции с DIB-секцией. Однако сейчас разница стала существенно меньше, производительность системы в целом выросла сильнее, чем производительность двумерных аппаратных ускорителей (видимо, разработчики видеокарт больше не считают двумерную графику узким местом и поэтому сосредоточили свои усилия на развитии аппаратных ускорителей 3D-графики). На некоторых мощных компьютерах можно даже столкнуться с ситуацией, когда DDB-изображение отстает по скорости от DIB.
Класс
TBitmap
может хранить изображение как в виде DDB, так и в виде DIB- секции — это определяется значением свойства
PixelFormat
. Значение
pfDevice
означает использование DDB, остальные значения — DIB-секции с различной цветовой глубиной. По умолчанию
TBitmap
создает изображение с форматом
pfDevice
, но программист может изменить формат в любой момент. При этом создается новое изображение требуемого формата, старое копируется в него и уничтожается.
Со свойством
PixelFormat
тесно связано свойство
HandleType
, которое может принимать значения
bmDIB
и
bmDDB
. Изменение свойства
PixelFormat
приводит к изменению свойства
HandleType
, и наоборот.
Примечание
Если вы собираетесь распечатывать изображение, содержащееся в
TBitmap
, то вы должны установкой свойств
PixelFormat
или
HandleType
обеспечить, чтобы изображение хранилось в формате DIB. Попытка вывести DDB-изображение на принтер приводит к непредсказуемым результатам (чаще всего просто ничего не выводится) из-за того, что драйвер принтера не понимает формат, совместимый с видеокартой.