在窗口周围绘制半透明阴影

时间:2021-01-06 21:35:24

标签: c++ winapi gdi+

我正在尝试做一些类似于 Auslogics Disk Defrag 对其自定义窗口所做的事情:

Dark shadow

可以看出,窗口周围模糊的半透明阴影比标准阴影要暗得多,因此程序必须自己绘制它。问题是,我找不到在窗口周围绘制任何东西透明的方法。

在回答类似问题时,有人建议在实际应用程序窗口后面创建一个稍大的透明窗口(使用 WS_EX_LAYERED + SetLayeredWindowAttributes()),然后在透明窗口上进行半透明绘图。这不仅听起来像一个丑陋的黑客,它实际上并不奏效。例如,如果尝试通过 GDI+ 在透明窗口上绘制半透明黑色矩形,则将 alpha 混合应用于窗口背景颜色(也将是透明颜色)上的形状颜色,然后使用计算出的颜色,显然不是窗口透明度,导致矩形不透明。

2 个答案:

答案 0 :(得分:0)

半透明阴影实际上是由黑色方块的高斯模糊完成的。

<块引用>

您可以使用此效果来创建发光和阴影,并使用 复合效果将结果应用到原始图像。这是 在照片处理中对高光和阴影等过滤器很有用。 您可以将此效果的输出用于照明效果的输入, 像镜面光或漫射光效果,因为 alpha 通道也很模糊,灯光效果使用 alpha 通道来确定表面几何形状作为高度图。

此效果由内置阴影效果使用。

参考:Gaussian blur effect

然后移除标准框架,整个窗口就是你的客户区,这样你就可以在扩展框架中绘制阴影了。

参考:Drawing in the Extended Frame Window

答案 1 :(得分:0)

我想我已经找到了适合我的解决方案。我希望不必为阴影创建额外的窗口,但是我能找到或想到的每种方法都需要我自己绘制所有控件和/或以某种方式纠正它们的 alpha 值。

所以,我使用了一个带有每像素 alpha 的分层窗口。我使用 Direct2D 对其进行绘制,或者,我使用一些具有透明度的 PNG 来显示阴影的边缘和角落,并将它们复制到内存 DC 上。无论哪种方式,我都只需在调整窗口大小时重新创建具有正确尺寸的阴影,然后调用 UpdateLayeredWindowIndirect。这两种方法似乎在 Windows 7 和 10 上运行良好,到目前为止我还没有发现任何故障。

阻止它在任务栏上显示有点棘手。我所知道的所有方法都有缺点。对我来说最有效的是制作主窗口拥有的分层窗口。至少这样它只会在程序实际运行的桌面上可见,不像其他替代方法会强制它显示在每个虚拟桌面上。最后,因为我禁用了该窗口,所以我通过处理 WM_SETCURSOR 与它进行交互。