简体   繁体   English

WPF玻璃窗口没有边框,没有重新调整焦点

[英]WPF glass window with no border and no resize out of focus

I am trying to create a Aero glass borderless and non-resizable WPF window using the DwmEnableBlurBehindWindow method from the DmwAPI . 我正在尝试使用DmwAPIDwmEnableBlurBehindWindow方法创建一个Aero glass 无边框 且不可调整大小的 WPF窗口。 However, for some strange reason the glass color of this window appears as if the window is out of focus . 但是,由于某些奇怪的原因,此窗口的玻璃颜色看起来好像窗口没有焦点 As you can see in the next three images, the normal windows with borders ( eg figure 1 and 2 ) work just fine and react as expected (dark blue in focus, whitish when out of focus (= non active)). 正如您在接下来的三张图片中看到的那样,带有边框的正常窗口( 例如图1和图2 )工作得很好并且按预期做出反应(焦点为深蓝色,失焦时为白色(=非活动))。

使用ToolWindow的DwmEnableBlurBehindWindowDwmEnableBlurBehindWindow与ToolWindow失焦

The borderless window with resizing allowed, shows the same behavior: 允许调整大小的无边框窗口显示相同的行为:

DwmEnableBlurBehindWindow具有无边框但可调整大小的窗口

The non-resizable borderless window however will always look as if it is out of focus (as you can see in the last figure 3 ) both when it is active and non-active. 然而, 不可调整大小的无边界窗口在它处于活动状态和非活动状态时总是看起来好像没有聚焦(如上图3所示 )。 It always looks whitish: 它总是看起来发白:

DwmEnableBlurBehindWindow具有无边框和不可调整大小的窗口

This is some example code of how I set the glass style: 这是我如何设置玻璃样式的一些示例代码:

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

I tried focusing the window, but that doesn't seem to affect the behavior. 我试着聚焦窗口,但这似乎并没有影响行为。 Any ideas or pointers on how to solve this? 关于如何解决这个问题的任何想法或指示?

I haven't worked much in dwm apis so I may be wrong but I think the default dwm rendering policy is using WindowStyle to figure out rendering. 我在dwm apis中工作不多,所以我可能错了,但我认为默认的dwm渲染策略是使用WindowStyle来计算渲染。 If you disable that policy, it behaves as you'd expect it to. 如果您禁用该策略,它的行为与您期望的一样。

Add the following bit to fix your blues xD 添加以下位来修复你的蓝调xD

const int DWMWA_NCRENDERING_POLICY = 2;
int DWMNCRP_DISABLED = 2;

DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, ref DWMNCRP_DISABLED, sizeof(int));

For details of this voodoo, please check the following resources: 有关此伏都教的详细信息,请查看以下资源:

DwmSetWindowAttribute function DwmSetWindowAttribute函数

DWMWINDOWATTRIBUTE enumeration DWMWINDOWATTRIBUTE枚举

MainWindow.xaml 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 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
            }
        }
    }
}

Screenshot with focus 屏幕截图有焦点

屏幕截图有焦点

Screenshot without focus 没有焦点的截图

没有焦点的Screenoshot

Test Environment 测试环境

OS: Windows 8 - x64 操作系统:Windows 8 - x64

Theme: Standard windows 主题:标准窗户

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM