【问题标题】:Mimicking Acrylic in a Win32 app在 Win32 应用程序中模仿 Acrylic
【发布时间】:2017-10-15 11:05:15
【问题描述】:

微软最近宣布了Acrylic, the glass-like material in Fluent Design。它仅以 XAML / UWP 的形式呈现,但看起来与玻璃非常相似,只是它可以任意着色并且可以在应用内应用到天桥控件以及应用的独立窗口。

“配方”使它看起来好像是 implemented in XAML itself,而不是暴露在更广泛的系统中。

一个相关的 SO 问题 confirms this(它没有具体的技术答案,但暗示丙烯酸不能像玻璃一样通过 WinAPI 获得。)

有人会如何在普通的旧 Win32 应用程序中模仿这一点? 使用玻璃和混合? (哪些 API,what's possible in Win10 Fall Update's glass APIs that was not in Win7?)如果应用是用 Win32 创建的,但使用 DirectX 表面进行渲染,它会带来更多可能性吗?

【问题讨论】:

  • This question 有一些截图可以更好地展示噪音效果。

标签: windows winapi dwm


【解决方案1】:

正如@zett42 的回答中提到的,我认为它是使用 DirectComposition 实现的。

一点点历史:在 Vista 中,Microsoft 引入了桌面窗口管理器 DWM,它是桌面的合成引擎。使用 DWM,窗口绘制到纹理,然后在 DWM 中组合这些纹理。好处是您可以获得 3D 动画、透明度等精美的效果,并且所有内容都是双缓冲的,因此您不会得到渲染伪影。

DWM 最初是基于 MIL(媒体集成层),我认为这是一个场景图 API。有趣的是,当时引入的 WPF 也使用了 MIL。这真的很酷,因为 DWM 可以看到 WPF 窗口的场景图,并且当它看到效果时,例如放大窗口时,它会将其视为矢量而不是位图,因此它可以在没有伪影的情况下对其进行缩放。但是,在某些时候,Microsoft 分叉了 WPF 中使用的 MIL 版本,并且这种集成丢失了。

Windows 8 快进几年了。微软推出了新的“Metro”应用(后来是“现代”,现在是“UWP”)。在底层,这些现代应用程序使用新的 API 进行合成,即 DirectComposition。此 API 也可用于 Win32 应用程序,现在由 DWM 本身使用。如果您查看公共 DWM 功能,一些与 MIL 相关的功能已被弃用,因此它支持我的理论,即 MS 从 MIL 转向 DC。因此,现在我们再次处于应用程序和 DWM 使用相同基础架构的初始情况,我们可以轻松添加一些有趣的效果。

在某些时候,MS 向 DirectComposition 引入了新的混合效果,由 IDCompositionDevice3 接口提供。其中包括高斯模糊效果,还有噪点、色调和其他必要的效果。我找到了一种将这些效果应用到 in 我的窗口的方法,但我不知道如何将它们应用到 我的窗口。不幸的是,我现在无法访问我的代码,当我访问时我会更新我的答案。

我的探索基于文章Efficient Alpha-Blended Windows: DirectComposition。基本上,您有一个与屏幕相对应的“设备”,以及一个与您的窗口内容相对应的“视觉”。你需要改变的是:

  • 您的设备可以为您创建效果。记得把QueryInterface转给IDCompositionDevice3
  • 然后,您可以在您的IDCompositionVisual3 上拨打SetEffect

不过,正如我所说,这只适用于窗口内容。我认为必须有一个秘密 API 来从 DWM 获取当前窗口的父 Visual,然后只需在该 Visual 上调用 SetEffect 即可获得效果。如果有人精通调试器,应该可以通过跟踪使用 Acyllic 效果的 UWP 应用找到该 API。

我想看看 GetWindowCompositionAttribute 函数。它最近获得了一些有趣的标记,例如 WCA_VISUAL_OWNER。

【讨论】:

【解决方案2】:

Rafael Rivera 发布了一个 small demo app 如何在 Windows 10 v1803(内部版本 17134.x - RS4 - 2018 年 4 月更新)后的桌面应用程序中使用 Acrylic Blur

基本上enum AccentState 有一个新条目ACCENT_ENABLE_ACRYLICBLURBEHIND = 4

【讨论】:

  • 相关记录的 Win32 API 调用是 DwmSetWindowAttribute(),它与未记录的 SetWindowCompositionAttribute() 相同,只是参数的传递方式不同。示例的相关代码可以在MainWindow.xaml.cs找到。
  • ACCENT_ENABLE_ACRYLICBLURBEHIND 比使用 ACCENT_ENABLE_BLURBEHIND 具有更大的模糊半径,但与 UWP 中的丙烯酸笔刷不完全相同。 (UWP 仍然有更大的模糊半径和其他组件)
【解决方案3】:

我认为可以使用 Win32 API 模拟这一点,或者至少创建一个接近的结果。

  • 可以使用您已经链接的未记录的SetWindowCompositionAttribute() 来实现模糊和着色。此功能必须由 DWM 提供,即使对于 XAML 实现也是如此。
  • 我不确定排除混合应该做什么,至少从 MS 页面上的缩小屏幕截图来看,它似乎可以忽略不计。
  • 噪声纹理应该很简单,因为它可能只是 alpha 混合...嗯...噪声。使用随机生成器或一些perlin noise function

您还可以查看Direct Composition,可能与WS_EX_NOREDIRECTIONBITMAP extended window style 结合使用,如文章“High-Performance Window Layering Using the Windows Composition Engine”中所述。我还没有使用过这项技术,但文章指出 XAML 是基于直接组合的,这应该会打开所有可能性。

【讨论】:

  • DirectComposition 是我以前没有遇到过的(它是 Win10 中的新功能吗?),而且肯定看起来不错。谢谢!
  • @DavidM DirectComposition 是在 Windows 8 中引入的。
【解决方案4】:

在最新的 windows 10 设备中,我们可以结合 DWM API 和 Direct Composition API 在 Win32 中重新创建丙烯酸效果。在较新的 Windows 中,我们可以将 DWM Thumnail 的内容复制到 IDComposition Visual 中,它可以用于重新创建丙烯酸的背景。

然后背景可以转移到IDCompositionGaussianBlurEffect来模糊背景。

这是一个工作示例:Win32 Acrylic Effect

但我强烈不建议将其用于生产。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    相关资源
    最近更新 更多