transparency layered window white

我怕爱的太早我们不能终老 提交于 2019-12-24 17:03:47

问题


I'm trying to make a layered window with c++ win32 but I'm having a problem with the drawing or "collision" of it

For reference the picture that I'm trying to display.

This is the basic creation of the window

//window
DWORD exFlags = 0;
if(m_bTransparent)
    exFlags |= WS_EX_LAYERED;
Create(WS_POPUP, exFlags);

std::wstring sPic(L"power-disconnected.png");
m_pAlertPic = m_pPowerMon->GetGPPicMan()->LoadPicture(sPic.c_str());

// make the window layered when using transparency
if(m_bTransparent && m_pAlertPic != nullptr)
{
    HDC hdcScreen = GetDC(GetHandle());
    HDC hdc = CreateCompatibleDC(hdcScreen);
    HBITMAP hbmpold = (HBITMAP)SelectObject(hdc, m_pAlertPic->GetBuffer());

    POINT dcOffset = {0, 0};
    SIZE size = {ww, wh};

    BLENDFUNCTION bf = {AC_SRC_OVER, 0, (int) (2.55 * 100), AC_SRC_ALPHA}; // blend function combines opacity and pixel based transparency
    UpdateLayeredWindow(GetHandle(), hdcScreen, NULL, &size, hdc, &dcOffset, RGB(255, 255, 255), &bf, ULW_ALPHA);
    SelectObject(hdc, hbmpold);
    DeleteDC(hdc);
    ReleaseDC(GetHandle(), hdcScreen);
}

and the message loop

int WindowAlert::WndProc(Gnaq::WindowBase* pWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
   switch(msg)
   {
   case WM_CLOSE:
       Hide();
       return 1;
   case WM_PAINT:
       // only draw when the widow is not transparent
       // layered window redraw them self
       if(!m_bTransparent)
           m_pCanvas->Draw(m_pGraphics);
       break;
   case WM_LBUTTONUP:
       pWnd->Hide();
       m_bDismised = true;
       break;
   }
   return DefWindowProcW(pWnd->GetHandle(), msg, wParam, lParam);

}

So this is the result I get

As you can see with this method I'm getting white borders where is should actually be fully transparent, but the semi transparent parts do work correctly.

here's what I've tried that gave me a "useful" change. First I just tried to add the ULW_COLORKEY flag to hide the white color

UpdateLayeredWindow(GetHandle(), hdcScreen, NULL, &size, hdc, &dcOffset, RGB(255, 255, 255), &bf, ULW_ALPHA | ULW_COLORKEY);

And the result.

So this hides the white border but also all the white in the picture. Next thing I've tried was using SetLayeredWindowAttributes in combination of UpdateLayeredWindow, without the ULW_COLORKEY flag

SetLayeredWindowAttributes(GetHandle(), 0xFFFFFF00, 255, LWA_COLORKEY);

Also in the window proc enable the paint, like this

case WM_PAINT:
    m_pCanvas->Draw(m_pGraphics);
    break;

This way I'm visually getting what I want like this

But the problem with his approach is that it the complete window is click able while with just using the UpdateLayeredWindow only the parts that should be fully transparent are click able like it should be. I also have the feeling with this last approach that it is more a "hack" than a decent approach.

So i hope that someone can tell me what I'm doing wrong.


回答1:


The first way was the correct. The fault was in the bitmap, which didn't had premultiplied alpha



来源:https://stackoverflow.com/questions/19449491/transparency-layered-window-white

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!