我想在Windows 10上的QML中获得一个半透明的模糊窗口,类似于Fluent Design指南(示例)。我知道你可以创建一个透明窗口:
Window{
visible: true
color: "transparent"
}
但这并不能达到我正在看的模糊效果。我也知道,人们可以模糊使用windows中的元素QtGraphicalEffects
一样FastBlur
,但我想模糊整个窗口本身。有没有办法做到这一点?我也尝试过使用QtWinExtras
模块并调用,QtWin::enableBlurBehindWindow
但这也不起作用:
QObject *root = engine.rootObjects()[0];
QQuickWindow *window = qobject_cast<QQuickWindow *>(root);
if (!window) {
qFatal("Error: Your root item has to be a window.");
return -1;
}
QtWin::enableBlurBehindWindow(window);
好的,所以我找到了一个比我想象的要容易的解决方案。正式而言,Microsoft不提供实现我所寻找的API。我偶然发现了这个线程,发现了这个。从那里,我根据自己的需要修改了代码,创建了一个包含以下内容的头文件:
#ifndef STRUCTS_H
#define STRUCTS_H
#include <windef.h>
#pragma once
typedef enum _WINDOWCOMPOSITIONATTRIB
{
WCA_UNDEFINED = 0,
WCA_NCRENDERING_ENABLED = 1,
WCA_NCRENDERING_POLICY = 2,
WCA_TRANSITIONS_FORCEDISABLED = 3,
WCA_ALLOW_NCPAINT = 4,
WCA_CAPTION_BUTTON_BOUNDS = 5,
WCA_NONCLIENT_RTL_LAYOUT = 6,
WCA_FORCE_ICONIC_REPRESENTATION = 7,
WCA_EXTENDED_FRAME_BOUNDS = 8,
WCA_HAS_ICONIC_BITMAP = 9,
WCA_THEME_ATTRIBUTES = 10,
WCA_NCRENDERING_EXILED = 11,
WCA_NCADORNMENTINFO = 12,
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
WCA_VIDEO_OVERLAY_ACTIVE = 14,
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
WCA_DISALLOW_PEEK = 16,
WCA_CLOAK = 17,
WCA_CLOAKED = 18,
WCA_ACCENT_POLICY = 19,
WCA_FREEZE_REPRESENTATION = 20,
WCA_EVER_UNCLOAKED = 21,
WCA_VISUAL_OWNER = 22,
WCA_HOLOGRAPHIC = 23,
WCA_EXCLUDED_FROM_DDA = 24,
WCA_PASSIVEUPDATEMODE = 25,
WCA_LAST = 26
} WINDOWCOMPOSITIONATTRIB;
typedef struct _WINDOWCOMPOSITIONATTRIBDATA
{
WINDOWCOMPOSITIONATTRIB Attrib;
PVOID pvData;
SIZE_T cbData;
} WINDOWCOMPOSITIONATTRIBDATA;
typedef enum _ACCENT_STATE
{
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, // RS4 1803
ACCENT_ENABLE_HOSTBACKDROP = 5, // RS5 1809
ACCENT_INVALID_STATE = 6
} ACCENT_STATE;
typedef struct _ACCENT_POLICY
{
ACCENT_STATE AccentState;
DWORD AccentFlags;
DWORD GradientColor;
DWORD AnimationId;
} ACCENT_POLICY;
typedef BOOL (WINAPI *pfnGetWindowCompositionAttribute)(HWND, WINDOWCOMPOSITIONATTRIBDATA*);
typedef BOOL (WINAPI *pfnSetWindowCompositionAttribute)(HWND, WINDOWCOMPOSITIONATTRIBDATA*);
#endif // STRUCTS_H
然后在我的main.cpp
:
#ifdef Q_OS_WIN
#include <QQuickWindow>
#include <windows.h>
#include <WinUser.h>
#include "structs.h" // my header file
#endif
#ifdef Q_OS_WIN
QObject *root = engine.rootObjects()[0];
QQuickWindow *window = qobject_cast<QQuickWindow *>(root);
if (!window) {
qFatal("Error: Your root item has to be a window.");
return -1;
}
HWND hwnd = (HWND)window->winId();
HMODULE hUser = GetModuleHandle(L"user32.dll");
if (hUser)
{
pfnSetWindowCompositionAttribute setWindowCompositionAttribute = (pfnSetWindowCompositionAttribute)GetProcAddress(hUser, "SetWindowCompositionAttribute");
if (setWindowCompositionAttribute)
{
ACCENT_POLICY accent = { ACCENT_ENABLE_BLURBEHIND, 0, 0, 0 };
WINDOWCOMPOSITIONATTRIBDATA data;
data.Attrib = WCA_ACCENT_POLICY;
data.pvData = &accent;
data.cbData = sizeof(accent);
setWindowCompositionAttribute(hwnd, &data);
}
}
#endif
这将启用我一直在寻找的“丙烯酸材料”效果(在QML中,你必须将窗口颜色设置为"transparent"
)。
实际上,我认为这是“玻璃”材料,而不是“丙烯酸”材料,因为您没有使用ACCENT_ENABLE_ACRYLICBLURBEHIND,而是使用ACCENT_ENABLE_BLURBEHIND