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

相关文章

如何设置vim永久显示行号

《如何设置vim永久显示行号》在Linux环境下,vim默认不显示行号,这在程序编译出错时定位错误语句非常不便,通过修改vim配置文件vimrc,可以在每次打开vim时永久显示行号... 目录设置vim永久显示行号1.临时显示行号2.永www.chinasem.cn久显示行号总结设置vim永久显示行号在li

Linux:alias如何设置永久生效

《Linux:alias如何设置永久生效》在Linux中设置别名永久生效的步骤包括:在/root/.bashrc文件中配置别名,保存并退出,然后使用source命令(或点命令)使配置立即生效,这样,别... 目录linux:alias设置永久生效步骤保存退出后功能总结Linux:alias设置永久生效步骤

Spring MVC如何设置响应

《SpringMVC如何设置响应》本文介绍了如何在Spring框架中设置响应,并通过不同的注解返回静态页面、HTML片段和JSON数据,此外,还讲解了如何设置响应的状态码和Header... 目录1. 返回静态页面1.1 Spring 默认扫描路径1.2 @RestController2. 返回 html2

四种简单方法 轻松进入电脑主板 BIOS 或 UEFI 固件设置

《四种简单方法轻松进入电脑主板BIOS或UEFI固件设置》设置BIOS/UEFI是计算机维护和管理中的一项重要任务,它允许用户配置计算机的启动选项、硬件设置和其他关键参数,该怎么进入呢?下面... 随着计算机技术的发展,大多数主流 PC 和笔记本已经从传统 BIOS 转向了 UEFI 固件。很多时候,我们也

Linux中chmod权限设置方式

《Linux中chmod权限设置方式》本文介绍了Linux系统中文件和目录权限的设置方法,包括chmod、chown和chgrp命令的使用,以及权限模式和符号模式的详细说明,通过这些命令,用户可以灵活... 目录设置基本权限命令:chmod1、权限介绍2、chmod命令常见用法和示例3、文件权限详解4、ch

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用

SpringBoot项目引入token设置方式

《SpringBoot项目引入token设置方式》本文详细介绍了JWT(JSONWebToken)的基本概念、结构、应用场景以及工作原理,通过动手实践,展示了如何在SpringBoot项目中实现JWT... 目录一. 先了解熟悉JWT(jsON Web Token)1. JSON Web Token是什么鬼

使用Spring Cache时设置缓存键的注意事项详解

《使用SpringCache时设置缓存键的注意事项详解》在现代的Web应用中,缓存是提高系统性能和响应速度的重要手段之一,Spring框架提供了强大的缓存支持,通过​​@Cacheable​​、​​... 目录引言1. 缓存键的基本概念2. 默认缓存键生成器3. 自定义缓存键3.1 使用​​@Cacheab