简体   繁体   English

在Window周围画半透明阴影

[英]Draw semi transparent shadow around Window

I'm trying to do something like what Auslogics Disk Defrag does with its custom window:我正在尝试做一些类似于 Auslogics Disk Defrag 对其自定义 window 所做的事情:

黑暗的影子

As can be seen, the blurred semi transparent shadow surrounding the window is much darker than the standard one, so the program must be drawing it by itself.可以看出,window周围的模糊半透明阴影比标准的要暗很多,所以程序一定是自己画的。 The problem is, I can't find a way to paint anything transparent around a window.问题是,我找不到在 window 周围绘制任何透明的方法。

In an answer to a similiar question, someone suggested creating a slightly bigger transparent window (using WS_EX_LAYERED + SetLayeredWindowAttributes() ) behind the actual application window, and then do the translucent drawing on the transparent one.在对类似问题的回答中,有人建议在实际应用程序 window 后面创建一个稍微大一点的透明 window(使用WS_EX_LAYERED + SetLayeredWindowAttributes() ),然后在透明的上面做半透明绘图。 Not only does it sound like an ugly hack, it doesn't actually work.它不仅听起来像一个丑陋的黑客,它实际上并不起作用。 If, for example, one tries to draw a semi transparent black rectangle on a transparent window via GDI+, alpha blending is applied to the shape's color over the window background color (which would also be the transparency color) and then the shape is drawn with the calculated color, which obviously is not the window transparency, resulting in an opaque rectangle.例如,如果尝试通过 GDI+ 在透明 window 上绘制半透明黑色矩形,则 alpha 混合将应用于 window 背景颜色(也将是透明度颜色)上的形状颜色,然后使用计算出来的颜色,显然不是 window 的透明度,导致一个不透明的矩形。

The semi transparent shadow is actually done by Gaussian Blur of the black square.半透明阴影实际上是由黑色方块的高斯模糊完成的。

You can use this effect to create glows and drop shadows and use the composite effect to apply the result to the original image.您可以使用此效果创建发光和阴影,并使用复合效果将结果应用于原始图像。 It is useful in photo processing for filters like highlights and shadows.它在高光和阴影等滤镜的照片处理中很有用。 You can use the output of this effect for input into lighting effects, like the Specular Lighting or Diffuse Lighting effects, because the alpha channel is blurred, too and lighting effects use the alpha channel to determine surface geometry as a height map.您可以使用此效果的 output 来输入光照效果,例如镜面光照或漫反射光照效果,因为 alpha 通道也是模糊的,并且光照效果使用 alpha 通道将表面几何形状确定为高度 map。

This effect is used by the built-in Shadow effect.此效果由内置阴影效果使用。

Refer: Gaussian blur effect参考: 高斯模糊效果

Then remove the standard frame, the entire window is your client area, so you can draw shadow in the extended frame.然后去掉标准框,整个window就是你的客户区,这样就可以在扩展框里画阴影了。

Refer: Drawing in the Extended Frame Window参考: 扩展框架中的图纸 Window

I think I've found a solution that works for me.我想我找到了适合我的解决方案。 I was hoping I wouldn't have to create an extra window just for the shadow, but every method I could find or think of would require me to draw all the controls by myself and/or somehow correct their alpha values.我希望我不必为阴影创建额外的 window,但我能找到或想到的每种方法都需要我自己绘制所有控件和/或以某种方式纠正它们的 alpha 值。

So, I'm using a layered window with per pixel alpha.所以,我使用的是分层的 window 与每像素 alpha。 I paint over it with Direct2D, or, alternatively, I use some PNGs with transparency for the edges and corners of the shadow and copy them on a memory DC.我使用 Direct2D 在其上绘制,或者,我使用一些具有透明度的 PNG 来绘制阴影的边缘和角落,并将它们复制到 memory DC 上。 Either way I simply recreate the shadow with the right dimensions when the window is resized, and call UpdateLayeredWindowIndirect.无论哪种方式,我只需在调整 window 的大小时重新创建具有正确尺寸的阴影,然后调用 UpdateLayeredWindowIndirect。 Both methods seem to be working well on Windows 7 and 10, and so far I haven't found any glitches.这两种方法似乎都在 Windows 7 和 10 上运行良好,到目前为止我还没有发现任何故障。

Preventing it from showing on the taskbar was a bit tricky.阻止它显示在任务栏上有点棘手。 All the ways I know have drawbacks.我知道的所有方法都有缺点。 What worked best for me was making the layered window owned by the main one.对我来说最有效的是制作主要的 window 的分层 window。 At least that way it will only be visible on the desktop where the program is actually running, unlike other alternatives which would force it to show on every virtual desktop.至少这样它只会在程序实际运行的桌面上可见,不像其他替代方案会强制它显示在每个虚拟桌面上。 Finally, because I disable that window, I interact with it by processing WM_SETCURSOR.最后,因为我禁用了 window,所以我通过处理 WM_SETCURSOR 与它进行交互。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM