2

我有一个具有透明背景的 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
     );
4

0 回答 0