WPF实现背景亚克力模糊效果时黑屏问题的解决方法
WPF登录窗口模糊背景失效,显示纯黑色问题排查
问题描述
我英文不太好,正在为公司开发ERP应用,从WinForms转用WPF后,想做一个居中的登录窗口,背景实现类似玻璃的模糊效果(灰色底加模糊)。参考教程用SetWindowCompositionAttribute实现,但我的项目里用这个方法后窗口背景变成纯黑色,达不到预期效果。我对相关枚举、结构体(比如AccentPolicy)和代码原理不太懂,只是复制教程代码,找不到问题所在。
代码展示
XAML代码
<Window x:Class="Diexsa_ERP.MainWindow" 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:Diexsa_ERP" mc:Ignorable="d" Background="#10000000" AllowsTransparency="True" WindowStyle="None" ResizeMode="NoResize" FontSize="20" WindowStartupLocation="CenterScreen" Title="MainWindow" Height="768" Width="1024" MouseDown="Window_MouseDown" Loaded="Window_Loaded"> <Grid HorizontalAlignment="Center" VerticalAlignment="Center" Height="400" Width="400"> <Border CornerRadius="25" Background="White" Opacity="0.5"> </Border> <!--PROFILE PHOTO--> <Ellipse Stroke="White" StrokeThickness="1" Height="100" Width="100" VerticalAlignment="Top" Margin="-50"> <Ellipse.Fill> <ImageBrush ImageSource="C:\Users\Sistemas\source\otros\Sistemas WPF\DIEXSA_ERP\Diexsa_ERP\Diexsa_ERP\assets\images\mandragora.png" /> </Ellipse.Fill> </Ellipse> <!--LOGIN PANEL--> <StackPanel Orientation="Vertical" Width="300" Margin="0, 86, 0, 44" HorizontalAlignment="Center"> <TextBlock Text="UserName:" VerticalAlignment="Center" Margin="10,5,10,0"> </TextBlock> <TextBox Height="50" Margin="10,5,10,0" Background="Transparent" VerticalContentAlignment="Center" Padding="10, 0"> <TextBox.Resources> <Style TargetType="{x:Type Border}"> <Setter Property="CornerRadius" Value="15"></Setter> </Style> </TextBox.Resources> </TextBox> <TextBlock Text="Password:" VerticalAlignment="Center" Margin="10,5,10,0"> </TextBlock> <TextBox Height="50" Background="Transparent" VerticalContentAlignment="Center" Padding="10, 0" Margin="10,5,10,0"> <TextBox.Resources> <Style TargetType="{x:Type Border}"> <Setter Property="CornerRadius" Value="15"></Setter> </Style> </TextBox.Resources> </TextBox> <Button Width="100" Height="50" Content="Login" Margin="10"> <Button.Resources> <Style TargetType="{x:Type Border}"> <Setter Property="CornerRadius" Value="15"></Setter> </Style> </Button.Resources> </Button> <Grid> <TextBlock Text="Forgot Password?" FontSize="12" Margin="10,0"> </TextBlock> <TextBlock Text="Create Account" FontSize="12" HorizontalAlignment="Right" Margin="10,0"> </TextBlock> </Grid> </StackPanel> </Grid> </Window>
窗口后台代码
using Diexsa_ERP.Class; using System.Windows; using System.Windows.Input; namespace Diexsa_ERP { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Window_MouseDown(object sender, MouseButtonEventArgs e) { if(e.ChangedButton == MouseButton.Left) { DragMove(); } } private void Window_Loaded(object sender, RoutedEventArgs e) { DataContext = new WindowBlurEffectCL(this); } } }
AccentPolicy相关枚举与结构体代码
using System; using System.Runtime.InteropServices; namespace Diexsa_ERP.Class { internal enum AccentState { ACCENT_DISABLED=0, ACCENT_ENABLE_GRADIENT=1, ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, ACCENT_ENABLE_BLURBEHIND = 3, ACCENT_ENABLE_ACRLYLICBLURBEHIND = 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 } }
模糊效果实现代码
using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop; namespace Diexsa_ERP.Class { class WindowBlurEffectCL { [DllImport ("user32.dll")] internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data); internal void EnableBlur(Window window) { var windowHelper = new WindowInteropHelper(window); var accent = new AccentPolicy(); accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; 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); } internal WindowBlurEffectCL(Window window) { EnableBlur(window); } } }
效果对比
预期效果

实际效果

解决方案
- 移除
AllowsTransparency="True":WPF的AllowsTransparency是自身实现的透明渲染,会和系统APISetWindowCompositionAttribute的合成效果冲突,导致背景变黑。修改窗口属性,去掉该设置,同时将Background改为Transparent。 - 添加半透明底色参数:在
AccentPolicy中设置GradientColor,给模糊层添加灰色半透明底色,格式为0xAA RR GG BB(AA为透明度,RR/GG/BB为RGB颜色值)。 - 增强模糊效果(可选):设置
AccentFlags=2,可以让模糊效果更明显。
修改后的窗口属性:
Background="Transparent" WindowStyle="None" ResizeMode="NoResize" FontSize="20" WindowStartupLocation="CenterScreen" Title="MainWindow" Height="768" Width="1024" MouseDown="Window_MouseDown" Loaded="Window_Loaded"
修改后的EnableBlur方法:
internal void EnableBlur(Window window) { var windowHelper = new WindowInteropHelper(window); var accent = new AccentPolicy(); accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; // 半透明灰色底色 accent.GradientColor = 0x7F000000; // 增强模糊效果 accent.AccentFlags = 2; 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); }
原理说明
SetWindowCompositionAttribute是Windows系统级API,直接调用系统 compositor 实现模糊效果,而WPF的AllowsTransparency会覆盖系统的合成逻辑,两者冲突导致黑屏。AccentState.ACCENT_ENABLE_BLURBEHIND用于启用窗口背后的模糊,GradientColor可以自定义模糊层的颜色和透明度,AccentFlags用于调整模糊的渲染行为。
内容的提问来源于stack exchange,提问作者Lorenzo C
相关产品推荐
相关产品推荐

