Пример кода ниже делит окно на три горизонтальных области. Затем там рисует альфа-переход точечного рисунка в каждой из этих областей окна как ниже указано:
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); } |