Add acrylic blur & DWM caption color support
build / build (push) Has been cancelled
build / publish (push) Has been cancelled

This commit is contained in:
ema
2026-04-08 01:12:50 +08:00
parent 94b56a885a
commit b22bb3a168
3 changed files with 124 additions and 8 deletions
+58 -3
View File
@@ -168,6 +168,40 @@ public static class WindowHelper
Marshal.FreeHGlobal(accentPtr);
}
public static void EnableAcrylicBlur(Window window, Color tintColor)
{
window.Background = Brushes.Transparent;
var hwnd = new WindowInteropHelper(window).EnsureHandle();
if (!window.AllowsTransparency && HwndSource.FromHwnd(hwnd) is HwndSource hwndSource)
{
hwndSource.CompositionTarget.BackgroundColor = Colors.Transparent;
}
var margins = new Dwmapi.Margins(-1, -1, -1, -1);
Dwmapi.DwmExtendFrameIntoClientArea(hwnd, ref margins);
var accent = new AccentPolicy();
var accentStructSize = Marshal.SizeOf(accent);
accent.AccentState = AccentState.AccentEnableAcrylicblurbehind;
accent.GradientColor = ToAbgr(tintColor, 0.8);
var accentPtr = Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent, accentPtr, false);
var data = new WindowCompositionAttributeData
{
Attribute = WindowCompositionAttribute.WcaAccentPolicy,
SizeOfData = accentStructSize,
Data = accentPtr
};
User32.SetWindowCompositionAttribute(hwnd, ref data);
Marshal.FreeHGlobal(accentPtr);
}
public static void DisableDwmBlur(Window window)
{
var accent = new AccentPolicy();
@@ -202,6 +236,12 @@ public static class WindowHelper
var micaEnabled = 0;
Dwmapi.DwmSetWindowAttribute(hwnd, (uint)Dwmapi.WindowAttribute.MicaEffect, ref micaEnabled, Marshal.SizeOf(typeof(int)));
}
if (Environment.OSVersion.Version >= new Version(10, 0, 22000))
{
var captionColor = -1;
Dwmapi.DwmSetWindowAttribute(hwnd, (uint)Dwmapi.WindowAttribute.CaptionColor, ref captionColor, Marshal.SizeOf(typeof(int)));
}
}
private static void EnableDwmBlur(Window window, bool isDarkTheme, uint dwAttribute, int pvAttribute)
@@ -209,15 +249,21 @@ public static class WindowHelper
// Mica will handle the color
window.Background = Brushes.Transparent;
var hwnd = new WindowInteropHelper(window).Handle;
var hwnd = new WindowInteropHelper(window).EnsureHandle();
if (!window.AllowsTransparency && HwndSource.FromHwnd(hwnd) is HwndSource hwndSource)
{
hwndSource.CompositionTarget.BackgroundColor = Colors.Transparent;
}
if (Environment.OSVersion.Version >= new Version(10, 0, 22000))
{
var captionColor = -2;
Dwmapi.DwmSetWindowAttribute(hwnd, (uint)Dwmapi.WindowAttribute.CaptionColor, ref captionColor, Marshal.SizeOf(typeof(int)));
}
var isDarkThemeInt = isDarkTheme ? 1 : 0;
Dwmapi.DwmSetWindowAttribute(hwnd, (uint)Dwmapi.WindowAttribute.UseImmersiveDarkMode, ref isDarkThemeInt, Marshal.SizeOf(typeof(bool)));
Dwmapi.DwmSetWindowAttribute(hwnd, (uint)Dwmapi.WindowAttribute.UseImmersiveDarkMode, ref isDarkThemeInt, Marshal.SizeOf(typeof(int)));
var margins = new Dwmapi.Margins(-1, -1, -1, -1);
Dwmapi.DwmExtendFrameIntoClientArea(hwnd, ref margins);
@@ -260,7 +306,16 @@ public static class WindowHelper
AccentEnableGradient = 1,
AccentEnableTransparentgradient = 2,
AccentEnableBlurbehind = 3,
AccentInvalidState = 4,
AccentEnableAcrylicblurbehind = 4,
AccentInvalidState = 5,
}
private static uint ToAbgr(Color color, double alphaScale)
{
return (uint)(color.R << 0 |
color.G << 8 |
color.B << 16 |
(int)(color.A * alphaScale) << 24);
}
[StructLayout(LayoutKind.Sequential)]
+3 -3
View File
@@ -33,6 +33,7 @@ public static class Dwmapi
public enum WindowAttribute
{
UseImmersiveDarkMode = 20,
CaptionColor = 35,
SystembackdropType = 38,
MicaEffect = 1029,
}
@@ -44,9 +45,8 @@ public static class Dwmapi
Mica = 2,
Acrylic = 3, // Automatically selects the best Acrylic effect available on the system (Acrylic11 > Acrylic10)
Tabbed = 4,
Acrylic10, // Windows 10 style, supported on Windows 10 and 11
Acrylic11, // Windows 11 style, supported on Windows 11 22523+ (Insider) and 22621+ (Stable)
Acrylic10 = 5, // Windows 10 style, supported on Windows 10 and 11
Acrylic11 = 6, // Windows 11 style, supported on Windows 11 22523+ (Insider) and 22621+ (Stable)
}
[DllImport("DwmApi.dll")]
+63 -2
View File
@@ -29,7 +29,9 @@ using System.Windows.Shell;
using Wpf.Ui.Violeta.Controls;
using static QuickLook.Common.NativeMethods.Dwmapi;
using Brush = System.Windows.Media.Brush;
using Color = System.Windows.Media.Color;
using FontFamily = System.Windows.Media.FontFamily;
using SolidColorBrush = System.Windows.Media.SolidColorBrush;
using Size = System.Windows.Size;
namespace QuickLook;
@@ -180,6 +182,7 @@ public partial class ViewerWindow : Window
&& SystemParameters.IsGlassEnabled
&& !App.IsGPUInBlacklist;
var backdrop = GetBackdropOption();
var keepsTransparentBackground = useTransparency && backdrop != SystembackdropType.None;
var windowChrome = WindowChrome.GetWindowChrome(this);
windowChrome?.GlassFrameThickness = useTransparency ? new Thickness(1) : new Thickness(0);
@@ -194,7 +197,7 @@ public partial class ViewerWindow : Window
}
var customColor = SettingHelper.Get("WindowBackgroundColor", string.Empty, "QuickLook");
if (!string.IsNullOrEmpty(customColor))
if (!keepsTransparentBackground && !string.IsNullOrEmpty(customColor))
{
try
{
@@ -249,8 +252,45 @@ public partial class ViewerWindow : Window
}
else if (App.IsWin10)
{
var acrylicTint = GetAcrylicTintColor();
WindowHelper.DisableDwmBlur(this);
WindowHelper.EnableBlur(this);
WindowHelper.EnableAcrylicBlur(this, acrylicTint);
}
else
{
Background = (Brush)FindResource("MainWindowBackgroundNoTransparent");
}
break;
case SystembackdropType.Acrylic10:
if (App.IsWin10 || App.IsWin11)
{
var acrylicTint = GetAcrylicTintColor();
WindowHelper.DisableDwmBlur(this);
WindowHelper.EnableAcrylicBlur(this, acrylicTint);
}
else
{
Background = (Brush)FindResource("MainWindowBackgroundNoTransparent");
}
break;
case SystembackdropType.Acrylic11:
if (App.IsWin11 && Environment.OSVersion.Version >= new Version(10, 0, 22523))
{
WindowHelper.DisableDwmBlur(this);
WindowHelper.EnableBackdropAcrylicBlur(this, CurrentTheme == Themes.Dark);
}
else if (App.IsWin10 || App.IsWin11)
{
var acrylicTint = GetAcrylicTintColor();
WindowHelper.DisableDwmBlur(this);
WindowHelper.EnableAcrylicBlur(this, acrylicTint);
}
else
{
@@ -306,6 +346,27 @@ public partial class ViewerWindow : Window
}
}
private Color GetAcrylicTintColor()
{
var customColor = SettingHelper.Get("WindowBackgroundColor", string.Empty, "QuickLook");
if (!string.IsNullOrEmpty(customColor))
{
try
{
return ((SolidColorBrush)new System.Windows.Media.BrushConverter().ConvertFromString(customColor)).Color;
}
catch
{
// ignore invalid color
}
}
return Background is SolidColorBrush currentBrush
? currentBrush.Color
: ((SolidColorBrush)FindResource("MainWindowBackground")).Color;
}
private static SystembackdropType GetBackdropOption()
{
var option = SettingHelper.Get("WindowBackdrop", nameof(SystembackdropType.Auto), "QuickLook")?.Trim();