专栏首页walterlv - 吕毅的博客在 Windows 10 上为 WPF 窗口添加模糊特效(就像开始菜单和操作中心那样)

在 Windows 10 上为 WPF 窗口添加模糊特效(就像开始菜单和操作中心那样)

在 Windows 10 上为 WPF 窗口添加模糊特效(就像开始菜单和操作中心那样)

发布于 2017-10-01 16:14 更新于 2018-02-19 22:31

其实我是希望能够找到为 Win32 桌面程序实现 Fluent Design System 效果的,不过一直没找到。倒是发现了一个可以让 Win32 桌面程序做出类似 Windows 10 开始菜单和操作中心那种模糊效果的方法。

写这篇文章并不意味着我推荐大家这么去做,只是希望将方法总结出来,作为一个研究点而已。

本文提供了一个完整的用于在 Windows 10 上实现模糊特效的 C# 类,没有放到 GitHub 也没有其他类型的开源。如果需要直接拿走就好。


为什么不推荐使用?

当初 Windows Vista 推出 Aero 特效后惊艳了世人。然而那还是个 30 帧动画大行其道的年代,即便是后来的 Windows 7 也是如此。这个特效不能使用更高帧率就在于对资源的消耗量太感人。然而 Windows 8/8.1 的推出,动画是其中的一个重要部分——那全屏的感人的流畅的动画,那丝般的顺滑,让人难忘。然而这么流畅是有代价的——需要 60 帧满速运行,而且不能占用太多资源,不然依然卡顿。于是微软只好砍掉了背景高斯模糊功能……充满遗憾……被世人唾骂……

忍受不了世人的咒骂,微软只好再把高斯模糊效果带回 Windows 10。可是,在算法没有从根本上得到改进的情况下,大量的资源消耗依然是不可忽视的问题。所以微软现在只好在少数几个地方先用用,满足大家曾经对于 Aero 的呼声,适当提升一点点审美。

既然微软能用,那么我们也理应能用。然而事实情况是——微软没有任何文档来说明如何实现这样的效果。足以说明微软也不希望他们担心的性能问题大量出现在用户的电脑上。(对于移动设备如 Surface 来说,带来的就是电池可用时间的缩短。)

叛逆者 说,他们终于在特效的算法上有了质的突破,创意来源于平时小组言谈中一点点想法。这就是 Fluent Design System!终于只需要非常少量的计算资源就能达到非常炫酷的现代效果。让人印象深刻的可以替代 Aero 的就属亚克力(Acrylic)了。这效果是在 DWM 进程上运行的(与 Aero 特效一样),所以也不会额外占用应用程序本身的计算资源。

然而,本文探究的方法并不是 Fluent Design System 中的任何部分。依然是微软不期望大家使用的方法,所以,本文并不推荐大家作为真实项目使用,而是作为一种探究学习的途径。

我封装的 API

为了方便大家使用,我封装了一个小的 API。于是大家可以非常方便地使用。

如果你想在 XAML 里用,直接在 MainWindow 上加上以下两行:

xmlns:interop="clr-namespace:Walterlv.Demo.Interop"
interop:WindowBlur.IsEnabled="True"

如果你希望直接在 cs 文件里面写,则这样就好了:

WindowBlur.SetIsEnabled(this, true);

注意这里的 this 指的是 MainWindow

事实上,当你用了上面的 API 试图看一看效果的时候,你会发现其实并不如本文一开始的图片那样。而是一个非常丑陋的窗口:

你需要做两件事情才能变得好看一些:

  1. 设置窗口背景色为透明(Transparent)/半透明(#A0FFFFFF),以便去掉默认的白色背景。
  2. 为窗口设置 WindowChrome 属性,以便去掉标题栏颜色的不同,并修复周围阴影几个像素的半透明偏差。

完整的代码可以看这里:

<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:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:interop="clr-namespace:Walterlv.Demo.Interop"
        mc:Ignorable="d" Title="Blur Demo" Height="350" Width="525"
        interop:WindowBlur.IsEnabled="True"
        Background="Transparent">
    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="-1" />
    </WindowChrome.WindowChrome>
    <Grid Background="#A0FFFFFF">
        <TextBlock Foreground="White"
                   FontSize="20" FontWeight="Light" TextAlignment="Center"
                   HorizontalAlignment="Center" VerticalAlignment="Center">
            <Run Text="Hello World" FontSize="48"/>
            <LineBreak/>
            <Run Text="白底效果" />
            <LineBreak/>
            <Run Text="walterlv.github.io"/>
        </TextBlock>
    </Grid>
</Window>

实现原理——SetWindowCompositionAttribute

WindowBlur 类内部用到了微软从未开放的 API,叛逆者 也已经证实这就是微软在开始菜单和操作中心中用到的 API。这个 API 就是 SetWindowCompositionAttribute

事实上此类中的代码来源也是多个地方找到的,最开始是 C 语言的版本,而后从 Nukepayload2/sample-win10-aeroglass 找到了 C# 的版本,最终基于它改造成了现在这个样子。

代码见本文最后,因为我想把参考资料放到前面来,以感谢前人的努力。


参考资料


附:封装好的 API 代码

本文会经常更新,请阅读原文: https://walterlv.com/post/win10/2017/10/02/wpf-transparent-blur-in-windows-10.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 好的框架需要好的 API 设计 —— API 设计的六个原则

    发布于 2018-06-30 09:23 更新于 2018-08...

    walterlv
  • 深入了解 WPF Dispatcher 的工作原理(PushFrame 部分)

    发布于 2017-09-25 19:49 更新于 2017-09...

    walterlv
  • Windows 中的 UAC 用户账户控制

    阅读本文,你可以初步了解 Windows 上的 UAC 用户账户控制机制。本文不会涉及到 UAC 的底层实现原理和安全边界问题。

    walterlv
  • 电脑硬件详解篇:硬盘

    更早提出闪存概念的是1967年,贝尔实验室江大原(Dawon Kahng,韩裔)和施敏博士(Simon Sze)共同发明了浮栅MOSFET,即所有闪存的基础。

    简单并不简单
  • 软件性能测试(连载5)

    线程单元中的处理器队列的即时长度,如果大于CPU数量+1,说明处理器处于堵塞状态。

    小老鼠
  • Go 语言内存管理(一):系统内存管理

    要搞明白 Go 语言的内存管理,就必须先理解操作系统以及机器硬件是如何管理内存的。因为 Go 语言的内部机制是建立在这个基础之上的,它的设计,本质上就是尽可能的...

    李海彬
  • LintCode Add Digits分析代码

    Given a non-negative integer num, repeatedly add all its digits until the result...

    desperate633
  • 程序员需要了解的硬核知识之磁盘

    我们大家知道,计算机的五大基础部件是 存储器、控制器、运算器、输入和输出设备,其中从存储功能的角度来看,可以把存储器分为内存和 磁盘,内存我们上面的文章已经介绍...

    cxuan
  • limma做RNAseq差异分析

    limma是一个很强大的用于分析芯片的R包,也可以用于RNA-Seq的差异分析 以两个组比较为例:首先输入count表达矩阵,这里也跟其他差异分析R包一样,不...

    生信编程日常
  • Linux GDB jump 命令介绍

    location 可以是程序的行号或者函数的地址,jump 会让程序执行流跳转到指定位置执行,当然其行为也是不可控制的,例如您跳过了某个对象的初始化代码,直接执...

    范蠡

扫码关注云+社区

领取腾讯云代金券