子窗口透明

实现亚克力材质(Windows 11/10)

// 引入所需的Windows头文件和库
#include <VersionHelpers.h>
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
typedef enum _ACCENT_STATE
{
    ACCENT_DISABLED = 0,
    ACCENT_ENABLE_GRADIENT = 1,
    ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
    ACCENT_ENABLE_BLURBEHIND = 3,
    ACCENT_INVALID_STATE = 4
} ACCENT_STATE;
typedef struct _ACCENT_POLICY
{
    ACCENT_STATE AccentState;
    DWORD AccentFlags;
    DWORD GradientColor;
    DWORD AnimationId;
} ACCENT_POLICY;
typedef struct _WINDOWCOMPOSITIONATTRIBDATA
{
    DWORD Attrib;
    PVOID pvData;
    SIZE_T cbData;
} WINDOWCOMPOSITIONATTRIBDATA;
static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
{
    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
    ImGui_ImplGlfw_ViewportData* vd = IM_NEW(ImGui_ImplGlfw_ViewportData)();
    viewport->PlatformUserData = vd;

    // Workaround for Linux: ignore mouse up events corresponding to losing focus of the previously
    // focused window (#7733, #3158, #7922)
#ifdef __linux__
    bd->MouseIgnoreButtonUpWaitForFocusLoss = true;
#endif

    // GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of
    // GLFW_FOCUSED With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem
    glfwWindowHint(GLFW_VISIBLE, false);
    glfwWindowHint(GLFW_FOCUSED, false);
#if GLFW_HAS_FOCUS_ON_SHOW
    glfwWindowHint(GLFW_FOCUS_ON_SHOW, false);
#endif
    glfwWindowHint(GLFW_DECORATED, (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? false : true);
#if GLFW_HAS_WINDOW_TOPMOST
    glfwWindowHint(GLFW_FLOATING, (viewport->Flags & ImGuiViewportFlags_TopMost) ? true : false);
#endif
    glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
    glfwWindowHint(GLFW_ALPHA_BITS, 8);  // 确保有Alpha位
    GLFWwindow* share_window = (bd->ClientApi == GlfwClientApi_OpenGL) ? bd->Window : nullptr;
    vd->Window =
        glfwCreateWindow((int)viewport->Size.x, (int)viewport->Size.y, "No Title Yet", nullptr, share_window);
    vd->WindowOwned = true;
    viewport->PlatformHandle = (void*)vd->Window;

#ifdef _WIN32
    viewport->PlatformHandleRaw = glfwGetWin32Window(vd->Window);

    // 添加Windows 11亚克力效果
    HWND hwnd = (HWND)viewport->PlatformHandleRaw;


    // 检查是否为Windows 11
    OSVERSIONINFOEX osvi;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    osvi.dwMajorVersion = 10;
    osvi.dwMinorVersion = 0;
    osvi.dwBuildNumber = 22000;  // Windows 11的首个版本号为22000

    DWORDLONG dwlConditionMask = 0;
    VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
    VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
    VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);

    bool isWin11OrGreater =
        VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, dwlConditionMask);

    if (isWin11OrGreater)
    {
        // Windows 11亚克力效果
        MARGINS margins = {-1};
        DwmExtendFrameIntoClientArea(hwnd, &margins);

        // 启用亚克力效果 (Windows 11)
        DWMWINDOWATTRIBUTE attribute = DWMWA_SYSTEMBACKDROP_TYPE;
        DWM_SYSTEMBACKDROP_TYPE backdropType = DWMSBT_MAINWINDOW;  // 或使用 DWMSBT_TRANSIENTWINDOW
        DwmSetWindowAttribute(hwnd, attribute, &backdropType, sizeof(backdropType));

        // 设置圆角
        int cornerPreference = DWMWCP_ROUND;
        DwmSetWindowAttribute(
            hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPreference, sizeof(cornerPreference));
    }
    else
    {
        // Windows 10的亚克力效果回退
        // Windows 10使用不同的API
        HRESULT hr = S_OK;

        // 启用模糊效果
        ACCENT_POLICY accent = {ACCENT_ENABLE_BLURBEHIND, 0, 0, 0};
        WINDOWCOMPOSITIONATTRIBDATA data;
        data.Attrib = 19;
        data.pvData = &accent;
        data.cbData = sizeof(accent);

        // 使用SetWindowCompositionAttribute函数
        // 需要声明函数指针
        typedef HRESULT(WINAPI * pSetWindowCompositionAttribute)(HWND, WINDOWCOMPOSITIONATTRIBDATA*);
        HMODULE hUser = GetModuleHandle(TEXT("user32.dll"));
        if (hUser)
        {
            pSetWindowCompositionAttribute SetWindowCompositionAttribute =
                (pSetWindowCompositionAttribute)GetProcAddress(hUser, "SetWindowCompositionAttribute");
            if (SetWindowCompositionAttribute)
            {
                SetWindowCompositionAttribute(hwnd, &data);
            }
        }
    }
