代码之家  ›  专栏  ›  技术社区  ›  ColmanJ BrokenGlass

透明分层窗口白色

  •  1
  • ColmanJ BrokenGlass  · 技术社区  · 11 年前

    我正试图用c++win32制作一个分层窗口,但我在绘制或“碰撞”它时遇到了问题

    作为参考,我试图显示的图片。

    default

    这是窗口的基本创建

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

    以及消息循环

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

    }

    所以这就是我得到的结果 UpdateLayeredWindow result 正如你在这个方法中看到的那样,我得到的是白色边界,实际上应该是完全透明的,但半透明部分确实可以正常工作。

    以下是我所做的尝试,它给了我一个“有用”的改变。 首先,我只是试图添加ULW_COLORKEY标志来隐藏白色

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

    以及结果。 ULW_COLORKEY

    所以这隐藏了白色的边界,但也隐藏了图片中所有的白色。 我尝试的下一件事是将SetLayeredWindowAttributes与UpdateLayeredWindow组合使用,不使用ULW_COLORKEY标志

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

    同样在窗口进程中启用绘制,如下所示

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

    通过这种方式,我可以像这样直观地得到我想要的东西 SetLayeredWindowAttributes

    但他的方法的问题是,它的整个窗口都是可以点击的,而只使用UpdateLayeredWindow,只有应该完全透明的部分才能像它应该的那样点击。我对最后一种方法也有一种感觉,那就是它更像是一种“破解”,而不是一种体面的方法。

    所以我希望有人能告诉我我做错了什么。

    1 回复  |  直到 11 年前
        1
  •  1
  •   ColmanJ BrokenGlass    11 年前

    第一种方式是正确的。错误出现在位图中,该位图没有预乘alpha