本文主要是介绍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)) //1809accentState = enable ? AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND : AccentState.ACCENT_DISABLED;else if (vOsVersion > new Version(10, 0))accentState = enable ? AccentState.ACCENT_ENABLE_BLURBEHIND : AccentState.ACCENT_DISABLED;elseaccentState = 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#regionpublic 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 窗体设置亚克力效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!