透明分层窗口白色 我试图用C++ Win32制作一个分层窗口,但是我对它的绘制或“碰撞”有问题
作为参考,我正在尝试显示的图片 这是窗口的基本创建透明分层窗口白色 我试图用C++ Win32制作一个分层窗口,但是我对它的绘制或“碰撞”有问题,c++,winapi,gdi,C++,Winapi,Gdi,作为参考,我正在尝试显示的图片 这是窗口的基本创建 //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()
//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);
}
这就是我得到的结果
正如你所看到的,通过这个方法,我得到了白色的边框,实际上应该是完全透明的,但是半透明的部分可以正常工作
这是我尝试过的,给了我一个“有用”的改变。
首先,我尝试添加ULW_COLORKEY标志来隐藏白色
UpdateLayeredWindow(GetHandle(), hdcScreen, NULL, &size, hdc, &dcOffset, RGB(255, 255, 255), &bf, ULW_ALPHA | ULW_COLORKEY);
结果呢。
因此,这隐藏了白色边框,但也隐藏了图片中的所有白色。
我尝试的下一件事是将SetLayeredWindowAttributes与UpdateLayeredWindow结合使用,而不使用ULW_COLORKEY标志
SetLayeredWindowAttributes(GetHandle(), 0xFFFFFF00, 255, LWA_COLORKEY);
同样在窗口过程中启用绘制,如下所示
case WM_PAINT:
m_pCanvas->Draw(m_pGraphics);
break;
这样我就可以像这样直观地得到我想要的
但他的方法的问题是,如果整个窗口是可点击的,而仅使用UpdateLayeredWindow,则应该是完全透明的部分才是可点击的。我也觉得最后一种方法更像是一种“黑客”,而不是一种体面的方法
所以我希望有人能告诉我我做错了什么。第一种方法是正确的。错误在位图中,它没有预乘alpha。第一种方法是正确的。该错误出现在位图中,它没有预乘alpha这是一个漏洞,您使用的是一个意外情况,即GDI使用24bpp画笔渲染背景,alpha为0,而图像使用32bpp绘制,alpha为255。第二种方法是正确的。您需要为窗口提供与颜色键匹配的默认背景笔刷。不是白色,用洋红色或石灰之类的东西。修改
wcex.hbrBackground=CreateSolidBrush(RGB(255,255,0))时修复WNDCLASSEX.hbrBackground代码>来自(HBRUSH)(彩色窗口+1)代码>实际上没有区别。我还更改了UpdateLayeredWindow
UpdateLayeredWindow中的颜色,它希望位图具有预乘alpha。这就是为什么在第一个示例中会出现不需要的白色边框;预乘法会删除这个。你是对的,我对alpha进行了预乘法,现在它像一个符咒一样工作。这是一个黑客,你使用的是一个意外事件,即GDI使用24bpp画笔渲染背景,alpha为0,而图像使用32bpp绘制,alpha为255。第二种方法是正确的。您需要为窗口提供与颜色键匹配的默认背景笔刷。不是白色,用洋红色或石灰之类的东西。修改wcex.hbrBackground=CreateSolidBrush(RGB(255,255,0))时修复WNDCLASSEX.hbrBackground代码>来自(HBRUSH)(彩色窗口+1)代码>实际上没有区别。我还更改了UpdateLayeredWindow
UpdateLayeredWindow中的颜色,它希望位图具有预乘alpha。这就是为什么在第一个示例中会出现不需要的白色边框;预乘运算会消除这个。你是对的,我已经对阿尔法进行了预乘,现在它就像一个符咒。