WPF 窗体设置亚克力效果

2023-11-30 17:20

本文主要是介绍WPF 窗体设置亚克力效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 WPF 窗体设置亚克力效果

控件名:WindowAcrylicBlur

作者: WPFDevelopersOrg  - 吴锋

原文链接:    https://github.com/WPFDevelopersOrg/WPFDevelopers

  • 框架使用大于等于.NET40

  • Visual Studio 2022

  • 项目使用 MIT 开源许可协议。

  • WindowAcrylicBlur 设置亚克力颜色。

  • Opacity 设置透明度。

c7f3087818a44f315cddef317c996722.png

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();});}
}

 鸣谢 - 吴锋

4dec8c8410ec1d3800ba58f262a38c92.gif

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 窗体设置亚克力效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/437871

相关文章

通过React实现页面的无限滚动效果

《通过React实现页面的无限滚动效果》今天我们来聊聊无限滚动这个现代Web开发中不可或缺的技术,无论你是刷微博、逛知乎还是看脚本,无限滚动都已经渗透到我们日常的浏览体验中,那么,如何优雅地实现它呢?... 目录1. 早期的解决方案2. 交叉观察者:IntersectionObserver2.1 Inter

Java实现为PDF设置背景色和背景图片

《Java实现为PDF设置背景色和背景图片》在日常的文档处理中,PDF格式因其稳定性和跨平台兼容性而广受欢迎,本文将深入探讨如何利用Spire.PDFforJava库,以简洁高效的方式为你的PDF文档... 目录库介绍与安装步骤Java 给 PDF 设置背景颜色Java 给 PDF 设置背景图片总结在日常的

C#中通过Response.Headers设置自定义参数的代码示例

《C#中通过Response.Headers设置自定义参数的代码示例》:本文主要介绍C#中通过Response.Headers设置自定义响应头的方法,涵盖基础添加、安全校验、生产实践及调试技巧,强... 目录一、基础设置方法1. 直接添加自定义头2. 批量设置模式二、高级配置技巧1. 安全校验机制2. 类型

python库pydantic数据验证和设置管理库的用途

《python库pydantic数据验证和设置管理库的用途》pydantic是一个用于数据验证和设置管理的Python库,它主要利用Python类型注解来定义数据模型的结构和验证规则,本文给大家介绍p... 目录主要特点和用途:Field数值验证参数总结pydantic 是一个让你能够 confidentl

Java利用Spire.XLS for Java设置Excel表格边框

《Java利用Spire.XLSforJava设置Excel表格边框》在日常的业务报表和数据处理中,Excel表格的美观性和可读性至关重要,本文将深入探讨如何利用Spire.XLSforJava库... 目录Spire.XLS for Java 简介与安装Maven 依赖配置手动安装 JAR 包核心API介

MySQL设置密码复杂度策略的完整步骤(附代码示例)

《MySQL设置密码复杂度策略的完整步骤(附代码示例)》MySQL密码策略还可能包括密码复杂度的检查,如是否要求密码包含大写字母、小写字母、数字和特殊字符等,:本文主要介绍MySQL设置密码复杂度... 目录前言1. 使用 validate_password 插件1.1 启用 validate_passwo

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Go语言编译环境设置教程

《Go语言编译环境设置教程》Go语言支持高并发(goroutine)、自动垃圾回收,编译为跨平台二进制文件,云原生兼容且社区活跃,开发便捷,内置测试与vet工具辅助检测错误,依赖模块化管理,提升开发效... 目录Go语言优势下载 Go  配置编译环境配置 GOPROXYIDE 设置(VS Code)一些基本

小白也能轻松上手! 路由器设置优化指南

《小白也能轻松上手!路由器设置优化指南》在日常生活中,我们常常会遇到WiFi网速慢的问题,这主要受到三个方面的影响,首要原因是WiFi产品的配置优化不合理,其次是硬件性能的不足,以及宽带线路本身的质... 在数字化时代,网络已成为生活必需品,追剧、游戏、办公、学习都离不开稳定高速的网络。但很多人面对新路由器

linux hostname设置全过程

《linuxhostname设置全过程》:本文主要介绍linuxhostname设置全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录查询hostname设置步骤其它相关点hostid/etc/hostsEDChina编程A工具license破解注意事项总结以RHE