C# · 12月 23, 2021

c# – 没有边框的WPF玻璃窗口,没有焦点重新调整大小

我正在尝试使用DmwAPI中的DwmEnableBlurBehindWindow方法创建一个Aero glass无边框且不可调整大小的 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); 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 );}

我试着聚焦窗口,但这似乎并没有影响行为.关于如何解决这个问题的任何想法或指示?

解决方法 我没有在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

主题:标准窗户