我正试图用c++win32制作一个分层窗口,但我在绘制或“碰撞”它时遇到了问题
作为参考,我试图显示的图片。
这是窗口的基本创建
//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,只有应该完全透明的部分才能像它应该的那样点击。我对最后一种方法也有一种感觉,那就是它更像是一种“破解”,而不是一种体面的方法。
所以我希望有人能告诉我我做错了什么。