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:
- Paint.Net
bmpx is the same 32-bit bmp, only with alpha . You can use Adobe Photoshop , it has the same functionality. - I load the resource manually, because
LoadImage does not know how to load rasters with alpha. SetDIBitsToDevice loads the alpha. - 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)