【问题标题】:Blurring the background of a semi-transparent form (like Aero glass)模糊半透明形式的背景(如 Aero 玻璃)
【发布时间】:2012-07-08 20:29:46
【问题描述】:

我有一个具有半透明背景的无边框、不可调整大小的 WPF 表单(WindowStyle=None、AllowsTransparency=True、ResizeMode=NoResize)。这是表单(一个半透明的红色矩形)现在在记事本上运行时的样子:

但是,我希望背景模糊,就像 Aero 玻璃一样,除了没有所有花哨的窗口边框和带条纹的彩色背景 - 我想自己处理。这是我希望它的样子的模型:

我怎样才能以最有效的方式实现这一目标?

WinForms 或 WPF 对我来说很好。希望它应该使用与 Aero 玻璃相同的东西(我可以只在启用 Aero 的情况下使用它),而不是像将下面的屏幕区域捕获为位图并对其进行模糊这样疯狂的东西。

这是我不想要的图片:

我知道这是可能的并且我知道该怎么做,但我不希望整个 Aero 玻璃窗口镀铬、边框和标题栏或窗口具有用户设置的 Aero 玻璃颜色,只是模糊窗口/窗体下方的任何内容的效果。

【问题讨论】:

  • 是的,这在表格内部很模糊。我希望表单本身模糊它下面的其他窗口。
  • 再一次,这在表格内部变得模糊了。我希望表单本身模糊它下面的其他窗口。
  • @FutureMillennium 您想模糊背景中的任何应用程序还是只模糊应用程序的窗口?如果是格式,您可能必须在不使用窗口的情况下进行屏幕截图,将该图像复制到您的窗口并对其进行模糊处理。

标签: c# wpf winforms aero aero-glass


【解决方案1】:

如果你想使用 Aero 模糊,那么你可以使用 DwmEnableBlurBehindWindow api。这是一个利用这个的派生窗口示例。

public class BlurWindow : Window
{
    #region Constants

    private const int WM_DWMCOMPOSITIONCHANGED = 0x031E;
    private const int DWM_BB_ENABLE = 0x1; 

    #endregion //Constants

    #region Structures
    [StructLayout( LayoutKind.Sequential )]
    private struct DWM_BLURBEHIND
    {
        public int dwFlags;
        public bool fEnable;
        public IntPtr hRgnBlur;
        public bool fTransitionOnMaximized;
    }

    [StructLayout( LayoutKind.Sequential )]
    private struct MARGINS
    {
        public int cxLeftWidth;
        public int cxRightWidth;
        public int cyTopHeight;
        public int cyBottomHeight;
    } 
    #endregion //Structures

    #region APIs

    [DllImport( "dwmapi.dll", PreserveSig = false )]
    private static extern void DwmEnableBlurBehindWindow(IntPtr hwnd, ref DWM_BLURBEHIND blurBehind);

    [DllImport( "dwmapi.dll" )]
    private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMargins);

    [DllImport( "dwmapi.dll", PreserveSig = false )]
    private static extern bool DwmIsCompositionEnabled(); 

    #endregion //APIs

    #region Constructor
    public BlurWindow()
    {
        this.WindowStyle = System.Windows.WindowStyle.None;
        this.ResizeMode = System.Windows.ResizeMode.NoResize;
        this.Background = Brushes.Transparent;
    } 
    #endregion //Constructor

    #region Base class overrides
    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized( e );

        if ( Environment.OSVersion.Version.Major >= 6 )
        {
            var hwnd = new WindowInteropHelper( this ).Handle;
            var hs = HwndSource.FromHwnd( hwnd );
            hs.CompositionTarget.BackgroundColor = Colors.Transparent;

            hs.AddHook( new HwndSourceHook( this.WndProc ) );
            this.InitializeGlass( hwnd );
        }
    } 
    #endregion //Base class overrides

    #region Methods

    #region InitializeGlass
    private void InitializeGlass(IntPtr hwnd)
    {
        if ( !DwmIsCompositionEnabled() )
            return;

        // fill the background with glass
        var margins = new MARGINS();
        margins.cxLeftWidth = margins.cxRightWidth = margins.cyBottomHeight = margins.cyTopHeight = -1;
        DwmExtendFrameIntoClientArea( hwnd, ref margins );

        // initialize blur for the window
        DWM_BLURBEHIND bbh = new DWM_BLURBEHIND();
        bbh.fEnable = true;
        bbh.dwFlags = DWM_BB_ENABLE;
        DwmEnableBlurBehindWindow( hwnd, ref bbh );
    }
    #endregion //InitializeGlass

    #region WndProc
    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if ( msg == WM_DWMCOMPOSITIONCHANGED )
        {
            this.InitializeGlass( hwnd );
            handled = false;
        }

        return IntPtr.Zero;
    } 
    #endregion //WndProc 

    #endregion //Methods
}

这里是一个使用 BlurWindow 的 sn-p。

var w = new BlurWindow();
w.Width = 100;
w.Height = 100;
w.MouseLeftButtonDown += (s1, e1) => {
    ((Window)s1).DragMove();
    e1.Handled = true;
};
w.Background = new SolidColorBrush( Color.FromArgb( 75, 255, 0, 0 ) );
w.Show();

【讨论】:

  • 这可能是因为在 Windows 8 中禁用了航空玻璃。我认为 there are hacks 可以重新启用它,但这并不是 MS 真正支持的东西。
【解决方案2】:

我曾经做过类似的事情,但我不需要以下内容:

  1. 我不需要太多移动表单。
  2. 在我的表单下没有发生任何动作。

我做了什么:

  1. 我曾经(以编程方式)最小化我的表单窗口。
  2. 用于在相同坐标处捕获其大小的图像片段的表单。
  3. 应用BlurBitmapEffect 后将该图像设置为背景。

我想这不是一个很好的答案,但我只是在写我所做的!

如果您对这种方法感兴趣,本文将为您提供帮助:http://www.codeproject.com/Articles/91487/Screen-Capture-in-WPF-WinForms-Application

【讨论】:

  • 谢谢,但这就是我要避免的。 Aero 是一个合成窗口管理器,您不必手动截屏一部分屏幕,然后将其模糊为位图。它不仅成本高昂,而且不像 Aero 那样进行硬件加速。
猜你喜欢
  • 2015-11-05
  • 2011-05-05
  • 1970-01-01
  • 2021-11-12
  • 2011-05-06
  • 1970-01-01
  • 1970-01-01
  • 2013-09-28
  • 2010-12-16
相关资源
最近更新 更多