WPF 窗体设置亚克力效果
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF 窗体设置亚克力效果相关的知识,希望对你有一定的参考价值。
WPF 窗体设置亚克力效果
控件名:WindowAcrylicBlur
作者: WPFDevelopersOrg - 吴锋
原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers
框架使用大于等于
.NET40
。Visual Studio 2022
。项目使用 MIT 开源许可协议。
WindowAcrylicBlur
设置亚克力颜色。Opacity
设置透明度。
1) 准备WindowAcrylicBlur.cs如下:
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using Microsoft.Win32;
using Microsoft.Windows.Shell;
namespace WPFDevelopers.Controls
internal enum AccentState
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
ACCENT_INVALID_STATE = 5
[StructLayout(LayoutKind.Sequential)]
internal struct AccentPolicy
public AccentState AccentState;
public uint AccentFlags;
public uint GradientColor;
public uint AnimationId;
[StructLayout(LayoutKind.Sequential)]
internal struct WindowCompositionAttributeData
public WindowCompositionAttribute Attribute;
public IntPtr Data;
public int SizeOfData;
internal enum WindowCompositionAttribute
// ...
WCA_ACCENT_POLICY = 19
// ...
internal class WindowOldConfig
public bool AllowsTransparency;
public Brush Background;
public WindowChrome WindowChrome;
public WindowStyle WindowStyle = WindowStyle.SingleBorderWindow;
internal class WindowOSHelper
public static Version GetWindowOSVersion()
var regKey = Registry.LocalMachine.OpenSubKey(@"Software\\Microsoft\\Windows NT\\CurrentVersion");
int major;
int minor;
int build;
int revision;
try
var str = regKey.GetValue("CurrentMajorVersionNumber")?.ToString();
int.TryParse(str, out major);
str = regKey.GetValue("CurrentMinorVersionNumber")?.ToString();
int.TryParse(str, out minor);
str = regKey.GetValue("CurrentBuildNumber")?.ToString();
int.TryParse(str, out build);
str = regKey.GetValue("BaseBuildRevisionNumber")?.ToString();
int.TryParse(str, out revision);
return new Version(major, minor, build, revision);
catch (Exception)
return new Version(0, 0, 0, 0);
finally
regKey.Close();
public class WindowAcrylicBlur : Freezable
private static readonly Color _BackgtoundColor = Color.FromArgb(0x01, 0, 0, 0); //设置透明色 防止穿透
[DllImport("user32.dll")]
internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);
private static bool EnableAcrylicBlur(Window window, Color color, double opacity, bool enable)
if (window == null)
return false;
AccentState accentState;
var vOsVersion = WindowOSHelper.GetWindowOSVersion();
if (vOsVersion > new Version(10, 0, 17763)) //1809
accentState = enable ? AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND : AccentState.ACCENT_DISABLED;
else if (vOsVersion > new Version(10, 0))
accentState = enable ? AccentState.ACCENT_ENABLE_BLURBEHIND : AccentState.ACCENT_DISABLED;
else
accentState = AccentState.ACCENT_DISABLED;
if (opacity > 1)
opacity = 1;
var windowHelper = new WindowInteropHelper(window);
var accent = new AccentPolicy();
var opacityIn = (uint) (255 * opacity);
accent.AccentState = accentState;
if (enable)
var blurColor = (uint) ((color.R << 0) | (color.G << 8) | (color.B << 16) | (color.A << 24));
var blurColorIn = blurColor;
if (opacityIn > 0)
blurColorIn = (opacityIn << 24) | (blurColor & 0xFFFFFF);
else if (opacityIn == 0 && color.A == 0)
blurColorIn = (0x01 << 24) | (blurColor & 0xFFFFFF);
if (accent.GradientColor == blurColorIn)
return true;
accent.GradientColor = blurColorIn;
var accentStructSize = Marshal.SizeOf(accent);
var accentPtr = Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent, accentPtr, false);
var data = new WindowCompositionAttributeData();
data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY;
data.SizeOfData = accentStructSize;
data.Data = accentPtr;
SetWindowCompositionAttribute(windowHelper.Handle, ref data);
Marshal.FreeHGlobal(accentPtr);
return true;
private static void Window_Initialized(object sender, EventArgs e)
if (!(sender is Window window))
return;
var config = new WindowOldConfig
WindowStyle = window.WindowStyle,
AllowsTransparency = window.AllowsTransparency,
Background = window.Background
;
var vWindowChrome = WindowChrome.GetWindowChrome(window);
if (vWindowChrome == null)
window.WindowStyle = WindowStyle.None; //一定要将窗口的背景色改为透明才行
window.AllowsTransparency = true; //一定要将窗口的背景色改为透明才行
window.Background = new SolidColorBrush(_BackgtoundColor); //一定要将窗口的背景色改为透明才行
else
config.WindowChrome = new WindowChrome
GlassFrameThickness = vWindowChrome.GlassFrameThickness
;
window.Background = Brushes.Transparent; //一定要将窗口的背景色改为透明才行
var vGlassFrameThickness = vWindowChrome.GlassFrameThickness;
vWindowChrome.GlassFrameThickness = new Thickness(0, vGlassFrameThickness.Top, 0, 0);
SetWindowOldConfig(window, config);
window.Initialized -= Window_Initialized;
private static void Window_Loaded(object sender, RoutedEventArgs e)
if (!(sender is Window window))
return;
var vBlur = GetWindowAcrylicBlur(window);
if (vBlur != null)
EnableAcrylicBlur(window, vBlur.BlurColor, vBlur.Opacity, true);
window.Loaded -= Window_Loaded;
protected override Freezable CreateInstanceCore()
throw new NotImplementedException();
protected override void OnChanged()
base.OnChanged();
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
base.OnPropertyChanged(e);
#region 开启Win11风格
public static WindowAcrylicBlur GetWindowAcrylicBlur(DependencyObject obj)
return (WindowAcrylicBlur) obj.GetValue(WindowAcrylicBlurProperty);
public static void SetWindowAcrylicBlur(DependencyObject obj, WindowAcrylicBlur value)
obj.SetValue(WindowAcrylicBlurProperty, value);
public static readonly DependencyProperty WindowAcrylicBlurProperty =
DependencyProperty.RegisterAttached("WindowAcrylicBlur", typeof(WindowAcrylicBlur),
typeof(WindowAcrylicBlur),
new PropertyMetadata(default(WindowAcrylicBlur), OnWindowAcryBlurPropertyChangedCallBack));
private static void OnWindowAcryBlurPropertyChangedCallBack(DependencyObject d,
DependencyPropertyChangedEventArgs e)
if (!(d is Window window))
return;
if (e.OldValue == null && e.NewValue == null)
return;
if (e.OldValue == null && e.NewValue != null)
window.Initialized += Window_Initialized;
window.Loaded += Window_Loaded;
if (e.OldValue != null && e.NewValue == null)
var vConfig = GetWindowOldConfig(d);
if (vConfig != null)
window.WindowStyle = vConfig.WindowStyle;
window.AllowsTransparency = vConfig.AllowsTransparency;
window.Background = vConfig.Background;
if (vConfig.WindowChrome != null)
var vWindowChrome = WindowChrome.GetWindowChrome(window);
if (vWindowChrome != null)
vWindowChrome.GlassFrameThickness = vConfig.WindowChrome.GlassFrameThickness;
if (e.OldValue == e.NewValue)
if (!window.IsLoaded)
return;
var vBlur = e.NewValue as WindowAcrylicBlur;
if (vBlur == null)
return;
EnableAcrylicBlur(window, vBlur.BlurColor, vBlur.Opacity, true);
#endregion
#region 内部设置
private static WindowOldConfig GetWindowOldConfig(DependencyObject obj)
return (WindowOldConfig) obj.GetValue(WindowOldConfigProperty);
private static void SetWindowOldConfig(DependencyObject obj, WindowOldConfig value)
obj.SetValue(WindowOldConfigProperty, value);
// Using a DependencyProperty as the backing store for WindowOldConfig. This enables animation, styling, binding, etc...
private static readonly DependencyProperty WindowOldConfigProperty =
DependencyProperty.RegisterAttached("WindowOldConfig", typeof(WindowOldConfig), typeof(WindowAcrylicBlur),
new PropertyMetadata(default(WindowOldConfig)));
#endregion
#region
public Color BlurColor
get => (Color) GetValue(BlurColorProperty);
set => SetValue(BlurColorProperty, value);
// Using a DependencyProperty as the backing store for BlurColor. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BlurColorProperty =
DependencyProperty.Register("BlurColor", typeof(Color), typeof(WindowAcrylicBlur),
new PropertyMetadata(default(Color)));
public double Opacity
get => (double) GetValue(OpacityProperty);
set => SetValue(OpacityProperty, value);
// Using a DependencyProperty as the backing store for Opacity. This enables animation, styling, binding, etc...
public static readonly DependencyProperty OpacityProperty =
DependencyProperty.Register("Opacity", typeof(double), typeof(WindowAcrylicBlur),
new PropertyMetadata(default(double)));
#endregion
2) 使用AcrylicBlurWindowExample.xaml如下:
<Window x:Class="WPFDevelopers.Samples.ExampleViews.AcrylicBlurWindowExample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers"
mc:Ignorable="d" WindowStartupLocation="CenterScreen"
ResizeMode="CanMinimize"
Title="Login" Height="350" Width="400">
<wpfdev:WindowChrome.WindowChrome>
<wpfdev:WindowChrome GlassFrameThickness="0 1 0 0"/>
</wpfdev:WindowChrome.WindowChrome>
<wpfdev:WindowAcrylicBlur.WindowAcrylicBlur>
<wpfdev:WindowAcrylicBlur BlurColor="AliceBlue" Opacity="0.2"/>
</wpfdev:WindowAcrylicBlur.WindowAcrylicBlur>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel HorizontalAlignment="Right"
Orientation="Horizontal"
Grid.Column="1"
wpfdev:WindowChrome.IsHitTestVisibleInChrome="True">
<Button Style="DynamicResource WindowButtonStyle"
Command="Binding CloseCommand,RelativeSource=RelativeSource AncestorType=local:AcrylicBlurWindowExample" Cursor="Hand">
<Path Width="10" Height="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="DynamicResource PathMetroWindowClose"
Fill="Red"
Stretch="Fill" />
</Button>
</StackPanel>
<StackPanel Grid.Row="1" Margin="40,0,40,0"
wpfdev:WindowChrome.IsHitTestVisibleInChrome="True">
<Image Source="/WPFDevelopers.ico" Width="80" Height="80"/>
<TextBox wpfdev:ElementHelper.IsWatermark="True" wpfdev:ElementHelper.Watermark="账户" Margin="0,20,0,0" Cursor="Hand"/>
<PasswordBox wpfdev:ElementHelper.IsWatermark="True" wpfdev:ElementHelper.Watermark="密码" Margin="0,20,0,0" Cursor="Hand"/>
<Button x:Name="LoginButton"
Content="登 录"
Margin="0,20,0,0"
Style="StaticResource PrimaryButton"/>
<Grid Margin="0 20 0 0">
<TextBlock FontSize="12">
<Hyperlink Foreground="Black" TextDecorations="None">忘记密码</Hyperlink>
</TextBlock>
<TextBlock FontSize="12" HorizontalAlignment="Right" Margin="0 0 -1 0">
<Hyperlink Foreground="#4370F5" TextDecorations="None">注册账号</Hyperlink>
</TextBlock>
</Grid>
</StackPanel>
</Grid>
</Window>
3) 使用AcrylicBlurWindowExample.xaml.cs如下:
using System.Windows;
using System.Windows.Input;
using WPFDevelopers.Samples.Helpers;
namespace WPFDevelopers.Samples.ExampleViews
/// <summary>
/// AcrylicBlurWindowExample.xaml 的交互逻辑
/// </summary>
public partial class AcrylicBlurWindowExample : Window
public AcrylicBlurWindowExample()
InitializeComponent();
public ICommand CloseCommand => new RelayCommand(obj =>
Close();
);
鸣谢 - 吴锋
Github|AcrylicBlurWindowExample[1]
码云|AcrylicBlurWindowExample[2]
使用 SetWindowCompositionAttribute 来控制程序的窗口边框和背景可以做 Acrylic 亚克力效果、模糊效果、主题色效果等[3]
参考资料
[1]
Github|AcrylicBlurWindowExample: https://github.com/WPFDevelopersOrg/WPFDevelopers/blob/master/src/WPFDevelopers.Samples/ExampleViews/AcrylicBlurWindowExample.xaml
[2]码云|AcrylicBlurWindowExample: https://gitee.com/WPFDevelopersOrg/WPFDevelopers/blob/master/src/WPFDevelopers.Samples/ExampleViews/AcrylicBlurWindowExample.xaml
[3]使用 SetWindowCompositionAttribute 来控制程序的窗口边框和背景可以做 Acrylic 亚克力效果、模糊效果、主题色效果等: https://blog.walterlv.com/post/set-window-composition-attribute.html
以上是关于WPF 窗体设置亚克力效果的主要内容,如果未能解决你的问题,请参考以下文章