1

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

}

これは私が得た結果 UpdateLayeredWindow の結果 です。この方法でわかるように、実際には完全に透明であるべきところに白い境界線が表示されますが、半透明の部分は正しく機能します。

これが私が試した「便利な」変更です。最初に、ULW_COLORKEY フラグを追加して白色を非表示にしようとしました

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

そして結果。 ULW_COLORKEY

これにより、白い境界線だけでなく、画像内のすべての白も非表示になります。次に試したのは、ULW_COLORKEY フラグを使用せずに、SetLayeredWindowAttributes を UpdateLayeredWindow と組み合わせて使用​​することでした。

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

また、ウィンドウ プロシージャで、このようにペイントを有効にします。

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

このようにして、私はこのように欲しいものを視覚的に得ています SetLayeredWindowAttributes

しかし、彼のアプローチの問題は、ウィンドウ全体がクリック可能である一方で、UpdateLayeredWindow を使用するだけでは、完全に透明であるべき部分だけがクリック可能であることです。また、この最後のアプローチは、まともなアプローチというよりも「ハック」であると感じています。

だから、誰かが私が間違っていることを教えてくれることを願っています。

4

1 に答える 1