【问题标题】:WPF glass window with no border and no resize out of focusWPF 玻璃窗口,无边框且无焦点调整大小
【发布时间】:2013-06-19 05:34:18
【问题描述】:

我正在尝试使用 DmwAPI 中的 DwmEnableBlurBehindWindow 方法创建 Aero 玻璃 无边框不可调整大小 WPF 窗口。但是,由于某种奇怪的原因,此窗口的玻璃颜色看起来好像窗口失焦。正如您在接下来的三张图片中看到的那样,带有边框的普通窗口(例如图 1 和 2)工作得很好并且反应如预期(深蓝色聚焦,失焦时发白(= 非活跃))。

允许调整大小的无边框窗口显示相同的行为:

不可调整大小的无边框窗口在处于活动状态时总是看起来好像失焦(您可以在最后一个图 3 中看到)并且不活跃。它总是看起来发白:

这是我如何设置玻璃样式的一些示例代码:

public MainWindow()
{
    InitializeComponent();

    WindowStyle = WindowStyle.None;
    ResizeMode = ResizeMode.NoResize;

    Height = 200;

    Background = Brushes.Transparent;
    Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    var windowInteropHelper = new WindowInteropHelper(this);
    var handle = windowInteropHelper.Handle;
    var mainWindowSrc = HwndSource.FromHwnd(handle);

    if (mainWindowSrc != null)
        if (mainWindowSrc.CompositionTarget != null)
            mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);
    var glassParams = new DwmApi.DwmBlurbehind
    {
        dwFlags = DwmApi.DwmBlurbehind.DWM_BB_ENABLE,
        fEnable = true,
        hRegionBlur = IntPtr.Zero
    };

    IntPtr dis = new IntPtr(2);
    DwmApi.DwmSetWindowAttribute(mainWindowSrc.Handle,
                DwmApi.DwmWindowAttribute.DWMWA_LAST,
                dis,
                sizeof(uint));

    DwmApi.DwmEnableBlurBehindWindow(
        handle,
        glassParams
        );
}

我尝试聚焦窗口,但这似乎不会影响行为。关于如何解决这个问题的任何想法或指示?

【问题讨论】:

    标签: c# wpf aero aero-glass


    【解决方案1】:

    我在 dwm apis 上工作不多,所以我可能错了,但我认为默认的 dwm 渲染策略是使用 WindowStyle 来计算渲染。如果您禁用该策略,它的行为将与您预期的一样。

    添加以下位来修复你的忧郁 xD

    const int DWMWA_NCRENDERING_POLICY = 2;
    int DWMNCRP_DISABLED = 2;
    
    DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, ref DWMNCRP_DISABLED, sizeof(int));
    

    有关此巫术的详细信息,请查看以下资源:

    DwmSetWindowAttribute function

    DWMWINDOWATTRIBUTE enumeration

    MainWindow.xaml

    <Window x:Class="dwm.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525"/>
    

    MainWindow.xaml.cs

    using System;
    using System.Runtime.InteropServices;
    using System.Windows;
    using System.Windows.Interop;
    using System.Windows.Media;
    
    namespace dwm
    {
        public partial class MainWindow
        {
            [DllImport("dwmapi.dll", PreserveSig = false)]
            public static extern void DwmEnableBlurBehindWindow(IntPtr hwnd, ref DwmBlurbehind blurBehind);
    
            [DllImport("dwmapi.dll", PreserveSig = true)]
            private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
    
            public MainWindow()
            {
                InitializeComponent();
            }
    
            protected override void OnSourceInitialized(EventArgs e)
            {
                base.OnSourceInitialized(e);
    
                var bb = new DwmBlurbehind
                {
                    dwFlags = CoreNativeMethods.DwmBlurBehindDwFlags.DwmBbEnable,
                    Enabled = true
                };
    
                WindowStartupLocation = WindowStartupLocation.CenterScreen;
                Background = Brushes.Transparent;
                ResizeMode = ResizeMode.NoResize;
                WindowStyle = WindowStyle.None;
    
                Focus();
    
                var hwnd = new WindowInteropHelper(this).Handle;
    
                HwndSource.FromHwnd(hwnd).CompositionTarget.BackgroundColor = Colors.Transparent;
    
                DwmEnableBlurBehindWindow(hwnd, ref bb);
    
                const int dwmwaNcrenderingPolicy = 2;
                var dwmncrpDisabled = 2;
    
                DwmSetWindowAttribute(hwnd, dwmwaNcrenderingPolicy, ref dwmncrpDisabled, sizeof(int));
            }
    
            [StructLayout(LayoutKind.Sequential)]
            public struct DwmBlurbehind
            {
                public CoreNativeMethods.DwmBlurBehindDwFlags dwFlags;
                public bool Enabled;
                public IntPtr BlurRegion;
                public bool TransitionOnMaximized;
            }
    
            public static class CoreNativeMethods
            {
                public enum DwmBlurBehindDwFlags
                {
                    DwmBbEnable = 1,
                    DwmBbBlurRegion = 2,
                    DwmBbTransitionOnMaximized = 4
                }
            }
        }
    }
    

    焦点屏幕截图

    没有焦点的屏幕截图

    测试环境

    操作系统:Windows 8 - x64

    主题:标准窗口

    【讨论】:

    • 我以前试过这个,现在又试了一次,但不幸的是没有运气:` IntPtr dis = new IntPtr(2); DwmApi.DwmSetWindowAttribute(mainWindowSrc.Handle, DwmApi.DwmWindowAttribute.DWMWA_NCRENDERING_POLICY, dis, sizeof(uint));`
    • 需要查看更多代码,因为我可以完全按照您的描述重现您的问题并使用上面的代码修复它。也许我们可以切换到房间讨论。我在 WPF 房间里几乎所有工作日 (GMT+1) 都在线
    • 我还没有看过你的代码,但我想我找到了你的问题。您使用的是IntPtr,而我使用的是ref int。如果我使用您的方法签名,我的代码确实无法工作。尝试切换到ref int,看看它是否适合你。
    • @StevenHouben 我刚刚使用了您的整个代码位,将方法签名更改为ref int,您的代码也可以正常工作。
    • 谢谢,它有效!还有一件事:关于如何防止窗口失焦的任何想法?我需要它的行为类似于任务栏。
    猜你喜欢
    • 2013-07-12
    • 2011-09-22
    • 1970-01-01
    • 1970-01-01
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多