简体   繁体   中英

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 . 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)).

使用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. 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. If you disable that policy, it behaves as you'd expect it to.

Add the following bit to fix your blues 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

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

Screenshot with focus

屏幕截图有焦点

Screenshot without focus

没有焦点的Screenoshot

Test Environment

OS: Windows 8 - x64

Theme: Standard windows

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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