#elif defined(__APPLE__)
    viewport->PlatformHandleRaw = (void*)glfwGetCocoaWindow(vd->Window);
#endif

    glfwSetWindowPos(vd->Window, (int)viewport->Pos.x, (int)viewport->Pos.y);

    // Install GLFW callbacks for secondary viewports
    glfwSetWindowFocusCallback(vd->Window, ImGui_ImplGlfw_WindowFocusCallback);
    glfwSetCursorEnterCallback(vd->Window, ImGui_ImplGlfw_CursorEnterCallback);
    glfwSetCursorPosCallback(vd->Window, ImGui_ImplGlfw_CursorPosCallback);
    glfwSetMouseButtonCallback(vd->Window, ImGui_ImplGlfw_MouseButtonCallback);
    glfwSetScrollCallback(vd->Window, ImGui_ImplGlfw_ScrollCallback);
    glfwSetKeyCallback(vd->Window, ImGui_ImplGlfw_KeyCallback);
    glfwSetCharCallback(vd->Window, ImGui_ImplGlfw_CharCallback);
    glfwSetWindowCloseCallback(vd->Window, ImGui_ImplGlfw_WindowCloseCallback);
    glfwSetWindowPosCallback(vd->Window, ImGui_ImplGlfw_WindowPosCallback);
    glfwSetWindowSizeCallback(vd->Window, ImGui_ImplGlfw_WindowSizeCallback);
    if (bd->ClientApi == GlfwClientApi_OpenGL)
    {
        glfwMakeContextCurrent(vd->Window);
        glfwSwapInterval(0);
    }
}

圆角窗口、窗口阴影

/**
 * 为Windows 11设置窗口模糊和阴影效果
 * @param hwnd 窗口句柄
 */
