Creating a transparent window in C++ Win32

前端 未结 2 1899
我寻月下人不归
我寻月下人不归 2020-11-29 16:40

I\'m creating what should be a very simple Win32 C++ app whose sole purpose it to ONLY display a semi-transparent PNG. The window shouldn\'t have any chrome, and all the opa

相关标签:
2条回答
  • 2020-11-29 17:14

    Use the SetLayeredWindowAttributesarchive function, this allows you to set a mask color that will become transparent, thus allowing the background to show through.

    You will also need to configure your window with the layered flag, e.g.:

    SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
    

    After that it's fairly simple:

    // Make red pixels transparent:
    SetLayeredWindowAttributes(hwnd, RGB(255,0,0), 0, LWA_COLORKEY);
    

    When your PNG contains semi-transparent pixels that you want to blend with the background, this becomes more complicated. You could try looking at the approach in this CodeProject article:

    Cool, Semi-transparent and Shaped Dialogs with Standard Controls for Windows 2000 and Above

    0 讨论(0)
  • 2020-11-29 17:29

    I was able to do exactly what I wanted by using the code from Part 1 and Part 2 of this series:

    Displaying a Splash Screen with C++


    • Part 1: Creating a HBITMAP archive
    • Part 2: Displaying the window archive

    Those blog posts are talking about displaying a splash screen in Win32 C++, but it was almost identical to what I needed to do. I believe the part that I was missing was that instead of just painting the PNG to the window using GDI+, I needed to use the UpdateLayeredWindow function with the proper BLENDFUNCTION parameter. I'll paste the SetSplashImage method below, which can be found in Part 2 in the link above:

    void SetSplashImage(HWND hwndSplash, HBITMAP hbmpSplash)
    {
      // get the size of the bitmap
      BITMAP bm;
      GetObject(hbmpSplash, sizeof(bm), &bm);
      SIZE sizeSplash = { bm.bmWidth, bm.bmHeight };
    
      // get the primary monitor's info
      POINT ptZero = { 0 };
      HMONITOR hmonPrimary = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
      MONITORINFO monitorinfo = { 0 };
      monitorinfo.cbSize = sizeof(monitorinfo);
      GetMonitorInfo(hmonPrimary, &monitorinfo);
    
      // center the splash screen in the middle of the primary work area
      const RECT & rcWork = monitorinfo.rcWork;
      POINT ptOrigin;
      ptOrigin.x = 0;
      ptOrigin.y = rcWork.top + (rcWork.bottom - rcWork.top - sizeSplash.cy) / 2;
    
      // create a memory DC holding the splash bitmap
      HDC hdcScreen = GetDC(NULL);
      HDC hdcMem = CreateCompatibleDC(hdcScreen);
      HBITMAP hbmpOld = (HBITMAP) SelectObject(hdcMem, hbmpSplash);
    
      // use the source image's alpha channel for blending
      BLENDFUNCTION blend = { 0 };
      blend.BlendOp = AC_SRC_OVER;
      blend.SourceConstantAlpha = 255;
      blend.AlphaFormat = AC_SRC_ALPHA;
    
      // paint the window (in the right location) with the alpha-blended bitmap
      UpdateLayeredWindow(hwndSplash, hdcScreen, &ptOrigin, &sizeSplash,
          hdcMem, &ptZero, RGB(0, 0, 0), &blend, ULW_ALPHA);
    
      // delete temporary objects
      SelectObject(hdcMem, hbmpOld);
      DeleteDC(hdcMem);
      ReleaseDC(NULL, hdcScreen);
    }
    
    0 讨论(0)
提交回复
热议问题