我有一个具有透明背景的 png 图像,我想将其用作分层窗口的背景。目标是能够透过窗口看到图像的透明部分(即使窗口移动或它后面的桌面发生变化)。
我尝试了很多东西,但我只设法绘制了窗口后面的内容(创建窗口时显示图像并显示后面的桌面,但移动窗口时透明背景不再起作用)
我已经检查了在 C++ Win32 中创建透明窗口并从 png、winapi 创建透明图像,但我无法重现类似的结果
最小代码示例:
我将以下功能用于如何使用UpdateLayeredWindowUpdateLayeredWindow
void display(HWND hwnd, const wchar_t* path)
{
// Load our PNG image
CImage img;
img.Load(path);
// Get dimensions
int iWidth = img.GetWidth();
int iHeight = img.GetHeight();
// Make mem DC + mem bitmap
HDC hdcScreen = GetDC(NULL);
HDC hDC = CreateCompatibleDC(hdcScreen);
HBITMAP hBmp = CreateCompatibleBitmap(hdcScreen, iWidth, iHeight);
HBITMAP hBmpOld = (HBITMAP)SelectObject(hDC, hBmp);
// Draw image to memory DC
img.Draw(hDC, 0, 0, iWidth, iHeight, 0, 0, iWidth, iHeight);
// Call UpdateLayeredWindow
BLENDFUNCTION blend = { 0 };
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
POINT ptPos = { 0, 0 };
SIZE sizeWnd = { iWidth, iHeight };
POINT ptSrc = { 0, 0 };
UpdateLayeredWindow(hwnd, hdcScreen, &ptPos, &sizeWnd, hDC, &ptSrc, 0, &blend, ULW_ALPHA);
SelectObject(hDC, hBmpOld);
DeleteObject(hBmp);
DeleteDC(hDC);
ReleaseDC(NULL, hdcScreen);
}
创建窗口:
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
{
SetProcessDPIAware();
GdiplusStartupInput gpStartupInput;
ULONG_PTR gpToken;
GdiplusStartup(&gpToken, &gpStartupInput, NULL);
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_POPUP | WS_EX_TOPMOST | WS_EX_LAYERED, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT,
700, 700,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GdiplusShutdown(gpToken);
return 0;
}
在窗口的消息处理程序中:
case WM_CREATE:
{
const wchar_t* path = L"path_to_png_image";
display(hwnd, path);
}
break;
case WM_PAINT:
{
//doing nothing
}
break;
该代码的问题只是没有绘制任何内容:我只是得到一个完全透明的窗口。WM_PAINT另外,即使我不使用,我也检查并被调用SetLayeredWindowAttributes
编辑 :
评论中指出的解决方案是设置WS_EX_TOPMOST | WS_EX_LAYERED为的第一个参数CreateWindowEx:
hwnd = CreateWindowEx(
WS_EX_TOPMOST | WS_EX_LAYERED, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_POPUP, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT,
700, 700,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);