void SetBlurEffectForWin11(HWND hwnd)
{
    // Windows 11相关常量定义
    const DWORD DWMWCP_DEFAULT = 0;
    const DWORD DWMWA_WINDOW_CORNER_PREFERENCE = 33;  // Windows 11
    const DWORD DWMSBT_MAINWINDOW = 2;                // Windows 11 主窗口背景类型
    const DWORD DWMWA_SYSTEMBACKDROP_TYPE = 38;       // Windows 11 背景类型属性
    const DWORD DWMWA_NCRENDERING_POLICY = 2;         // 非客户区渲染策略
    const DWORD DWMNCRP_ENABLED = 1;                  // 启用非客户区渲染
    const DWORD DWMWA_USE_IMMERSIVE_DARK_MODE = 20;   // 沉浸式暗模式

    // 设置背景模糊类型
    int backdropType = DWMSBT_MAINWINDOW;
    DwmSetWindowAttribute(hwnd, DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, sizeof(int));
    
    // 设置边缘参数
    MARGINS margins = {0, 0, 0, 0};
    DwmExtendFrameIntoClientArea(hwnd, &margins);
    
    // 启用阴影效果
    BOOL shadow = TRUE;
    DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &shadow, sizeof(shadow));
    
    // 启用非客户区渲染
    DWORD dwAttribute = DWMNCRP_ENABLED;
    DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &dwAttribute, sizeof(dwAttribute));
}
// 引入所需的Windows头文件和库
#include <VersionHelpers.h>
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
typedef enum _ACCENT_STATE
{
    ACCENT_DISABLED = 0,
    ACCENT_ENABLE_GRADIENT = 1,
    ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
    ACCENT_ENABLE_BLURBEHIND = 3,
    ACCENT_INVALID_STATE = 4
} ACCENT_STATE;
typedef struct _ACCENT_POLICY
{
    ACCENT_STATE AccentState;
    DWORD AccentFlags;
    DWORD GradientColor;
    DWORD AnimationId;
} ACCENT_POLICY;
typedef struct _WINDOWCOMPOSITIONATTRIBDATA
{
    DWORD Attrib;
    PVOID pvData;
    SIZE_T cbData;
} WINDOWCOMPOSITIONATTRIBDATA;
static void ImGui_ImplGlfw_CreateWindow(ImGuiViewport* viewport)
{
    ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData();
    ImGui_ImplGlfw_ViewportData* vd = IM_NEW(ImGui_ImplGlfw_ViewportData)();
    viewport->PlatformUserData = vd;

    // Workaround for Linux: ignore mouse up events corresponding to losing focus of the previously
    // focused window (#7733, #3158, #7922)
#ifdef __linux__
    bd->MouseIgnoreButtonUpWaitForFocusLoss = true;
#endif

    // GLFW 3.2 unfortunately always set focus on glfwCreateWindow() if GLFW_VISIBLE is set, regardless of
    // GLFW_FOCUSED With GLFW 3.3, the hint GLFW_FOCUS_ON_SHOW fixes this problem
    glfwWindowHint(GLFW_VISIBLE, false);
    glfwWindowHint(GLFW_FOCUSED, false);
#if GLFW_HAS_FOCUS_ON_SHOW
    glfwWindowHint(GLFW_FOCUS_ON_SHOW, false);
#endif
     glfwWindowHint(GLFW_DECORATED, (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? false : true);
    //glfwWindowHint(GLFW_DECORATED, true);
#if GLFW_HAS_WINDOW_TOPMOST
    glfwWindowHint(GLFW_FLOATING, (viewport->Flags & ImGuiViewportFlags_TopMost) ? true : false);
#endif
    glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);
    glfwWindowHint(GLFW_ALPHA_BITS, 8);  // 确保有Alpha位
    GLFWwindow* share_window = (bd->ClientApi == GlfwClientApi_OpenGL) ? bd->Window : nullptr;
    vd->Window =
        glfwCreateWindow((int)viewport->Size.x, (int)viewport->Size.y, "No Title Yet", nullptr, share_window);
    vd->WindowOwned = true;
    viewport->PlatformHandle = (void*)vd->Window;

#ifdef _WIN32
    viewport->PlatformHandleRaw = glfwGetWin32Window(vd->Window);

    // 添加Windows 11亚克力效果
    HWND hwnd = (HWND)viewport->PlatformHandleRaw;

    // 检查是否为Windows 11
    OSVERSIONINFOEX osvi;
    ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    osvi.dwMajorVersion = 10;
    osvi.dwMinorVersion = 0;
    osvi.dwBuildNumber = 22000;  // Windows 11的首个版本号为22000

    DWORDLONG dwlConditionMask = 0;
    VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
    VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
    VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);

    bool isWin11OrGreater =
        VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, dwlConditionMask);

    if (isWin11OrGreater)
    {
        const DWORD DWMWCP_DEFAULT = 0;
        const DWORD DWMWA_WINDOW_CORNER_PREFERENCE = 33;  // Windows 11
        int backdropType = DWMSBT_MAINWINDOW;
        DwmSetWindowAttribute(hwnd, DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, sizeof(int));
        MARGINS margins = {0, 0, 0, 0};
        DwmExtendFrameIntoClientArea(hwnd, &margins);
        BOOL shadow = TRUE;
        DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &shadow, sizeof(shadow));
        DWORD dwAttribute = DWMNCRP_ENABLED;
        DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &dwAttribute, sizeof(dwAttribute));

        // Windows 11亚克力效果
        MARGINS margins2 = {-1};
        DwmExtendFrameIntoClientArea(hwnd, &margins2);

        // 启用亚克力效果 (Windows 11)
        DWMWINDOWATTRIBUTE attribute = DWMWA_SYSTEMBACKDROP_TYPE;
        //DWM_SYSTEMBACKDROP_TYPE backdropType = DWMSBT_MAINWINDOW;  // 或使用 DWMSBT_TRANSIENTWINDOW
        DwmSetWindowAttribute(hwnd, attribute, &backdropType, sizeof(backdropType));

        // 设置圆角
        int cornerPreference = DWMWCP_ROUND;
        DwmSetWindowAttribute(
            hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPreference, sizeof(cornerPreference));
    }
    else
    {
        // Windows 10 阴影方法
        MARGINS shadowMargins = {1, 1, 1, 1};
        DwmExtendFrameIntoClientArea(hwnd, &shadowMargins);

        // 确保启用了非客户区渲染
        DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED;
        DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, &ncrp, sizeof(ncrp));

        // Windows 10的亚克力效果回退
        // Windows 10使用不同的API
        HRESULT hr = S_OK;

        // 启用模糊效果
        ACCENT_POLICY accent = {ACCENT_ENABLE_BLURBEHIND, 0, 0, 0};
        WINDOWCOMPOSITIONATTRIBDATA data;
        data.Attrib = 19;
        data.pvData = &accent;
        data.cbData = sizeof(accent);

        // 使用SetWindowCompositionAttribute函数
        // 需要声明函数指针
        typedef HRESULT(WINAPI * pSetWindowCompositionAttribute)(HWND, WINDOWCOMPOSITIONATTRIBDATA*);
        HMODULE hUser = GetModuleHandle(TEXT("user32.dll"));
        if (hUser)
        {
            pSetWindowCompositionAttribute SetWindowCompositionAttribute =
                (pSetWindowCompositionAttribute)GetProcAddress(hUser, "SetWindowCompositionAttribute");
            if (SetWindowCompositionAttribute)
            {
                SetWindowCompositionAttribute(hwnd, &data);
            }
        }

        // 添加:为Windows 10启用阴影效果
        DwmExtendFrameIntoClientArea(hwnd, &shadowMargins);
    }
