2016-10-05 2 views
1

Я хотел бы нарисовать буфер (с альфа-информацией!) В пределах данного окна. Чертеж выполняется вне WM_PAINT (это делается в методе CefRenderHandler :: OnPaint, вызывается из Chromium-Embedded-Framework).Windows AlphaBlend с использованием буфера

Проблема, что у меня есть это:

  • старое содержимое окна не очищается (если буфер изменен, я состарюсь содержание нарисованы и новое содержание обращается).
  • альфа-канал ошибочно интерпретировано - Я думаю, что даже если пиксель имеет информацию альфа, расписано, как это не будет иметь информацию о альфа

Это то, что я до сих пор:

OnPaint (...): создание

HDC screen_dc = GetDC(windowHandle); 
RECT rcWin; 
GetClientRect(windowHandle, &rcWin); 

BITMAPINFO info; 
ZeroMemory(&info, sizeof(BITMAPINFO)); 
info.bmiHeader.biBitCount = 32; 
info.bmiHeader.biWidth = width; 
info.bmiHeader.biHeight = -height; 
info.bmiHeader.biPlanes = 1; 
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
info.bmiHeader.biSizeImage = width*height * 4; 
info.bmiHeader.biCompression = BI_RGB; 

void *buf; 
HBITMAP hDib = CreateDIBSection(screen_dc, &info, DIB_RGB_COLORS, (void **)&buf, 0, 0); 
memcpy(buf, buffer, width * height * 4); //buffer contains bitmap to draw 
HDC hDibDC = CreateCompatibleDC(screen_dc); 
HGDIOBJ hOldObj = SelectObject(hDibDC, hDib); 
BLENDFUNCTION blendFunction_; 
blendFunction.BlendOp = AC_SRC_OVER; 
blendFunction.BlendFlags = 0; 
blendFunction.SourceConstantAlpha = 255; 
blendFunction.AlphaFormat = AC_SRC_ALPHA; 
AlphaBlend(screen_dc, 0, 0, width, height, hDibDC, 0, 0, width, height, blendFunction); 

SelectObject(hDibDC, hOldObj); 
ReleaseDC(windowHandle, screen_dc); 
DeleteObject(hDib); 
DeleteDC(hDibDC); 

окно:

WNDCLASSEX wcex = {0}; 
wcex.cbSize = sizeof(wcex); 
wcex.style = CS_HREDRAW | CS_VREDRAW; 
wcex.lpfnWndProc = BrowserWindowWndProc; 
wcex.hInstance = hinstance; 
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 
wcex.hbrBackground = WHITE_BRUSH; 
wcex.lpszClassName = BROWSER_WINDOW_CLASS; 
wcex.cbClsExtra = 0; 
wcex.cbWndExtra = 0; 
RegisterClassEx(&wcex); 

DWORD exStyle{0}; 
exStyle |= WS_EX_TOOLWINDOW; 
exStyle |= WS_EX_LAYERED; 

DWORD style {0}; 
style |= WS_SYSMENU; 
style |= WS_VISIBLE; 

HWND hWnd = CreateWindowEx(
    exStyle, 
    BROWSER_WINDOW_CLASS, 
    BROWSER_WINDOW_CLASS, 
    style, 
    100, 
    100, 
    300, 
    300, 
    nullptr, 
    nullptr, 
    hinstance, 
    nullptr 
); 
... 
SetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 255, LWA_COLORKEY); 

Не могли бы вы помочь мне с этими проблемами?

Заранее спасибо.

+0

в OnPaint вы должны использовать HDC, взятый из функции BeginPaint вместо использования GetDC. Это может решить проблему с фоновым содержимым. Что касается неправильных значений альфа, вам может потребоваться предварительно рассчитать альфа-значения в растровом изображении, как показано здесь: http://www.fengyuan.com/article/alphablend.html – VuVirt

ответ

1

Нет необходимости использовать как AlphaBlend, так и слоистые окна. Используйте только многослойные окна:

void OnPaint(HDC hdc, int width, int height, HBITMAP hbitmap) 
{ 
    HDC memdc = CreateCompatibleDC(hdc); 
    auto oldbmp = SelectObject(memdc, hbitmap); 

    BITMAP bm; 
    GetObject(hbitmap, sizeof(bm), &bm); 
    BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, memdc, 0, 0, SRCCOPY); 

    SelectObject(memdc, oldbmp); 
    DeleteDC(memdc); 
} 

Где hbitmap является дескриптор точечного рисунка, созданного ранее. Белые области растрового изображения должны выглядеть прозрачными при использовании SetLayeredWindowAttributes(hwnd, RGB(255,255,255), 255, LWA_COLORKEY);

Или используйте LWA_COLORKEY | LWA_ALPHA для регулировки как прозрачности, так и уровня альфа.

Предполагая, что OnPaint является ответом на WM_PAINT, использовать BeginPaint/EndPaint вместо GetDC/ReleaseDC

Обратите внимание, что WHITE_BRUSH равна нулю, поэтому wcex.hbrBackground = WHITE_BRUSH; устанавливает кисть фона к нулю. Вместо этого назначьте кисть.

В качестве альтернативы вы можете использовать TransparentBlt в том же окне:

HDC memdc = CreateCompatibleDC(hdc); 
auto oldbmp = SelectObject(memdc, hbitmap); 

BITMAP bm; 
GetObject(hbitmap, sizeof(bm), &bm); 
TransparentBlt(hdc, 0, 0, width, height, 
    memdc, 0, 0, bm.bmWidth, bm.bmHeight, RGB(255, 255, 255)); 

SelectObject(memdc, oldbmp); 
DeleteDC(memdc); 
+0

Да, это работает. Единственное, что вроде не работает, - это полупрозрачные пиксели (которые находятся внутри hbitmap). Но теперь я могу уйти. Я использовал TransparentBlt. Я не использую LWA_ALPHA, так как прозрачность для всех пикселей (я этого не хочу). Я рисую это вне WM_PAINT, поэтому мне нужно использовать GetDC/ReleaseDC –

+0

Это из файла * .png? Дайте дополнительную информацию в вопросе об изображении, если возможно, загрузите образец (загрузка по умолчанию будет конвертировать * .bmp в * .png) –

+0

Нет, это не статическое изображение, я уже упоминал, что этот буфер поступает из Chromium- Embedded-Framework. Другими словами, это буфер, созданный хромом из html. –

Смежные вопросы