FAQ по C/C++/Visual C++
Работа с сетью Использование TrueColor иконок в программе |
Составители: SUnteXx, Leprecon |
Использование TrueColor иконок в программе | |||
Строго говоря, в этой статье описываются приемы работы с обновленным элементом библиотеки 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; m_ImageList.Create(x, y, Константа_ILC_*, 0, 0);В данных примерах используется странный параметр - "Константа ILC_*" он означает, что здесь, в зависимости от нужд программы (и программиста) используются разные значения. А нужд у нас с вами может быть (аж!) целых два варианта. Вариант 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() { return (IsWinXP() & (ScreenBPP() >= 32)); }Соответственно, если мы работаем в режиме TrueColor и в Windows XP мы используем 32-х битный битмап, а если нет - то, скажем, 256-цветный аналог. Таким образом, создание имаджлиста выливается в следующий код: 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()) m_ImageList.Add(&m_ImageList, &m_ImageList); else m_ImageList.Add(&m_ImageList, RGB(255, 0, 255));Опять-таки, в случае написания программы на чистом 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);Теперь, для воспроизведения изображения нужно либо самим воспользоваться функциями прорисовки изображения, входящими в имаджлист, либо передать указатель (на класс имаджлиста в случае MFC) или хендл на сам имаджлист (API) в контрол, который сам воспользуется этими же функциями отрисовки. Ну, вот в общем-то и все. Надеюсь, что я прояснил еще один вопрос, возникающий при программировании для Windows XP. Удачного программирования. |
Написанный ниже текст предназначен только для Windows XP (и ее продолжений)|||
|
FAQ составлен по материалам Форума на Исходниках.Ру. Copyright © 2002 by Sources.ru. All rights reserved. |