WPF窗口透明时的背景模糊

16

我正在尝试创建一个WPF应用程序,其中包含一个半透明无边框窗口,可以模糊其后面的背景。

以下是我想要实现的示例:

Screenshot

我尝试使用 DwmEnableBlurBehindWindow,但它只适用于Windows Vista/7。

我正在寻找在Windows 7、8和10上都能使用的解决方案。


你确定它在Windows 8上不起作用吗?这个链接似乎暗示DWM在Windows 8上始终处于开启状态。 - user585968
微软在Windows 8中删除了这个功能。 - David Heffernan
在Windows 8中,您仍然可以使用DwmEnableBlurBehindWindow,但是其行为与预期不同,它不会在应用程序后面模糊,而只是使用基于窗口颜色方案的纯色填充。 - Tom
1
那是因为微软移除了该功能,正如我所说的。 - David Heffernan
4个回答

21

对于任何感兴趣的人,我已经找到了一个Windows 10的解决方案。然而,在Windows 8上似乎不可能实现;正如David Heffernan所提到的,DwmEnableBlurBehindWindow已从Windows 8中删除。然而,Microsoft在Windows 10中重新引入了一种解决方案来实现这种效果。


链接已失效 :/ 在至少放置代码片段的时间会很方便,因为SO还在。 - JazziJeff
1
Github仓库链接:https://github.com/riverar/sample-win10-aeroglass - Scott Solmer

4
我希望我没有来晚。您可以使用SetWindowCompositionAttribute,但是您必须将WindowStyle设置为“None”并实现自己的本机窗口功能和句柄。此外,从自定义控件继承相当复杂。总之,有模糊控件可用。您可以通过浏览“BlurryControls”在NuGet上找到它,或者在GitHub上查看代码。无论哪种方式,我希望这很有帮助。在GitHub上,您还将找到一个示例应用程序。

2

Windows 8

尽管Windows 8已经是一个被彻底忘却的死胡同,但我们仍然需要确保我们的程序在不同版本的系统中表现一致。如果没有动态背景特效,并且窗口相对较小(比如消息框或类似于我们自己应用程序窗口的),则可以在Loaded事件处理程序中采用手动模糊窗口后面的屏幕图像的解决方案。

var screen = window.Owner.PointToScreen(new System.Windows.Point((window.Owner.ActualWidth - window.ActualWidth) / 2, (window.Owner.ActualHeight - window.ActualHeight) / 2));
var rect = new Rectangle((int)screen.X, (int)screen.Y, (int)window.ActualWidth, (int)window.ActualHeight);
var bitmap = new Bitmap(rect.Width, rect.Height);
using (var graphics = Graphics.FromImage(bitmap))
  graphics.CopyFromScreen(rect.Left, rect.Top, 0, 0, rect.Size);
border.Background = new ImageBrush(ApplyGaussianBlur(bitmap.ToBitmapImage())) {
  TileMode = TileMode.None,
  Stretch = Stretch.None,
  AlignmentX = AlignmentX.Center,
  AlignmentY = AlignmentY.Center,
};

其中border是最外层的Border,通常完全为空,仅在Windows 8上使用。

辅助函数是通常的位图转换:

public static BitmapSource ToBitmapImage(this System.Drawing.Bitmap image) {
  var hBitmap = image.GetHbitmap();
  var bitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
  DeleteObject(hBitmap);
  return bitmap;
}

ApplyGaussianBlur() 最好使用像 WriteableBitmapEx 这样的直接位图操作包来解决,需要进行必要的修改。


0

自Windows 8开始,Microsoft移除了玻璃效果。这就解释了为什么你期望的模糊效果在Windows 8及以后的版本中没有观察到。你将不得不学会在这些操作系统上没有它而生活。


我知道在Windows 8中已经移除了玻璃效果,但一定还有一种实现这种效果的方法。例如,我见过其他程序做到了这一点,比如Start10 - Tom
@Tom:这个看起来不像是真正的Aero玻璃效果。从外观上看,似乎该应用程序对背景进行了截图,并将其乘以自己的背景纹理。 - IInspectable
1
@IInspectable:一开始我也是这么想的,但我在它后面运行了一个视频,你可以看到它在移动。我尝试了你提到的方法,通过截屏并将其添加到背景中并应用模糊效果,它确实有效,只是不太理想。如果桌面在窗口打开时发生变化,则幻觉就会被破坏。 - Tom
2
@Tom:我刚刚安装了Windows 10,你说得对:高斯模糊又回来了,应用在了多个UI元素上(开始菜单、时钟/日历、操作中心等)。 - IInspectable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接