【问题标题】:Acrylic material in win32 appwin32 app中的亚克力材质
【发布时间】:2017-05-12 07:21:21
【问题描述】:

微软最近公布了他们新的“流利”设计语言,其中一部分是"acrylic" material。此效果使元素透明并模糊背景。它既可以应用于窗口,使底层窗口的部分发光(背景丙烯酸),也可以应用于窗口中的单个元素,以便其他控件发光(应用内丙烯酸)。它在概念上和视觉上与 macOS 上的活力非常相似。

它是作为 XAML 中的特殊画笔实现的,但我想知道有没有办法在常规 Win32 应用程序中使用它(背景丙烯酸)?效果看起来非常类似于应用于开始菜单和任务栏(由SetWindowCompositionAttribute 处理)的模糊,这让我相信它可能可以通过类似的标志来激活。

一个子问题:我想知道它是如何实现的?它只是您可以在窗口上设置的标志,然后在 DWM 中应用(如 SetWindowCompositionAttribute,或如 Vista 和 7 中的 Aero Glass)?还是 UWP 对 DWM 有某种控制,并且可以设置着色器来控制它的渲染方式?在 Vista 下,当 DWM 第一次被引入时,它与 WPF 有共同的代码,并且它实际上共享(类似 DirectX)的缓冲区和场景图,所以这样的技巧是可能的。 magifier 实用程序可以magnify WPF apps sharply like vector images,但该功能后来丢失了。 MS 在该页面上呈现“丙烯酸”的方式(作为不同的图层,并作为 XAML 画笔实现)让我认为您必须以某种方式将图层注入 DWM 场景图中,这将使其更难或无法使用来自 Win32。

【问题讨论】:

    标签: uwp dwm acrylic-material fluent-design


    【解决方案1】:

    Sciter 4.2 增加了对丙烯酸背景的支持(在 Windows 和 MacOS 上):

    Sciter 中的亚克力主题和类似 UWP 的控件(CSS 样式):

    uSciter 演示浏览器,Windows:

    uSciter 演示浏览器,MacOS:

    Windows 上的 Sciter 是一个普通的 Win32 应用程序(不是 UWP)。

    为了呈现该模糊,它执行以下操作:

    使用WS_EX_NOREDIRECTIONBITMAP ex 标志创建窗口。

    来电:

    struct WINDOWCOMPOSITIONATTRIBDATA {
      WINDOWCOMPOSITIONATTRIB dwAttrib;
      PVOID                   pvData;
      SIZE_T                  cbData;
    };
    
    enum ACCENT_STATE {
      ACCENT_DISABLED = 0,
      ACCENT_ENABLE_GRADIENT = 1,
      ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
      ACCENT_ENABLE_BLURBEHIND = 3,
      ACCENT_ENABLE_ACRYLIC_BLURBEHIND = 4,
      ACCENT_INVALID_STATE = 5
    };
    
    ACCENT_POLICY accent = { ACCENT_ENABLE_ACRYLIC_BLURBEHIND, 0, clr, 0 };
    WINDOWCOMPOSITIONATTRIBDATA data;
    data.dwAttrib = WCA_ACCENT_POLICY;
    data.pvData = &accent;
    data.cbData = sizeof(accent);
    SetWindowCompositionAttribute(get_hwnd(), &data);
    

    其中 clr 是 AGBR,类似于 0xCC000000 用于背景后面的暗模糊。

    使用在 DirectComposition Visual 上设置的 Direct2D 表面渲染内容,使用 IDXGIFactory2::CreateSwapChainForComposition 附加到窗口的交换链

    所有这一切的细节有点模糊和 COM 冗长,叹息(我是 Sciter 的作者)。

    至少你应该使用 Direct2D 进行绘图,以便呈现这样的东西。

    【讨论】:

    • 顺便提一下,这种方式在Windows10 1903+中是行不通的。
    【解决方案2】:

    我刚刚发现这个项目将亚克力引入 WPF:https://github.com/bbougot/AcrylicWPF

    看来你的假设是好的。它使用 SetWindowsCompositionAttribute 并在其上应用着色器。

    【讨论】:

    • 这不是 Windows 10 Fluent Design System 真正的亚克力效果。它使用自己的着色器效果,名为 Noise.fx 并在自己的进程上运行。模糊效果是SetWindowsCompositionAttribute 但不推荐。它只是模拟 Fluent Design System 的亚克力笔刷。
    【解决方案3】:

    Sciter 使用的亚克力效果是通过使用 SetWindowCompositionAttribute(),目前它是滞后的,但我想出了另一种方法来实现相同的亚克力效果,但方法不同。

    看看这个Win32 Acrylic Effect using IDComposition and Direct2D

    【讨论】:

    • 相当整洁,一点也不卡顿!我想知道DwmCreateSharedMultiWindowVisual 是否对底层像素进行采样并将它们拉入您的进程,或者它是否只是告诉 DWM 将此窗口合成到背景之上?我记得旧 Aero 只是在 DWM 中合成了所有(alpha 透明)窗口,而 Acrylic 的文档在某处说它必须出于 安全原因 应用模糊,因为背景位图是在您的进程.
    • 他们也可以使用dwm属性隐藏窗口
    【解决方案4】:

    它的效果是使用较低级别的 XAML 组合 API 创建的,它使用 UWP 的 XAML 合成器,所以我会说我怀疑你能否在 Win32 中本机实现这一点。如果你真的想要它,你可以将你的应用程序带到桌面桥上,然后转换 UI,或者使用当今可用的技术来模仿效果。 (Chrome 等浏览器设法将 Window Chrome 进一步引入他们的应用程序,尽管我不确定您将如何实现丙烯酸效果)。

    【讨论】:

    • “我怀疑你是否能够在 Win32 中实现这一点”——这是可行的,请参阅我的回答。
    • 现在可以通过使用桌面桥和 XAML 岛来实现。
    猜你喜欢
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 2018-06-17
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多