2016-10-05 10 views
1

주어진 윈도우 내에 버퍼 (알파 정보 포함)를 그려야합니다. 드로잉은 WM_PAINT 외부에서 수행됩니다 (Chromium-Embedded-Framework에서 호출 된 CefRenderHandler :: OnPaint 메서드에서 수행됩니다). 내가 가진 것을버퍼를 사용하는 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에서 당신은 BeginPaint 함수의 기능을 대신의 GetDC를 사용하는 촬영 HDC를 사용해야합니다. 이렇게하면 배경 내용의 문제가 해결 될 수 있습니다. 잘못된 알파 값에 대해서는 다음과 같이 비트 맵에 알파 값을 미리 곱해야합니다. http://www.fengyuan.com/article/alphablend.html – VuVirt

답변

1

AlphaBlend과 창을 모두 사용할 필요는 없습니다. hbitmap 이전에 생성 한 비트 맵에 대한 핸들입니다

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); 
} 

: 층 창문 만 사용하십시오. SetLayeredWindowAttributes(hwnd, RGB(255,255,255), 255, LWA_COLORKEY);

투명도 및 알파 수준을 모두 조정하려면 비트 맵의 ​​흰색 영역이 투명하게 표시되어야합니다. OnPaint 가정

WM_PAINT에 대한 응답, WHITE_BRUSH가 0이 아닌 GetDC/ReleaseDC

주의 BeginPaint/EndPaint를 사용하므로 wcex.hbrBackground = WHITE_BRUSH; 0으로 배경 브러시를 설정합니다. 브러시 핸들을 대신 지정하십시오.

또는 당신은 같은 창에서 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- 임베디드 프레임 워크. 즉, html의 chromium에 의해 생성 된 버퍼입니다. –