When specifying window class parameters, I specify:

WindowClass.hbrBackground = CreatePatternBrush((HBITMAP)LoadImageA(hInstance, MAKEINTRESOURCEA(TEST), IMAGE_BITMAP, 320, 320, LR_CREATEDIBSECTION)); 

(with this loading of the RGBA image, the icons in the tray menu were obtained with alpha)

After registering a class, I create a window:

 CreateWindowExA(WS_EX_TOPMOST, WindowClass.lpszClassName, ApplicationTitleA.c_str(), WS_POPUP, (GetSystemMetrics(SM_CXSCREEN) - AW_WIDTH) / 2, (GetSystemMetrics(SM_CYSCREEN) - AW_HEIGHT) / 2, AW_WIDTH, AW_HEIGHT, NULL, NULL, hInstance, NULL); 

( .hbrBackground , transparent if the .hbrBackground not loaded).

The TEST image from resources is a 32-bit bmp file (RGBA).

How to load it so that it supports alpha images? Where the windows and the desktop below should be visible, now is a black background.

    2 answers 2

    The classic solution: use WS_EX_LAYERED with UpdateLayeredWindow .


    For example, I took the standard visual studio blank for a window application. I added the first alpha png to the resources, which I found:

    To do this, add the line to the resource file *.rc :

     IDI_SOTEST9 RCDATA "penguin.bmpx" 

    I received penguin.bmpx from png, passing it through Paint.Net .

    Then, in WndProc added the ability to drag a window beyond its client area:

     case WM_NCHITTEST: return HTCAPTION; 

    And expanded the initialization code, in InitInstance :

     BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; BLENDFUNCTION blend; POINT ptPos, ptSrc; SIZE sizeWnd; HDC hdcScreen, hdcMem; HGDIOBJ hBitmap; HRSRC hRSrc; HGLOBAL hRes; BITMAPFILEHEADER *pRes; BITMAPINFOHEADER *bi; void *bits, *premultiply; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindowEx(WS_EX_LAYERED, szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if( !hWnd ) { return FALSE; } // load resource hRSrc = FindResource(hInstance, MAKEINTRESOURCE(IDI_SOTEST9), RT_RCDATA); hRes = LoadResource(hInstance, hRSrc); pRes = (BITMAPFILEHEADER*)LockResource(hRes); bi = (BITMAPINFOHEADER*)(pRes + 1); bits = ((char*)pRes) + pRes->bfOffBits; // premultiply premultiply = malloc(bi->biHeight * bi->biWidth * sizeof(RGBQUAD)); for( int c = bi->biHeight * bi->biWidth; c--; ) { RGBQUAD &src = ((LPRGBQUAD)bits)[c]; RGBQUAD &dst = ((LPRGBQUAD)premultiply)[c]; dst.rgbRed = (BYTE)MulDiv(src.rgbRed, src.rgbReserved, 255); dst.rgbGreen = (BYTE)MulDiv(src.rgbGreen, src.rgbReserved, 255); dst.rgbBlue = (BYTE)MulDiv(src.rgbBlue, src.rgbReserved, 255); dst.rgbReserved = src.rgbReserved; } hdcScreen = GetDC(HWND_DESKTOP); // prepare bitmap hBitmap = CreateCompatibleBitmap(hdcScreen, bi->biWidth, bi->biHeight); hdcMem = CreateCompatibleDC(hdcScreen); hBitmap = SelectObject(hdcMem, hBitmap); SetDIBitsToDevice( hdcMem, 0, 0, bi->biWidth, bi->biHeight, 0, 0, 0, bi->biHeight, premultiply, (BITMAPINFO*)bi, DIB_RGB_COLORS ); free(premultiply); // prepare window memset(&blend, 0, sizeof(blend)); blend.BlendOp = AC_SRC_OVER; blend.SourceConstantAlpha = 255; blend.AlphaFormat = AC_SRC_ALPHA; sizeWnd.cx = bi->biWidth; sizeWnd.cy = bi->biHeight; ptPos.x = 0; ptPos.y = 0; ptSrc.x = 0; ptSrc.y = 0; UpdateLayeredWindow(hWnd, hdcScreen, &ptPos, &sizeWnd, hdcMem, &ptSrc, 0, &blend, ULW_ALPHA); // cleanup ReleaseDC(HWND_DESKTOP, hdcScreen); hBitmap = SelectObject(hdcMem, hBitmap); DeleteDC(hdcMem); DeleteObject(hBitmap); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } 

    Everything, the background of the window is now with alpha, and without connecting additional libraries:

    Let me explain some of the nuances:

    1. Paint.Net bmpx is the same 32-bit bmp, only with alpha . You can use Adobe Photoshop , it has the same functionality.
    2. I load the resource manually, because LoadImage does not know how to load rasters with alpha. SetDIBitsToDevice loads the alpha.
    3. For full-fledged work with transparency, before loading a raster it is important to perform a standard premultiply . Will work without it, but defective.

    Link to a packaged zip project (if you could not figure it out)
    Link to exe (who is not afraid)

    • one
      Thanks for the detailed answer! - Iceman

    Well, of course, this will not work for you. That was worth waiting for.

    To solve the problem, use the functions from the Desktop Windows Manager API: DwmExtendFrameIntoClientArea (supported starting with Windows Vista).

    To install the glass frame , do the following :

    The effect is to create a "sheet of glass" effect.

    And then sculpt your translucent image on the background. I think that should help.