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

实现效果

到此这篇关于WPF实现窗体亚克力效果的示例代码的文章就介绍到这了,更多相关WPF窗体亚克力内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • WPF设置窗体可以使用鼠标拖动大小的方法

    本文实例讲述了WPF设置窗体可以使用鼠标拖动大小的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: private void Window_Loaded(object sender, RoutedEventArgs e) {     // 获取窗体句柄     IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(this).Handle; // 获得窗体的 样式     int oldstyle = Nat

  • WPF实现窗体中的悬浮按钮

    WPF实现窗体中的悬浮按钮,按钮可拖动,吸附停靠在窗体边缘. 控件XAML代码: <Button x:Class="SunCreate.Common.Controls.FloatButton" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmln

  • 自定义WPF窗体形状的实战记录

    介绍 你好WPF爱好者. 随着WPF等统一API语言的发明,丰富用户界面变得非常容易. 创建丰富的用户界面只是一个想法. 您需要拥有的是创造性思维和最新技术融合. WPF和Expression Blend在制作丰富的UI应用程序,清晰的图形和非常好的动画方面非常有用. 在创建WPF应用的时候,你第一个看到的就是窗体类.它作为窗体的基础,提供标准的边框.工具条.最大化.最小化和关闭按钮.WPF窗体是XAML文件和后台代码文件的混合体. 背景 我将要发布的是将窗口矩形形状塑造成图像的形状. 它可以是

  • WPF实现抽屉菜单效果的示例代码

    WPF 实现抽屉菜单 框架使用大于等于.NET40: Visual Studio 2022; 项目使用 MIT 开源许可协议: 更多效果可以通过GitHub[1]|码云[2]下载代码; 由于在WPF中没有现成的类似UWP的抽屉菜单,所以我们自己实现一个. 1) DrawerMenu.cs 代码如下. using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System

  • WPF实现3D粒子波浪效果

    本文实例为大家分享了WPF实现3D粒子波浪效果的具体代码,供大家参考,具体内容如下 实现效果如下: 步骤: 1.3D粒子类Particle.cs public class Particle { public Point3D Position;//位置 public double Size;//尺寸 public int XIndex;//X位置标识 public int YIndex;//Y位置标识 } 2.粒子系统ParticleSystem类 public class ParticleSys

  • WPF实现倒计时转场动画效果

    代码如下 一.创建 CountdownTimer.xaml 继承ContentControl代码如下. using System; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windo

  • 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; usi

  • WPF实现文本描边+外发光效果的示例代码

    解决思路: (1)描边效果可以将文本字符串用GDI+生成Bitmap,然后转成BitmapImage,再用WPF的Image控件显示. (2)外发光效果用WPF自带的Effect实现 代码: using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; using System.IO; namespace TextHighLighthDemo { public clas

  • 基于WPF实现弹幕效果的示例代码

    WPF 实现弹幕效果 框架使用大于等于.NET40: Visual Studio 2022; 项目使用 MIT 开源许可协议: 此篇代码目的只是为了分享思路 实现基础弹幕一定是要使用Canvas比较简单,只需实现Left动画从右到左. 弹幕消息使用Border做弹幕背景. 内容使用TextBlock做消息文本展示. 当动画执行完成默认移除Canvas中的弹幕控件. 使用这种方式去加载弹幕GPU会占较高. 1) 准备BarrageExample.xaml如下: <UserControl x:Cla

  • Qt自绘实现苹果按钮滑动效果的示例代码

    用到的类:QTimer,QPaintEvent,QPainter,QRectF 首先,重写绘制事件,需要在头文件加入QPaintEvent头文件,并定义几个变量. bool ison=false; float currentValue; float widthSize,heightSize; 然后加入如下代码: 思路就是鼠标点击,触发paintEvent函数 void MainWindow::mousePressEvent(QMouseEvent *event){ Q_UNUSED(event)

  • 基于WPF实现用户头像选择器的示例代码

    目录 实现思路 核心代码 参考资料 实现思路 制作一个用户头像选择器仿 WeGame 制作一个用户头像选择Canvas为父控件所实现,展示图片使用Image,Path当作上方的蒙版; Canvas:主要用途方便移动Image,设置ClipToBounds="True"裁剪为一个正方形200x200做为主要展示区域; Image:展示需要裁剪的图片: Path:CombinedGeometry[1]绘制蒙版大小200x200效果如下: 当选择一个本地图片的时候判断宽与高谁更大,谁小就将它

  • WPF+Canvas实现平滑笔迹的示例代码

    目录 实现思路 实现效果 实现代码 实现思路 收集路径点集. 平均采样路径点集. 将路径点集转为 LineB. 把 LineB 数据传给 Path. 实现效果 实现代码 1)Vector2D.cs 代码如下 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace WPFDevelopers.Samples.ExampleViews.CanvasHandWriti

  • C#实现跑马灯效果的示例代码

    目录 文章描述 开发环境 开发工具 实现代码 实现效果 文章描述 跑马灯效果,功能效果大家应该都知道,就是当我们的文字过长,整个页面放不下的时候(一般用于公告等),可以让它自动实现来回滚动,以让客户可以看到完整的信息(虽然要多等一会儿时间). 其实对于Winform这种技术,实现任何的动态效果相对来说都比较麻烦.而且一般都需要搭配定时器使用,当然,这次要写的跑马灯效果也是一样的,使用了System.Timers.Timer来实现,关于其他定时器以及用法,之前文章有写过,有兴趣的可以翻一下. 因为

  • 【JS+CSS3】实现带预览图幻灯片效果的示例代码

    一.前期准备 1.1 案例分析 适用场景:单例布局 1.2 方法论 V视图 HTML+CSS+调试 C js实现控制流程 D数据 优化扩展 二.代码 结构 <div class="slider"><!-- 特效区 --> <div class="main"><!-- 主视图区 --> <div class="main_i"> <div class="caption&quo

  • 使用mint-ui实现省市区三级联动效果的示例代码

    引用插件:饿了么的mint-ui组件中的picker功能,具体API可参照官网说明:http://mint-ui.github.io/docs/#/zh-cn2/picker 背景:项目需要做一个省份-城市-地区的选择级联效果,我从gayhub上找了一下,决定使用mint-ui的组件,因为各个功能都很全而且设计跟我们的项目风格类似. 具体实现: 通过阅读官网的实例,大概就能知道这个组件的用法: 在vue中写入组件:<mt-picker :slots="slots" @change

随机推荐