在Win32应用中模仿丙烯酸

时间:2017-05-16 11:27:48

标签: windows winapi dwm

微软最近宣布Acrylic, the glass-like material in Fluent Design。它仅作为XAML / UWP呈现,但看起来非常类似于玻璃,除了它可以任意着色并且可以应用于应用程序中的天桥控件以及应用程序的独立窗口。

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

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

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

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

4 个答案:

答案 0 :(得分:6)

如@ zett42的答案所述,我认为它是使用DirectComposition实现的。

一点历史:借助Vista,微软推出了桌面窗口管理器DWM,它是桌面的合成引擎。使用DWM,窗口绘制到纹理,然后在DWM中组合。好处是你可以获得3D动画,透明度等奇特的效果,并且所有东西都是双缓冲的,所以你不会得到渲染工件。

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

快进几年到Windows 8.微软推出了新的" Metro"应用程序(后来"现代",现在" UWP")。在幕后,这些现代应用程序使用新的组合API,DirectComposition。此API也适用于Win32应用程序,现在由DWM本身使用。如果你看一下公共DWM函数,那些与MIL相关的函数已被弃用,因此它支持我的理论,即MS从MIL转向DC。因此,现在我们再次处于初始状态,即应用程序和DWM使用相同的基础架构,我们可以轻松添加一些有趣的效果。

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

我的研究基于Efficient Alpha-Blended Windows: DirectComposition。基本上,你有一个"设备"对应于屏幕,以及" Visual"对应你的窗口内容。你需要改变的是:

  • 您的设备可以为您创建效果。请务必QueryInterface将其IDCompositionDevice3
  • 然后,您可以在SetEffect上致电IDCompositionVisual3

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

作为蓝色镜头,我会看一下GetWindowCompositionAttribute函数。它最近获得了一些有趣的声音标志,例如WCA_VISUAL_OWNER。

答案 1 :(得分:5)

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

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

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

答案 2 :(得分:5)

自Windows 10 v1803(Build 17134.x - RS4 - 2018年4月更新)以来,Rafael Rivera在桌面应用程序中发布了small demo app如何使用Acrylic Blur

enter image description here

基本上static int fifo_flag = 0; static void sigintHandler(int sig_num) { write(1,"in isr\n",strlen("in isr\n")); fifo_flag = 1; } int main(void){ printf("Access-Control-Allow-Origin: *\n"); printf("Content-Type: text/event-stream\n\n"); int fd = 0, index = 0; char buf[MAX_BUF]; #if 0 char *myfifo = "data"; #endif //char * myfifo = "/tmp/omcipipe"; struct stat st; struct sigaction info; info.sa_handler = sigintHandler; //info.sa_flags = /* set to defaulgs a/c to your requirement*/ if (stat(myfifo, &st) != 0) { mkfifo(myfifo, 0666); perror("mkfifo"); } fd = open(myfifo, O_RDONLY | 0666); if(fd == -1){ perror("open"); return 0; } char ch = 0; while(read(fd, &ch, 1) > 0) { sigaction(SIGINT,&info,NULL);/* if ctrl+c is called */ buf[index] = ch; //sleep(1);/* just to observe ctrl+c behaviour, not advised to use */ printf("%c\n",buf[index]); index++; } buf[index] = '\0'; printf("data: %s", buf); printf("\n"); puts( "----closing----"); close(fd); if(fifo_flag == 1) { /*if flag is set, unlink fifo */ unlink(myfifo); /* you can unlink fifo file here */ } return 0; } 有一个新条目enum AccentState

答案 3 :(得分:2)

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

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

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