#elif defined(__APPLE__)
    viewport->PlatformHandleRaw = (void*)glfwGetCocoaWindow(vd->Window);
#endif

    glfwSetWindowPos(vd->Window, (int)viewport->Pos.x, (int)viewport->Pos.y);

    // Install GLFW callbacks for secondary viewports
    glfwSetWindowFocusCallback(vd->Window, ImGui_ImplGlfw_WindowFocusCallback);
    glfwSetCursorEnterCallback(vd->Window, ImGui_ImplGlfw_CursorEnterCallback);
    glfwSetCursorPosCallback(vd->Window, ImGui_ImplGlfw_CursorPosCallback);
    glfwSetMouseButtonCallback(vd->Window, ImGui_ImplGlfw_MouseButtonCallback);
    glfwSetScrollCallback(vd->Window, ImGui_ImplGlfw_ScrollCallback);
    glfwSetKeyCallback(vd->Window, ImGui_ImplGlfw_KeyCallback);
    glfwSetCharCallback(vd->Window, ImGui_ImplGlfw_CharCallback);
    glfwSetWindowCloseCallback(vd->Window, ImGui_ImplGlfw_WindowCloseCallback);
    glfwSetWindowPosCallback(vd->Window, ImGui_ImplGlfw_WindowPosCallback);
    glfwSetWindowSizeCallback(vd->Window, ImGui_ImplGlfw_WindowSizeCallback);
    if (bd->ClientApi == GlfwClientApi_OpenGL)
    {
        glfwMakeContextCurrent(vd->Window);
        glfwSwapInterval(0);
    }
}