WPF实现窗体亚克力效果的示例代码
作者:驚鏵 发布时间:2022-07-25 10:38:08
标签:WPF,窗体,亚克力
WPF 窗体设置亚克力效果
框架使用大于等于.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)) //1809
accentState = enable ? AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND : AccentState.ACCENT_DISABLED;
else if (vOsVersion > new Version(10, 0))
accentState = enable ? AccentState.ACCENT_ENABLE_BLURBEHIND : AccentState.ACCENT_DISABLED;
else
accentState = 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
#region
public 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();
});
}
}
实现效果
来源:https://mp.weixin.qq.com/s/xFoqJqds249l0LotgDtsLg
0
投稿
猜你喜欢
- mybatis insert foreach循环插入@Insert("<script>" +
- c#开发cad如何预览图块1.定义变量的方法代码如下2. 获取GetDwgImag图像的方法代码3.实现显示DWG文件的方法代码方
- Feign的作用是将Http请求抽象化为一个Interface客户端,可以调用接口的形式来执行Http请求,以达到简化Http调用的目的。F
- Redis 3.X版本引入了集群的新特性,为了保证所开发系统的高可用性项目组决定引用Redis的集群特性。对于Redis数据访问的支持,目前
- 1. 前言本节将对 Spring Security 中的密码编码进行一些探讨。2. 不推荐使用md5首先md5 不是加密算法,是哈希摘要。以
- 简单使用redis-zset实现排行榜此方法实现一个根据某字段的查询次数进行排行,查询的次数越多排行越前(从大到小排序),适用于初学者1.添
- 前言本篇内容:提示语的国际化返回,自定义多语言。本文使用aop方式,拦截接口返回的数据,进行转换。正文 先看这次示例教
- 本文实例为大家分享了Android下载进度监听和通知的具体代码,供大家参考,具体内容如下下载管理器关于下载进度的监听,这个比较简单,以apk
- 温馨提示:本教程的 GitHub 地址为「intellij-idea-tutorial」,欢迎感兴趣的童鞋Star、Fork,纠错。首先,给
- 本文实例为大家分享了java实现简单单链表的具体代码,供大家参考,具体内容如下一、定义:单链表是一种链式存取的数据结构,用一组地址任意的存储
- 网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,
- 一、服务端TcpListener server = new TcpListener(IPAddress.Parse("127.0.
- 众所周知,PDF文档通常是不能编辑和修改的。如果用户需要在PDF文档中签名或者填写其他内容时,就需要PDF文档中有可编辑的域。开发者也经常会
- Java类之间的关系图在Java以及其他的面向对象设计模式中,类与类之间主要有6种关系,他们分别是:依赖、关联、聚合、组合、继承、实现。他们
- Spring内置 * 对于 Web 应用来说,ServletContext 对象是唯一的,一个 Web 应用,只有一个ServletCont
- Feign使用@RequestLine遇到的坑如何在微服务项目中调用其它项目的接口试使用spring cloud feign声明式调用。/*
- Java中四种访问权限总结一、Java中有四种访问权限, 其中三种有访问权限修饰符,分别为private、public、prot
- 最近在看《.NET游戏编程入门经典 C#篇》 第一章介绍了如何制作俄罗斯方块,自己试了试按照书上的步骤,可算是完成了。于是写下这篇文章留作纪
- 具体实现方式不多说了,请看下文一、前言当下微信公众号几乎已经是每个公司必备的,但是大部分微信公众账号用户体验都欠佳,特别是涉及到用户绑定等,
- 本文主要关注如何使用mybatis/mybatis plus连接SQL Server数据库,因此将省略其他项目配置、代码。框架选择应用框架: