Mimicking Acrylic in a Win32 app

二次信任 提交于 2019-11-30 05:19:25

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.

zett42

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.

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)

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!