Mimicking Acrylic in a Win32 app
Asked Answered
C

4

11

Microsoft recently announced Acrylic, the glass-like material in Fluent Design. It's presented as XAML / UWP only, but looks very similar to glass, except it can be arbitrarily tinted and can apply in-app to flyover controls as well as to the app's standalone windows.

The 'recipe' makes it appear as though it's implemented in XAML itself, not being exposed to the wider system.

Microsoft's recipe for making acrylic: background, blue, blend, tint, noise

A related SO question confirms this (it's devoid of concrete, technical answers, but implies acrylic isn't available through the WinAPI the way glass is.)

How would someone mimic this in a plain old Win32 app? Using glass, and blending? (Which APIs, and what's possible in Win10 Fall Update's glass APIs that was not in Win7?) If the app was created with Win32 but used a DirectX surface for rendering, would it open more possibilities?

Chara answered 16/5, 2017 at 11:27 Comment(1)
This question has some screenshots that give a better impression of the noise effect.Battology
E
10

As mentioned in @zett42's answer, I think it is implemented using DirectComposition.

A little bit of history: With Vista, Microsoft introduced the Desktop Window Manager, DWM, which is a compositing engine for the Desktop. With DWM, windows draw to textures, which are then combined in the DWM. The benefits are that you can get fancy effects like 3D animations, transparency, etc. and everything is double-buffered, so you get no rendering artifacts.

The DWM originally was based on MIL (Media integration layer), which was a scenegraph API I think. Interestingly, WPF which was introduced around that time also used MIL. This was really cool because DWM could see the scene graph of a WPF window, and when it would so effects, such as zooming in a window, it would see it as vectors and not as a bitmap, so it could scale it without artifacts. However, at some point Microsoft forked the version of MIL used in WPF, and this integration was lost.

Fast forward a few years to Windows 8. Microsoft introduced new "Metro" apps (later "Modern", and now "UWP"). Under the hood, these modern apps use a new API for composition, DirectComposition. This API is also available to Win32 apps, and it is now used by DWM itself. If you look at the public DWM functions, some related to MIL are deprecated, so it supports my theory that MS moved away from MIL and towards DC. So now that we are in the initial situation again where apps as well as the DWM use the same infrastructure, we can easily add some interesting effects.

At some point, MS has introduced new blending effects to DirectComposition, provided by the IDCompositionDevice3 interface. Among those is a gaussan blur effect, but also noise, tint, and other effects neccessary. I found a way to apply these effects within my window, but I don't know how to apply them to my window. Unfortunately, I don't have access to my code right now, I'll update my answer when I do.

I based my exploration on the article Efficient Alpha-Blended Windows: DirectComposition. Basically, you have a "Device" corresponding to the screen, and a "Visual" corresponding your window contents. What you have to change is:

  • Your Device can create Effects for you. Remember to QueryInterface it to IDCompositionDevice3.
  • Then, you can call SetEffect on your IDCompositionVisual3.

However, as I said, this only applies to the window contents. I think there must be a secret API to get a parent Visual to the current window from the DWM, and then it should be just a matter of calling SetEffect on that Visual to get the effect. If somebody is skilled with a debugger, it should be possible to find that API by tracing a UWP app that uses the Acyllic effect.

As a shot in the blue, I would look at the GetWindowCompositionAttribute function. It recently gained some interesting sounding flags, such as WCA_VISUAL_OWNER.

Edrisedrock answered 31/5, 2017 at 4:16 Comment(2)
In UWP it's exposed as CreateHostBackdropBrush -- and it does indeed appear to float around dcomp.dll -- but alas MS doesn't have any immediate plans to add HostBackdropBrush to the DirectComposition API set. :(Jannery
Your "shot in the blue" appears to be right as another answer states that there is the new flag ACCENT_ENABLE_ACRYLICBLURBEHIND = 4Battology
E
9

Rafael Rivera posted a small demo app how to use Acrylic Blur in Desktop applications since Windows 10 v1803 (Build 17134.x - RS4 - April 2018 Update)

enter image description here

Basically the enum AccentState has a new entry ACCENT_ENABLE_ACRYLICBLURBEHIND = 4.

Europeanize answered 2/5, 2018 at 15:17 Comment(2)
The related documented Win32 API call is DwmSetWindowAttribute() which is the same as the undocumented SetWindowCompositionAttribute() except that the arguments are passed differently. The relevant code of the sample can be found in MainWindow.xaml.cs.Battology
ACCENT_ENABLE_ACRYLICBLURBEHIND has larger blur radius than using ACCENT_ENABLE_BLURBEHIND, but not completely the same as acrylic brush in UWP. (UWP still has more larger blur radius and other components)Mikamikado
B
5

I think it would be possible to mimic this using Win32 API or at least create a result that comes close.

  • The blur and tinting could be achieved using undocumented SetWindowCompositionAttribute(), which you already linked. This functionality has to be provided by DWM, which is certainly true even for the XAML implementation.
  • I'm not sure what the exclusion blend is supposed to do, at least from the downscaled screenshots on the MS page, it appears to be neglible.
  • The noise texture should be straightforward to do as it's propably just alpha-blended... well... noise. Use a random generator or maybe some perlin noise function?

You may also look into Direct Composition, possibly combined with the WS_EX_NOREDIRECTIONBITMAP extended window style, as explained in the article "High-Performance Window Layering Using the Windows Composition Engine". I have not used this technology yet, but the article states that XAML is based on Direct Composition, which should open up all possibilities.

Battology answered 16/5, 2017 at 20:5 Comment(2)
DirectComposition is something I haven't come across before (is it new in Win10?) and definitely looks the way to go. Thankyou!Chara
@DavidM DirectComposition was introduced in Windows 8.Battology
B
3

In Latest windows 10 device we can combine DWM API and Direct Composition API to recreate the acrylic effect in Win32. In newer Windows we can copy the contents of DWM Thumnail into IDComposition Visual and it can be used to recreate the backdrop for acrylic.

Then the backdrop can be transferred to IDCompositionGaussianBlurEffect to blur the backdrop.

Here is a working Example :Win32 Acrylic Effect

But I highly don't recommend it for production.

Beaufert answered 18/6, 2021 at 3:53 Comment(2)
That's great to know, thankyou. Why don't you recommend it for production? And how well does this work with normal Win32 controls on the window, ie "over" the acrylic?Chara
I didn't recommend it for production because. These are private api that Microsoft uses internally. So they can be changed or removed any time without any prior notice.Beaufert

© 2022 - 2024 — McMap. All rights reserved.