【问题标题】:Draw semi transparent shadow around Window在 Window 周围绘制半透明阴影
【发布时间】:2021-04-12 15:59:56
【问题描述】:

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

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

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

【问题讨论】:

  • 是的,我看到了,但它只是解释了如何在保持 Windows 创建的标准阴影的同时创建无边框窗口。我已经知道该怎么做,这不是我想要做的。我想知道的是如何在窗户周围绘制自己的半透明阴影(或任何其他形状)。或者至少改变标准的颜色/暗度,但我认为这是不可能的。
  • 需要“丑陋的黑客”才能获得这种效果。 GDI+ 是一匹老马,无法做到这一点,您必须接受 DirectWrite 支持的那种渲染。已经存在了十多年了,尽管 GUI 框架的支持很微弱。 WPF 可以做到。
  • 是的,我想我可能不得不使用比 GDI+ 更复杂的东西。顺便说一句,当我说丑陋的黑客时,我只是指创建一个额外的窗口。我已经假设我必须创建一个透明的窗口。我确实尝试让我的主窗口部分透明(只是围绕它的一个透明框架),捕获它周围的屏幕部分,在其上混合 alpha,然后将它放在窗口上。它可以工作,但当然,如果我拖动窗口,它会闪烁。我想我会尝试使用 DWM 和 Direct3D 来兼容 Vista/7。

标签: c++ winapi gdi+


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

    参考:Gaussian blur effect

    然后去掉标准框架,整个窗口就是你的客户区,所以你可以在扩展框架中画阴影。

    参考:Drawing in the Extended Frame Window

    【讨论】:

    • 其实我知道如何做高斯模糊。不过,我不知道 Direct2D 有一个功能可以做到这一点,所以很高兴知道。无论如何,我的问题是在整个窗口之外绘制,而不仅仅是在客户区域之外。我已经使用 DWM 在扩展框架上绘制,但我现在要做的是绘制半透明的东西,以便我的阴影后面的任何东西(桌面图标、其他窗口等)仍然可以通过它看到,就像我发布的图片一样。 DwmExtendFrameIntoClientArea 真的可以吗?
    • @MarioD 我没有做过这样的效果。不过我咨询了相关工程师,得到了肯定的答复,DWM是正确的方向。
    猜你喜欢
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多