Пример кода ниже делит окно на три горизонтальных области. Затем там рисует альфа-переход точечного рисунка в каждой из этих областей окна как ниже указано:
void DrawAlphaBlend (HWND hWnd, HDC hdcwnd)
{
HDC hdc; // дескриптор DC, нужно создать
BLENDFUNCTION bf; // структура для alpha-перехода
HBITMAP hbitmap; // дескриптор точечного рисунка
BITMAPINFO bmi; // заголовок точечного рисунка
VOID *pvBits; // указатель на DIB секцию
ULONG ulWindowWidth, ulWindowHeight; // окно ширина/высота
ULONG ulBitmapWidth, ulBitmapHeight; // рисунок ширина/высота
RECT rt; // используется для получения габаритов окна
UINT32 x,y; // пошаговые переменные
UCHAR ubAlpha; // для создания градиентов прозрачности
UCHAR ubRed;
UCHAR ubGreen;
UCHAR ubBlue;
float fAlphaFactor; // чтобы делать умножение в обратном порядке
// получим габариты окна
GetClientRect(hWnd, &rt);
// вычислим ширину/высоту окна
ulWindowWidth = rt.right - rt.left;
ulWindowHeight = rt.bottom - rt.top;
// убедимся, что мы имеем по меньшей мере какой-то размер окна
if ((!ulWindowWidth) || (!ulWindowHeight))
return;
// поделим окно внутри на 3 горизонтальных области
ulWindowHeight = ulWindowHeight / 3;
// создадим DC для нашего рисунка - источниковый DC для AlphaBlend
hdc = CreateCompatibleDC(hdcwnd);
// обнулим область памяти для информации о точечном рисунке
ZeroMemory(&bmi, sizeof(BITMAPINFO));
// установим информацию о рисунке
// зададим ширину и высоту рисунка 60% от ширины и высоты
// каждой области из этих трех горизонтальных областей. Позже,
// переход произойдет в центре каждой из этих трех областей.
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = ulBitmapWidth = ulWindowWidth -
(ulWindowWidth/5)*2;
bmi.bmiHeader.biHeight = ulBitmapHeight = ulWindowHeight -
(ulWindowHeight/5)*2;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32; // четыре 8-битовых компонента
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = ulBitmapWidth * ulBitmapHeight * 4;
// создадим свою DIB секцию и выберем рисунок в DC
hbitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits,
NULL, 0x0);
SelectObject(hdc, hbitmap);
// В верхней области окна, α = 50%, но нет исходного α
// формат цвета для каждого пикселя равен 0xaarrggbb
// установим все пиксели в синий, а исходный α в 0
for (y = 0; y < ulBitmapHeight; y++)
for (x = 0; x < ulBitmapWidth; x++)
((UINT32 *)pvBits)[x + y * ulBitmapWidth] = 0x000000ff;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 0x7f; // поовина 0xff = 50% прозрачности
bf.AlphaFormat = 0; // игнорируем исходный α-канал
if (!AlphaBlend(hdcwnd, ulWindowWidth/5, ulWindowHeight/5,
ulBitmapWidth, ulBitmapHeight,
hdc, 0, 0, ulBitmapWidth, ulBitmapHeight, bf))
return; // α-переход завершился ошибкой
// в средней области окна, α = 100% (отключено), исходный α равен
// 0 в середине рисунка и непрозрачный в остальной части рисунка
for (y = 0; y < ulBitmapHeight; y++)
for (x = 0; x < ulBitmapWidth; x++)
if ((x > (int)(ulBitmapWidth/5)) &&
(x < (ulBitmapWidth-ulBitmapWidth/5)) &&
(y > (int)(ulBitmapHeight/5)) &&
(y < (ulBitmapHeight-ulBitmapHeight/5)))
//в середине рисунка: исходный α = 0 (прозрачный).
// Это означает умножение каждого компонента на 0x00.
// Поэтому, после AlphaBlend, мы имеем a, 0x00 * r,
// 0x00 * g и 0x00 * b (что равно 0x00000000)
// пока установим все пиксели в красный цвет
((UINT32 *)pvBits)[x + y * ulBitmapWidth] = 0x00ff0000;
else
// в остатке рисунка исходный α = 0xff (непрозрачный)
// и установим все пиксели в синий цвет
((UINT32 *)pvBits)[x + y * ulBitmapWidth] = 0xff0000ff;
endif;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = AC_SRC_ALPHA; // используем исходный α
bf.SourceConstantAlpha = 0xff; // непрозрачный (α отключена)
if (!AlphaBlend(hdcwnd, ulWindowWidth/5,
ulWindowHeight/5+ulWindowHeight, ulBitmapWidth,
ulBitmapHeight, hdc, 0, 0, ulBitmapWidth,
ulBitmapHeight, bf))
return;
// нижняя область окна использует α = 75%, исходный α изменяется
// Создадим градиент действия, используя исходный α, а затем
// изменим его даже несколько больше чем α
ubRed = 0x00;
ubGreen = 0x00;
ubBlue = 0xff;
for (y = 0; y < ulBitmapHeight; y++)
for (x = 0; x < ulBitmapWidth; x++)
{
// обычный градиент исходит от значения пикселя α до
// значения пикселя x
ubAlpha = (UCHAR)((float)x / (float)ulBitmapWidth * 255);
// вычисляем коэффициент на который умножаем каждый
// компонент
fAlphaFactor = (float)ubAlpha / (float)0xff;
// умножаем каждый пиксель fAlphaFactor, таким образом
// каждый компонент меньше или равен значению α.
((UINT32 *)pvBits)[x + y * ulBitmapWidth]
= (ubAlpha << 24) | //0xaa000000
((UCHAR)(ubRed * fAlphaFactor) << 16) | //0x00rr0000
((UCHAR)(ubGreen * fAlphaFactor) << 8) | //0x0000gg00
((UCHAR)(ubBlue * fAlphaFactor)); //0x000000bb
}
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = AC_SRC_ALPHA; // используем исходный α
bf.SourceConstantAlpha = 0xbf; // используем α с
// 75% непрозрачности
AlphaBlend(hdcwnd, ulWindowWidth/5,
ulWindowHeight/5+2*ulWindowHeight, ulBitmapWidth,
ulBitmapHeight, hdc, 0, 0, ulBitmapWidth,
ulBitmapHeight, bf);
// сделаем очистку
DeleteObject(hbitmap);
DeleteDC(hdc);
}
|