Использование TrueColor иконок в программе
Написанный ниже текст предназначен только для Windows XP (и ее продолжений)
Строго говоря, в этой статье описываются приемы работы с обновленным элементом библиотеки common controls 6.0 ImageList для обеспечения XP-интерфейса с использованием 32-битных битмапов.
Q: Что такое 32-битные картинки?
A: Для обеспечения нового интерфейса, в Windows XP были введены 32-битные изображения. По структуре они аналогичны битмапам типа TrueColor с 24-битным цветом. Однако, в них "базовая тройка" цветов каждой четырехбайтовой структуры RGBr (R - красный, G - зеленый, B - синий, r - резервный байт), описывающей точку в 24-х битных битмапах, заменена "базовой четверкой" RGBA, где резервный байт заменен действующим байтом, обозначающим т.н. "альфа-канал", т.е. этот байт обозначает прозрачность выбранной точки. При этом, значение 0x00 означает полностью прозрачную точку, а 0xFF - полностью непрозрачную точку.
Для обеспечения этой самой прозрачности в элемент ImageList библиотеки common controls Windows были внесены изменения. Однако эти самые изменения были внесены только в последнюю, шестую версию этой библиотеки. Для ее подключения к программе в Windows XP используется манифест.
- Как же использовать все эти нововведения в своей программе, - спросите вы.
Для начала нужно создать этот самый имаджлист.
Создание имаджлиста
При использовании Windows API нужно использовать функцию ImageList_Create
Вариант 1. Мы используем в качестве изображения 32-х битную иконку.
В этом случае все просто - можно смело ставить в качестве параметов "ILC_COLOR32 | ILC_MASK", т.к. иконки всегда используют для отрисовки изображения маску.
Т.е. в этом случае можно написать (для иконок формата 16x16):
Этот случай немного сложнее. Однако, этого достаточно, чтобы его использовал в своих программах только Microsoft. На момент написания статьи (август 2002 года) я не видел ни одной программы, использующей 32-битные битмапы. Везде, изображения используются только в виде иконок.
Небольшое отступление. Обычно, битмапы при использовании в качестве изображений с использованием в качестве маски какого-либо цвета, которым закрашивается фон картинки. Обычно используется цвет Magenta - RGB(255, 0, 255), хотя можно использовать и любой другой.
В случае использования 32-х битных битмапов, маска абсолютно не нужна. Однако, вследствие того, что существуют режимы экрана, отличные от TrueColor, придется использовать два вида битмапов: с использованием цветовой маски и без нее. Поэтому, необходимо ввести функцию, проверяющую количество цветов экрана и, заодно, версию операционной системы. Вот они:
Таким образом, создание имаджлиста выливается в следующий код:
Теперь, после того, как мы создали имаджлист с нужными параметрами, надо добавить в него эти самые изображения. Продолжим разбиение на два варианта (какие это варианты, см. выше)
Вариант 1: Вот здесь-то и проявляется неудобство этого варианта для использования иконок в качестве, скажем, изображений для панели инструментов (toolbar), содержащей порой до нескольких десятков кнопок: каждую иконку надо загружать в имаджлист отдельной командой!
Приведу пример для загрузки трех иконок. В нем использована MFC. Для использования этого кода в чистом API надо заменить "m_ImageList.Add" на "ImageList_AddIcon":
Заметьте, что в этом случае иконки получают номера от нуля до двух.
Вариант 2: Несмотря на навороченное создание имаджлиста для этого варианта, все изображения сразу загружаются одной командой. Однако, при этом надо иметь как минимум два битмапа: один для варианта TrueColor с 32-х битным цветом и еще один - для варианта 256 и HiColor - цветных режимов.
При добавлении изображения в имаджлист необходимо помнить, что в случае 32-х битных изображений у нас в битмапе отсутствует маска и надо загрузить его соответствующим образом:
Ну, вот в общем-то и все. Надеюсь, что я прояснил еще один вопрос, возникающий при программировании для Windows XP. Удачного программирования.
Строго говоря, в этой статье описываются приемы работы с обновленным элементом библиотеки common controls 6.0 ImageList для обеспечения XP-интерфейса с использованием 32-битных битмапов.
Q: Что такое 32-битные картинки?
A: Для обеспечения нового интерфейса, в Windows XP были введены 32-битные изображения. По структуре они аналогичны битмапам типа TrueColor с 24-битным цветом. Однако, в них "базовая тройка" цветов каждой четырехбайтовой структуры RGBr (R - красный, G - зеленый, B - синий, r - резервный байт), описывающей точку в 24-х битных битмапах, заменена "базовой четверкой" RGBA, где резервный байт заменен действующим байтом, обозначающим т.н. "альфа-канал", т.е. этот байт обозначает прозрачность выбранной точки. При этом, значение 0x00 означает полностью прозрачную точку, а 0xFF - полностью непрозрачную точку.
Для обеспечения этой самой прозрачности в элемент ImageList библиотеки common controls Windows были внесены изменения. Однако эти самые изменения были внесены только в последнюю, шестую версию этой библиотеки. Для ее подключения к программе в Windows XP используется манифест.
- Как же использовать все эти нововведения в своей программе, - спросите вы.
Для начала нужно создать этот самый имаджлист.
Создание имаджлиста
При использовании Windows API нужно использовать функцию ImageList_Create
ImageList_Create(x, y, Константа_ILC_*, 0, 0);при использовании MFC это же самое создание будет выглядеть так:
CImageList m_ImageList;В данных примерах используется странный параметр - "Константа ILC_*" он означает, что здесь, в зависимости от нужд программы (и программиста) используются разные значения. А нужд у нас с вами может быть (аж!) целых два варианта.
m_ImageList.Create(x, y, Константа_ILC_*, 0, 0);
Вариант 1. Мы используем в качестве изображения 32-х битную иконку.
В этом случае все просто - можно смело ставить в качестве параметов "ILC_COLOR32 | ILC_MASK", т.к. иконки всегда используют для отрисовки изображения маску.
Т.е. в этом случае можно написать (для иконок формата 16x16):
ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 0, 0);Вариант 2. Мы используем в качестве изображения 32-х битный битмап.
Этот случай немного сложнее. Однако, этого достаточно, чтобы его использовал в своих программах только Microsoft. На момент написания статьи (август 2002 года) я не видел ни одной программы, использующей 32-битные битмапы. Везде, изображения используются только в виде иконок.
Небольшое отступление. Обычно, битмапы при использовании в качестве изображений с использованием в качестве маски какого-либо цвета, которым закрашивается фон картинки. Обычно используется цвет Magenta - RGB(255, 0, 255), хотя можно использовать и любой другой.
В случае использования 32-х битных битмапов, маска абсолютно не нужна. Однако, вследствие того, что существуют режимы экрана, отличные от TrueColor, придется использовать два вида битмапов: с использованием цветовой маски и без нее. Поэтому, необходимо ввести функцию, проверяющую количество цветов экрана и, заодно, версию операционной системы. Вот они:
BOOL IsWinXP()И, наконец третья функция, объединяющая первые две:
{
// Проверка операционной системы
DWORD dwVersion = GetVersion();
// Get major and minor version numbers of Windows
DWORD dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
DWORD dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
// Check for Windows XP
if ((dwVersion < 0x80000000) && // The OS is a NT family
(dwWindowsMajorVersion >= 5) &&
(dwWindowsMinorVersion >= 1)) // Windows NT 5.1 is an Windows XP version
return TRUE;
return FALSE;
}
int ScreenBPP()
{
// Возвращает количество битов на точку в данном режиме
int iRet;
HDC hdc = GetDC(NULL);
if (hdc != NULL)
{
iRet = GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(NULL, hdc);
}
return iRet;
}
BOOL Set32BPP()Соответственно, если мы работаем в режиме TrueColor и в Windows XP мы используем 32-х битный битмап, а если нет - то, скажем, 256-цветный аналог.
{
return (IsWinXP() & (ScreenBPP() >= 32));
}
Таким образом, создание имаджлиста выливается в следующий код:
ImageList_Create(16, 16, (Set32BPP())? 0 : ILC_MASK) | ILC_COLOR32, 0, 0);Добавление изображения в созданный имаджлист.
Теперь, после того, как мы создали имаджлист с нужными параметрами, надо добавить в него эти самые изображения. Продолжим разбиение на два варианта (какие это варианты, см. выше)
Вариант 1: Вот здесь-то и проявляется неудобство этого варианта для использования иконок в качестве, скажем, изображений для панели инструментов (toolbar), содержащей порой до нескольких десятков кнопок: каждую иконку надо загружать в имаджлист отдельной командой!
Приведу пример для загрузки трех иконок. В нем использована MFC. Для использования этого кода в чистом API надо заменить "m_ImageList.Add" на "ImageList_AddIcon":
HICON m_hImage;
int n_Index;
// Добавляем иконки в имаджлист
m_hImage = LoadIcon(NULL, IDI_ICON1);
n_Index = m_ImageList.Add(m_hImage); // Иконка №0
m_hImage = LoadIcon(NULL, IDI_ICON2);
n_Index = m_ImageList.Add(m_hImage); // Иконка №1
m_hImage = LoadIcon(NULL, IDI_ICON3);
n_Index = m_ImageList.Add(m_hImage); // Иконка №2
Заметьте, что в этом случае иконки получают номера от нуля до двух.
Вариант 2: Несмотря на навороченное создание имаджлиста для этого варианта, все изображения сразу загружаются одной командой. Однако, при этом надо иметь как минимум два битмапа: один для варианта TrueColor с 32-х битным цветом и еще один - для варианта 256 и HiColor - цветных режимов.
// Загружаем битмапыВ этом случае, вы загружаете сразу столько изображений, сколько вам позволят ограничения системы.
CBitmap m_Bitmap;
if (Set32BPP())
m_Bitmap.LoadBitmap(IDB_BITMAPXP32);
else
m_Bitmap.LoadBitmap(IDB_BITMAP256);
При добавлении изображения в имаджлист необходимо помнить, что в случае 32-х битных изображений у нас в битмапе отсутствует маска и надо загрузить его соответствующим образом:
if (Set32BPP())Опять-таки, в случае написания программы на чистом API код видоизменяется. Приведу его без разрыва на комментарий:
m_ImageList.Add(&m_ImageList, &m_ImageList);
else
m_ImageList.Add(&m_ImageList, RGB(255, 0, 255));
// Загружаем битмапыТеперь, для воспроизведения изображения нужно либо самим воспользоваться функциями прорисовки изображения, входящими в имаджлист, либо передать указатель (на класс имаджлиста в случае MFC) или хендл на сам имаджлист (API) в контрол, который сам воспользуется этими же функциями отрисовки.
HBITMAP hBmp;
if (Set32BPP())
{
hBmp = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAPXP32));
ImageList_Add(hImageList, hBmp, hBmp);
}
else
{
hBmp = LoadBitmap(hInsatnce, MAKEINTERESOURCE(IDB_BITMAP256));
ImageList_AddMasked(hImageList, hBmp, RGB(255, 0, 255));
}
DeleteObject(hBmp);
Ну, вот в общем-то и все. Надеюсь, что я прояснил еще один вопрос, возникающий при программировании для Windows XP. Удачного программирования.