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

または透明度とアルファレベルの両方を調整するには、LWA_COLORKEY | LWA_ALPHAを使用すると、ビットマップの白い部分が透明に表示されます。 OnPaintを仮定

WHITE_BRUSHがゼロであるので、wcex.hbrBackground = WHITE_BRUSH;がゼロに背景ブラシを設定することに代えGetDC/ReleaseDC

BeginPaint/EndPaintを使用し、WM_PAINTに対する応答です。代わりにブラシハンドルを割り当てます。

別の方法としては、同じウィンドウ内で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

はい、動作します。唯一のものは、半透明のピクセル(hビットマップ内にある)です。しかし、私は今それを残すことができます。 私はTransparentBltを使用しました。私はLWA_ALPHAを使用しません。なぜなら、すべてのピクセルに透明性を持たせるからです(私はそれを望んでいません)。 私はそれをWM_PAINTの外部にペイントしていますので、GetDC/ReleaseDCを使用する必要があります –

+0

これは* .pngファイルですか?可能であれば、画像に関する質問に詳細を記入してください(デフォルトのアップロードでは* .bmpが* .pngに変換されます) –

+0

いいえ、静的画像ではありません。組み込みフレームワーク。つまり、htmlのクロムによって生成されるバッファです。 –

関連する問題