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窗體亞克力內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!