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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/282288.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS向后台传递json数组对象

var Obj [];            //一下代码可以循环插入            var returnObj new Object();//创建一个对象returnObj.id “123”&#xff1b;returnObj.money 456“”;Obj.push(returnObj);           JS中将Obj对象进行序列化操作   …

ArrayBlockingQueue跟LinkedBlockingQueue的区别

1.队列中的锁的实现不同 ArrayBlockingQueue中的锁是没有分离的&#xff0c;即生产和消费用的是同一个锁&#xff1b; LinkedBlockingQueue中的锁是分离的&#xff0c;即生产用的是putLock&#xff0c;消费是takeLock 2.在生产或消费时操作不同 ArrayBlockingQueue基于数组&…

jqGrid('setSelection',rowid)报Cannot read property 'multiple' of undefined

项目组非要上jeeweb框架&#xff0c;用jqgrid大量iframe做为前端框架&#xff0c;臃肿不堪。 今天上午&#xff0c;在进行选定操作jqGrid(setSelection,rowid)报Cannot read property multiple of undefined&#xff0c;怎么分析也找不出原因&#xff0c;最后百度搜了一下竟然有…

数据分块加载——BigPipe 技术【类似facebook】

一、原理 分块加载&#xff0c;加载完一块&#xff0c;就先把页面数据刷给用户&#xff0c;再加载下面的&#xff0c;直到加载完毕二、基础需知&#xff1a;三、服务端和php的相应配置 如果想实现分块加载【bigpipe技术】&#xff0c;还需要对nginx.conf 和 php.ini 进行相应配…

Maven -- 在进行war打包时用正式环境的配置覆盖开发环境的配置

我们的配置文件一般都放在 src/main/resource 目录下。 假定我们的正式环境配置放在 src/main/online-resource 目录下。 那么打成war包时&#xff0c;我们希望用online-resource下的配置文件取代resource 下的配置文件。 pom.xml 插件配置&#xff1a; <plugin><gr…

右键一下,哇塞!

面向 Dev 频道的 Windows 预览体验成员微软推送了 Windows 11 预览版Insider Preview Build 25211主要变化1.微软改进了 Windows 11 小组件面板&#xff0c;小组件面板中的添加按钮更加醒目&#xff0c;点击用户头像将打开小组件设置。Windows 11 小组件由 Microsoft Edge 浏览…

前端学习 -- Css -- 内联元素的盒模型

内联元素不能设置width和height&#xff1b;设置水平内边距,内联元素可以设置水平方向的内边距&#xff1a;padding-left&#xff0c;padding-right&#xff1b;垂直方向内边距&#xff0c;内联元素可以设置垂直方向内边距&#xff0c;但是不会影响页面的布局&#xff1b;为元素…

Redis 数据持久化的方案的实现

一、需要了解的基础 1、Redis实现数据持久化的两种实现方式&#xff1a; RDB&#xff1a;指定的时间间隔内保存数据快照 AOF&#xff1a;先把命令追加到操作日志的尾部&#xff0c;保存所有的历史操作二、RDB 实现 Redis数据持久化&#xff08;默认方式&#xff09;1、编辑 red…

div剩余空间填满

div里有一个固定高度的div使其另一个div填满空间&#xff0c;外层div设置的高度为百分比&#xff0c;给外层一个相对定位&#xff0c;设置想要充满的div高度为100%&#xff0c;其中这次有个要求&#xff0c;使其填充div里面的内容距离固定高度div30px&#xff1b;给填充div一个…

快速生成快递柜唯一取件码

曾管理一万多台快递柜&#xff0c;优化了系统中生成唯一取件码的算法。项目&#xff1a;https://github.com/nnhy/PickupCode新建项目&#xff0c;添加 Nuget 应用 NewLife.Redis &#xff0c;借助其Add去重能力。代码如下&#xff1a;private static void Main(string[] args)…

自动调试自动编译五分钟上手

Browsersync能让浏览器实时、快速响应您的文件更改&#xff08;html、js、css、sass、less等&#xff09;并自动刷新页面。更重要的是 Browsersync可以同时在PC、平板、手机等设备下进项调试。 无论您是前端还是后端工程师&#xff0c;使用它将提高您30%的工作效率。 MD5加密&a…

六台机器搭建RedisCluster分布式集群

一、RedisCluster结构二、redis Cluster集群搭建1、修改redis.conf中需要更改的配置 bind 改成当前ip cluster-enabled yes #允许redis集群 cluster-config-file nodes-6379.conf #集群配置文件 cluster-node-timeout 15000 #集群中节点允许失联的最大时间15s 注&#xff1…

C# 的 async/await 其实是stackless coroutine

注&#xff1a; 最近Java 19引入的虚拟线程火热&#xff0c;还有很多人羡慕 go的 coroutine&#xff0c;很多同学一直有一个疑问&#xff1a; C# 有 虚拟线程或者 coroutine吗&#xff0c;下面的这个回答可以解决问题。这里节选的是知乎上的hez2010 的高赞回答&#xff1a;http…

推荐使用typora

最近在网上接触到一款全新的markdown写作工具——typora。 现在它已经是我的主要写作工具了。 甚至我也也会利用它安排自己的工作和任务。 typora介绍 下载链接特色&#xff1a;可以即时渲染markdown语法的书写工具总算找到了&#xff0c;终于不用再纠结发生语法错误&#xff0…

中文词频统计

import jiebafoopen(text.txt,r,encodingutf-8)tfo.read()fo.close() wordsjieba.cut(t)dic{}for w in words: if len(w)1: continue else: dic[w]dic.get(w,0)1wc list(dic.items())wc.sort(keylambda x:x[1],reverse True)for i in range(20): print(wc[i]) 转载于:https:/…

实现html锚点的两种方式

1&#xff0c;a标签name属性。 2&#xff0c;使用标签的id属性&#xff1b;

mysql实现读写分离

一、环境介绍&#xff1a; LNMP vmware workstation pro配置了3个虚拟机&#xff0c;均安装了LNMP环境&#xff1a; Pro &#xff1a;192.168.0.105 Pro2&#xff1a;192.168.0.106 Pro3&#xff1a;192.168.0.107 二、Mysql主从复制同步的实现 https://blo…

[BZOJ1509][NOI2003]逃学的小孩

1509: [NOI2003]逃学的小孩 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 968 Solved: 489[Submit][Status][Discuss]Description Input 第一行是两个整数N&#xff08;3  N  200000&#xff09;和M&#xff0c;分别表示居住点总数和街道总数。以下M行&#xff0c;每行…

十一随笔|读书

十一放假回老家前三天一直下雨&#xff0c;没法帮父母干农活&#xff0c;阴雨天气农村就闲下来了亲戚间走动&#xff0c;长辈们谈论孩子不好好学习&#xff0c;孩子抱怨学习没用大学毕业照样找不到工作。现在大学生就业现状确实不容乐观&#xff0c;当下不好好学习没有拖底&…

yii之behaviors

BaseController: protected $actions [*];protected $except [];protected $mustlogin [];protected $verbs [];// 行为过滤public function behaviors(){return [access > [class > \yii\filters\AccessControl::className(),only > $this->actions, // 针对哪…