Алекс Jenter - Программирование на Visual C++. Архив рассылки
- Название:Программирование на Visual C++. Архив рассылки
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Алекс Jenter - Программирование на Visual C++. Архив рассылки краткое содержание
РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.
Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Что это такое? Дело в том, что AlphaBlend() может работать в двух разных режимах.
Первый (и наиболее простой в использовании) режим работы AlphaBlend() предполагает, что значение Alpha задано для всей картинки. В таком случае, оно применяется ко всем пикселам без исключения.
Формат BLENDFUNCTION в этом случае:
BLENDFUNCTION blend;
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.AlphaFormat = 0;
blend.SourceConstantAlpha = 180;
Для поля BlendOp в данный момент определено только одно допустимое значение — AC_SRC_OVER.
Поле BlendFlags должно содержать 0.
Плохо документированный параметр AlphaFormat определяет взаимодействие пикселов источника и приемника, о чем мы еще поговорим далее.
Параметр SourceConstantAlpha определяет степень непрозрачности. Задав для этого поля 0, вы не увидите свой растр вообще. Максимальное значение, умещающееся в тип BYTE, равно 255. При этом выводимый растр полностью перекроет область назначения. Но зачем вам, в таком случае, AlphaBlend()? И это значение используется, в-основном, для второго режима.
Он требует некоторой дополнительной подготовки. В этом режиме растр, подготовленный для вывода, должен содержать информацию о степени прозрачности каждого пиксела. Это достигается, например, применением формата 32 бита на пиксел (по одному байту на каждый цветовой компонент и одному – на альфа-канал).
Сложности возникнут вот с чем. Мне неизвестен ни один графический пакет, позволяющий сохранять растры с альфа-каналом в формате, пригодном для AlphaBlend(). При создании такого растра программно мы можем сохранить его на диск (в формате Windows Bitmap 32-bit). Он прочитывается популярными программами типа ACDSee, но функции LoadBitmap() и LoadImage() отказываются его загружать. При попытке поместить его в ресурс rc.exe у меня вывалился с сообщением Internal error…
Но унывать не стоит. Мы можем подготовить растр в памяти, скомбинировав, например, два растра – с изображением объекта и его тени. К счастью, функция AlphaBlend() может работать с растрами, созданными с помощью CreateDIBSection():
HBITMAP CreateDIBSection(
HDC hdc, // handle to DC
CONST BITMAPINFO *pbmi, // bitmap data
UINT iUsage, // data type indicator
VOID **ppvBits, // bit values
HANDLE hSection, // handle to file mapping object
DWORD dwOffset // offset to bitmap bit values
);
Здесь hdc – контекст, совместимый с устройством вывода, pbmi – указатель на структуру BITMAPINFO с информацией о размерах и цветовой глубине создаваемого растра. Параметр iUsage определяет, что будет содержаться в буфере растра – индексы в палитре цветов (DIB_PAL_COLORS) или прямые их значения (DIB_RGB_COLORS). Очевидно, что второе – для режима TrueColor палитра не нужна.
Указатель на созданный буфер при успешном вызове будет возвращен в параметре ppvBits.
В параметрах hSection и dwOffset при работе с растром в памяти необходимо указывать 0.
ПРИМЕЧАНИЕ
Все вышесказанное не означает, что спрайты с альфа-каналом нельзя хранить в ресурсах программы. Вы можете включить их как custom resource, загрузить с помощью LoadResource() и заполнить полученными данными буфер, созданный с помощью CreateDIBSection(). Но не забывайте, что это значительно увеличит размер вашего исполняемого модуля. Кроме того, можно рассмотреть вариант подгрузки предварительно рассчитанных в подобной программе растров из внешних файлов – средствами библиотеки исполнения или используя параметры hSection и dwOffset при вызове CreateDIBSection().
Использование CreateDIBSection() облегчает доступ к битам изображения: в противном случае такие картинки можно было бы вывести только в режиме экрана True Color 32 bit. Для обращения с таким форматом данных идеально подходит структура RGBQUAD:
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
Альфа-канал можно хранить в поле rgbReserved, хотя оно для этого и не предназначалось :) Кроме того, остается еще одна (недокументированная) возможность – воспользоваться функцией AlphaDIBBlend(), которую мы рассматривать не будем.
Результат приведен здесь.

Детали работы с битами растров мы опустим (все это можно найти в прилагаемом проекте). Отмечу только, что для вывода использовался такой формат BLENDFUNCTION:
blend.BlendOp = AC_SRC_OVER;
blend.BlendFlags = 0;
blend.AlphaFormat = AC_SRC_NO_PREMULT_ALPHA;
blend.SourceConstantAlpha = 255;
Параметр AC_SRC_NO_PREMULT_ALPHA не описан в MSDN за январь 2000 года и найден экспериментально (и подглядыванием в wingdi.h :) При его задании используется альфа-канал растра источника и не используется альфа-канал приемника (возможно и такое).
СОВЕТ
При использовании альфа-канала у вас все равно остается возможность без пересчета битов растра изменять прозрачность всей картинки – SourceConstantAlpha работает и в этом случае.
И в завершение напомню, что AlphaBlend() также требует включения в проект при сборке библиотеки импорта msimg32.lib, которая отсутствует в Windows 95.
ВОПРОС-ОТВЕТ
Как создать многострочный тултип?
Автор: Александр Шаргин
Начиная с версии 4.70 библиотеки Comctl32.dll тултипы поддерживают многострочный режим работы. По умолчанию он выключен, и всё, что требуется от нас – активизировать его. Для этого предназначено сообщение TTM_SETMAXTIPWIDTH, которое позволяет задать ширину тултипа (в пикселях). По умолчанию ширина установлена в –1, что соответствует однострочному режиму работы. В этом режиме тултип игнорирует все пары '\r\n' в тексте подсказки, выдавая его в одну строку. Задание любого положительного значения ширины переводит тултип в многострочный режим работы.
В многострочном режиме тултип корректно обрабатывает комбинации '\r\n', переходя на новую строку. Кроме того, он старается вписать текст в заданную ширину, разбивая его на строки самостоятельно. Переход на новую строку возможен только между словами, поэтому если в тексте подсказки есть длинные слова, заданная ширина может быть превышена. Если вы не хотите, чтобы тултип разбивал текст на строки по своему усмотрению, задайте значение ширины, заведомо превышающее ширину экрана. Например:
SendMessage(hTip, TTM_SETMAXTIPWIDTH, 0, (LPARAM)0xFFFFFF);
В MFC аналогичного эффекта можно добиться, используя фукцию CToolTipCtrl::SetMaxTipWidth. Единственный параметр, который она получает – новое значение ширины тултипа. Например:
// m_tt - объект класса CToolTipCtrl
m_tt.SetMaxTipWidth(0xFFFFFF);
Проблемы возникают только в том случае, когда вы используете встроенную поддержку тултипов класса CWnd. В этом случае тултип создаётся и уничтожается в недрах MFC, причём документированного способа добраться до него не существует. Выйти из положения можно, воспользовавшись недокументированным: MFC сохраняет указатель на созданный ею объект класса CToolTipCtrl в структуре _AFX_THREAD_STATE, и можно получить к нему доступ, используя выражение AfxGetThreadState()->m_pToolTip.
Читать дальшеИнтервал:
Закладка: