You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

效果对比

预期效果

预期效果截图

实际效果

实际黑屏效果截图

解决方案

  1. 移除AllowsTransparency="True":WPF的AllowsTransparency是自身实现的透明渲染,会和系统APISetWindowCompositionAttribute的合成效果冲突,导致背景变黑。修改窗口属性,去掉该设置,同时将Background改为Transparent。
  2. 添加半透明底色参数:在AccentPolicy中设置GradientColor,给模糊层添加灰色半透明底色,格式为0xAA RR GG BB(AA为透明度,RR/GG/BB为RGB颜色值)。
  3. 增强模糊效果(可选):设置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 09:44:55