I would like to get a semi-transparent blurred window in QML on Windows 10 similar to the Fluent Design guidelines (example). I know you can make a transparent window:
Window{
visible: true
color: "transparent"
}
but this doesn't achieve the blur effect I am looking at. I am also aware that one can blur elements inside the windows using QtGraphicalEffects
like FastBlur
but I would like to blur the entire window itself.
Is there a way to achieve this? I have also tried using the QtWinExtras
module and call QtWin::enableBlurBehindWindow
but this doesn't work either:
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);
Ok so I found a solution that turned out to be easier than I thought it would be. Officially Microsoft does not provide an API to achieve what I was looking for. I stumbled across this thread and I found this. From there I adapted the code to my needs, I created a header file containing:
#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
And then in my 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
This enables the "Acrylic Material" effect I was looking for (in QML you have to set the window color to "transparent"
).
actually, I believe this is "glass" material, not "acrylic" since you're not using ACCENT_ENABLE_ACRYLICBLURBEHIND but ACCENT_ENABLE_BLURBEHIND