WINAPI/DWMAPI Blur-behind window with irregular shape

前端 未结 3 966
[愿得一人]
[愿得一人] 2021-02-10 15:29

NB: THIS IS NOT A QUESTION ABOUT A BORDERLESS WINDOW.

So, I stumbled upon this program while I was exploring my Start menu the other day on Windows 7:

3条回答
  •  傲寒
    傲寒 (楼主)
    2021-02-10 16:10

    Here's a quickly hacked together WPF solution. It uses the hRgnBlur of the DWM_BLURBEHIND structure, and some interop.

    This example will apply an ellipse-shaped background blur on the window.

    You can easily convert this to an attached property or behavior for MVVM-friendliness. It's also a good idea to listen to the WM_DWMCOMPOSITIONCHANGED message and reapply the blur if needed.

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
    
            WindowStyle = WindowStyle.None;
            AllowsTransparency = true;
    
            SourceInitialized += OnSourceInitialized;
        }
    
        private void OnSourceInitialized(object sender, EventArgs eventArgs)
        {
            if (!NativeMethods.DwmIsCompositionEnabled())
                return;
    
            var hwnd = new WindowInteropHelper(this).Handle;
    
            var hwndSource = HwndSource.FromHwnd(hwnd);
            var sizeFactor = hwndSource.CompositionTarget.TransformToDevice.Transform(new Vector(1.0, 1.0));
    
            Background = System.Windows.Media.Brushes.Transparent;
            hwndSource.CompositionTarget.BackgroundColor = Colors.Transparent;
    
            using (var path = new GraphicsPath())
            {
                path.AddEllipse(0, 0, (int)(ActualWidth * sizeFactor.X), (int)(ActualHeight * sizeFactor.Y));
    
                using (var region = new Region(path))
                using (var graphics = Graphics.FromHwnd(hwnd))
                {
                    var hRgn = region.GetHrgn(graphics);
    
                    var blur = new NativeMethods.DWM_BLURBEHIND
                    {
                        dwFlags = NativeMethods.DWM_BB.DWM_BB_ENABLE | NativeMethods.DWM_BB.DWM_BB_BLURREGION | NativeMethods.DWM_BB.DWM_BB_TRANSITIONONMAXIMIZED,
                        fEnable = true,
                        hRgnBlur = hRgn,
                        fTransitionOnMaximized = true
                    };
    
                    NativeMethods.DwmEnableBlurBehindWindow(hwnd, ref blur);
    
                    region.ReleaseHrgn(hRgn);
                }
            }
        }
    
        [SuppressUnmanagedCodeSecurity]
        private static class NativeMethods
        {
            [StructLayout(LayoutKind.Sequential)]
            public struct DWM_BLURBEHIND
            {
                public DWM_BB dwFlags;
                public bool fEnable;
                public IntPtr hRgnBlur;
                public bool fTransitionOnMaximized;
            }
    
            [Flags]
            public enum DWM_BB
            {
                DWM_BB_ENABLE = 1,
                DWM_BB_BLURREGION = 2,
                DWM_BB_TRANSITIONONMAXIMIZED = 4
            }
    
            [DllImport("dwmapi.dll", PreserveSig = false)]
            public static extern bool DwmIsCompositionEnabled();
    
            [DllImport("dwmapi.dll", PreserveSig = false)]
            public static extern void DwmEnableBlurBehindWindow(IntPtr hwnd, ref DWM_BLURBEHIND blurBehind);
        }
    }
    

    Used with the following XAML:

    
    
        
            
        
    
    

    The result is:

    blur example

提交回复
热议问题