Вообще – то на эту тему писали довольно много. Для понимания основных механизмов получения эффектов прозрачности рекомендую прочитать статью Рона Джери "Bitmaps with transparency" (ее можно найти в MSDN в разделе Technical Articles->Multimedia->GDI). Также рекомендую изучить находящиеся там статьи Дейла Роджерсона ("Sprites Make the World Go Round") и Германа Родента ("Animation in Win32").
К сожалению, все эти статьи разделяют общий недостаток – почтенный возраст. Цель данной статьи – показать, что с появлением Windows 95, а затем Windows 98 и Windows 2000 жить программистам стало намного проще (и интереснее!). Все приводимые примеры написаны, для удобства, с использованием библиотеки MFC, но принципы остаются общими.
Windows 95 и списки изображений
С выходом Windows 95 в распоряжении программистов оказалась удобная библиотека Common Controls. В ее составе были не только новые (теперь уже известные всем) элементы управления, но и невизуальный компонент – список изображения (Image List control). Его основное предназначение – содержать набор картинок одинакового размера. Это удобно для применения в разнообразных элементах – например, в панелях инструментов (toolbar).
Нас же больше интересует другая интересная возможность – хранить в списках изображений информацию о прозрачности. Это достигается одним из двух способов:
• Загрузкой растрового изображения с указанием, пикселы какого цвета считать прозрачными;
• Подготовкой специальной маски прозрачности – черно-белого растра, в котором пикселы черного цвета означают прозрачность для соответствующих точек основного растра. При этом маска прозрачности должна иметь такие же размеры, что и основной растр.
Нужно понимать, что в обоих случаях список изображений будет содержать маску прозрачности, просто при первом способе она будет создана за вас. Какой способ избрать – дело вкусов каждого программиста. Я обычно нахожу в палитре какой-нибудь ненужный цвет и назначаю его прозрачным. В большинстве случаев не везет ярко-сиреневому цвету (RGB 255,0,255).
Создание списков прозрачных изображений
Создать список изображения и загрузить в него растр с прозрачностью можно так:
CBitmap m_Bmp;
m_Bmp.LoadBitmap(IDB_BITMAP1);
CImageList imgList;
imgList.Create(cx, cy, ILC_COLOR24|ILC_MASK, 1, 0);
imgList.Add(&m_Bmp, RGB(255, 255, 255));
В приводимых примерах будет предполагаться, что растровые изображения находятся в ресурсах программы и имеют глубину цвета 24 бита (16 млн. цветов). При создании списка необходимо указать размеры загружаемого растра (cx, cy), его цветовой формат (ILC_COLOR24, 16 миллионов оттенков) и признак наличия маски (ILC_MASK). Последние два параметра Create() определяют число хранимых в списке изображений и величину приращения списка при нехватке места. Макрос RGB удобен для указания цвета в 24-битовом диапазоне, в данном случае – цвета прозрачности.
В принципе, загрузить картинку можно и одним вызовом, но этот метод не поддерживает полноцветные изображения (как в нашем примере):
CImageList imgList;
imgList.Create(IDB_BITMAP1, cx, 0, RGB(255,255,255));
По умолчанию, такой растр ограничен 16 цветами.
Рисование с помощью Image List
Для чего списки изображений действительно полезны, так это для облегчения работы по рисованию. Вы вспомните навскидку число и порядок параметров у BitBlt()? А ее неудобство из-за необходимости подготовить дополнительный контекст устройства в памяти? Все это способно смутить не только новичка, но и более опытного программиста.
Ситуация еще более усложняется, когда мы имеем дело с прозрачностью. Необходимо выводить картинку несколько раз с различными параметрами растровых операций (Raster operation, ROP). Каждый раз, когда мы собираемся вывести на экран небольшое изображение космического корабля, необходимо проделать уйму работы.
К счастью, программисты Microsoft уже сделали ее за нас. Можно нарисовать растр, содержащийся в списке изображений, просто вызвав функцию ImageList_Draw(). С использованием MFC этот вызов выглядит, например, так:
imgList.Draw(pDC, 0, m_drawPoint, ILD_TRANSPARENT);
Здесь pDC – указатель на контекст устройства (CDC), 0 – порядковый номер выводимого из списка изображения, m_drawPoint — координаты начала области вывода. Флаг ILD_TRANSPARENT указывает, что вывод нужно осуществлять с учетом маски прозрачности.
Для самых любознательных сообщу, что реализация эффекта прозрачности при этом достигается методом, который Рон Джери называет Black Source Method, т.е., "метод черного источника". Он позволяет выводить изображение с прозрачными участками за два вызова BitBlt() вместо трех, но требует предварительно заменить пикселы, являющиеся прозрачными, черным цветом. Поэтому, загружая растр в список изображений, вы меняете его.
Читать дальше