专栏首页walterlv - 吕毅的博客Windows 10 应用创建模糊背景窗口的三种方法

Windows 10 应用创建模糊背景窗口的三种方法

Windows 10 应用创建模糊背景窗口的三种方法

发布于 2018-07-16 11:44 更新于 2018-08-31 23:59

现代的操作系统中创建一张图片的高斯模糊效果非常容易,不过如果要在窗口中获得模糊支持就需要操作系统的原生支持了。iOS/Mac 和 Windows 系统都对此有支持。

本文将介绍三种创建模糊背景窗口的方法。有人可能喜欢称之为毛玻璃窗口、亚克力窗口。


This post is written in multiple languages. Please select yours:

中文 English

最早我是在 StackOverflow 上回答一位网友的提问时写了一份非常长的答案,后来小伙伴建议我将答案改写成博客,于是我就改了。StackOverflow 上的答案在这里:colors - WPF: How to Style my form with Transparency levels - Stack Overflow

三种创建模糊背景窗口的方法

Windows 10 上创建带模糊背景的窗口有三种不同的方法,不过每一种都是既有好处又有坏处的:

  1. 调用 Win32 API —— SetWindowCompositionAttribute,使用这种方式能够获得一个背景轻微透明的窗口。当然,如果需要模拟亚克力效果或者是 iOS/Mac 上的模糊效果就 gg 了。
  1. 为窗口中的背景图片添加 WPF 自带的模糊效果 BlurEffect。这种方式你想获得多大的模糊半径就能获得多大的模糊半径,不过带来的就是更高的性能损耗。同时,还得考虑在移动窗口的时候动态地去更新背景图片并再次模糊。
  1. 使用 Fluent Design System 中的亚克力效果 —— AcrylicBrush。这绝对是 Windows 10 上获得背景模糊效果中视觉效果最好,同时又最省性能的方法了。不过,这种方法只能在 UWP 应用中使用。

SetWindowCompositionAttribute API

SetWindowCompositionAttribute 并没有那么好调用,所以我为此写了一个辅助类类封装对背景模糊效果的调用。使用这个辅助类,你只需要使用一行代码就能开启背景模糊效果。

可以在 XAML 代码中使用 interop:WindowBlur.IsEnabled="True"

<Window x:Class="Walterlv.Demo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:interop="clr-namespace:Walterlv.Demo.Interop"
    mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"
    interop:WindowBlur.IsEnabled="True"
    Background="Transparent">
</Window>

可以在 cs 代码中使用 WindowBlur.SetIsEnabled(this, true)

public class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        WindowBlur.SetIsEnabled(this, true);
    }
}

我为 WindowBlur 类准备了一个 GitHub Gist,在这里:https://gist.github.com/walterlv/752669f389978440d344941a5fcd5b00。你只需要将代码全部复制到你的项目中即可开始使用。

当然,我还写了一篇博客专门讲使用 SetWindowCompositionAttribute API 实现背景模糊效果:在 Windows 10 上为 WPF 窗口添加模糊特效(就像开始菜单和操作中心那样)

WPF BlurEffect

WPF 的 UIElement 都有 Effect 属性,将其设置为 BlurEffect 即可获得控件的高斯模糊效果。

<Window x:Class="MejirdrituTeWarqoudear.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        AllowsTransparency="True" WindowStyle="None"
        Width="540" Height="360">
    <Grid>
        <Image Source="YourImageFile.jpg" Stretch="Fill" Margin="-60">
            <Image.Effect>
                <BlurEffect KernelType="Gaussian" Radius="60" />
            </Image.Effect>
        </Image>
        <Border CornerRadius="60" Margin="30" Background="#7F000000">
            <TextBlock Foreground="White"
                       FontSize="20" FontWeight="Light" TextAlignment="Center"
                       HorizontalAlignment="Center" VerticalAlignment="Center">
                <Run Text="Hello World" FontSize="48"/>
                <LineBreak/>
                <Run Text="walterlv.github.io"/>
            </TextBlock>
        </Border>
    </Grid>
</Window>

特别注意:此方法有严重地性能问题

如果你的窗口是一个异形窗口,例如是具有圆角的矩形,那么你需要额外为控件设置 RectangleGeometry 来裁剪控件。

<Window x:Class="MejirdrituTeWarqoudear.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Width="540" Height="360">
    <Grid>
        <Grid.Clip>
            <RectangleGeometry RadiusX="60" RadiusY="60" Rect="30 30 480 300" />
        </Grid.Clip>
        <Image Source="High+Sierra.jpg" Stretch="Fill" Margin="-60">
            <Image.Effect>
                <BlurEffect KernelType="Gaussian" Radius="60" />
            </Image.Effect>
        </Image>
        <Border Background="#7F000000">
            <TextBlock Foreground="White"
                        FontSize="20" FontWeight="Light" TextAlignment="Center"
                        HorizontalAlignment="Center" VerticalAlignment="Center">
                <Run Text="Hello World" FontSize="48"/>
                <LineBreak/>
                <Run Text="walterlv.github.io"/>
            </TextBlock>
        </Border>
    </Grid>
</Window>

如果是圆形窗口,我另外写了一篇文章来说明进行圆形裁剪:WPF 中使用附加属性,将任意 UI 元素或控件裁剪成圆形(椭圆)

UWP AcyclicBrush

微软的官方文档 Acrylic material - UWP app developer - Microsoft Docs 讲解了如何使用亚克力效果。

本文会经常更新,请阅读原文: https://walterlv.com/post/create-blur-background-window.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (walter.lv@qq.com)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 文件被占用?系统自带的“资源监视器(resmon)”也能帮你找到占用它的真凶

    发布于 2018-03-09 13:26 更新于 2018-05...

    walterlv
  • CentOS 的终端中如何搜索文件

    其中 filename 是你需要找的文件或文件夹的名称。我们没有指定搜索文件的路径,默认是当前文件夹。

    walterlv
  • 阻止某个 NuGet 包意外升级

    2018-06-29 09:59

    walterlv
  • 海量数据迁移之分区并行切分(r2笔记60天)

    在海量的数据迁移中,如果某个表特别大,可以考虑对表中的分区进行切分,比如某个表有100g,还有100个分区,那么可以考虑针对这100个分区,那么可以考虑把这10...

    jeanron100
  • 【死磕Sharding-jdbc】---数据源

    以 com.dangdang.ddframe.rdb.sharding.example.jdbc.Main剖析分库分表配置与实现,其部分源码如下:

    用户1655470
  • Mac 文档阅读软件Dash软件破解版

    代码改变世界-coding
  • 编程小白 | 每日一练(187)

    这道理放在编程上也一并受用。在编程方面有着天赋异禀的人毕竟是少数,我们大多数人想要从编程小白进阶到高手,需要经历的是日积月累的学习,那么如何学习呢?当然是每天都...

    闫小林
  • Appium+python自动化(十三)- 输入中文 - 一次填坑记(超详解)

    无论你在哪里,在做什么都会遇到很多坑,这些坑有些事别人挖的,有些是自己挖的。别人挖的叫坑人,自己挖的叫自杀,儿子挖的叫坑爹。因此在做app自动化道路上也...

    北京-宏哥
  • PHP XDebug 本地调试

    很久没写PHP了、同样很很久没有用XDebug了,近期有个简单的场景要用到,简单记录一下关键步骤。

    许杨淼淼
  • Android App 国际化

    internationalization ( 国际化 )简称 i18n,因为在 i 和 n 之间还有 18 个字符,localization (本地化),简称L...

    QQ音乐技术团队

扫码关注云+社区

领取腾讯云代金券