WPF 窗体设置亚克力效果

阅读: 评论:0

WPF 窗体设置亚克力效果

WPF 窗体设置亚克力效果

 WPF 窗体设置亚克力效果

控件名:WindowAcrylicBlur

作者: WPFDevelopersOrg  - 吴锋

原文链接:    

  • 框架使用大于等于.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(@"SoftwareMicrosoftWindows NTCurrentVersion");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, 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, 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, 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=""xmlns:x=""xmlns:d=""xmlns:mc=""xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"xmlns:wpfdev=""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: .Samples/ExampleViews/AcrylicBlurWindowExample.xaml

[2]

码云|AcrylicBlurWindowExample: .Samples/ExampleViews/AcrylicBlurWindowExample.xaml

[3]

使用 SetWindowCompositionAttribute 来控制程序的窗口边框和背景可以做 Acrylic 亚克力效果、模糊效果、主题色效果等: .html

本文发布于:2024-02-05 04:42:25,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170724407163136.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

下一篇:SO Pricing
标签:窗体   亚克力   效果   WPF
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23