子窗口透明



实现亚克力材质(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);
}
}