Win32:如何使阴影支持非矩形分层窗口?
我通过添加 分层窗口 创建了="http://msdn.microsoft.com/en-us/library/ms632680(VS.85).aspx" rel="nofollow noreferrer">WS_EX_LAYERED 扩展样式:
wndClass.ExStyle = wndClass.ExStyle | WS_EX_LAYERED;
Windows 将使用黑色作为色度键颜色值。我将留下一个大的黑色边框以使问题变得明显:
窗口构建完成后,我告诉它 使用黑色作为色度键颜色:
SetLayeredWindowAttributes(hwnd, 0x00000000, 255, LWA_COLORKEY);
现在弹出的分层窗口显示为部分透明:
问题出在最后一步。我想使用 CS_DROPSHADOW 类样式,可用从 Windows XP 开始,创建投影:
wndClass.Style = wndClass.Style | CS_DROPSHADOW;
出现投影,但阴影围绕原始矩形窗口,并且不考虑分层窗口提供的窗口透明度:
有谁知道我在某个地方错过了什么神奇的选项,可以使阴影尊重非矩形分层窗口?
出现此问题的另一个示例是当您不包含 6px 填充/边距时。 Windows® 主题绘制的提示窗口不是矩形的。这会在窗口透明的地方留下一个小的可见间隙,但不会出现阴影:
Microsoft 已成功使其发挥作用,正如您从 Internet Explorer 的提示中看到的那样:
仔细观察 Windows tooltips
类提示窗口。使用 SpyXX - 我可以获得它的窗口矩形和类样式:
SpyXX 说:
Rectangle: (440, 229)-(544, 249), 104x20
Restored Rect: (440, 229)-(544, 249), 104x20
Client Rect: (0, 0)-(104, 20), 104x20
所以一切都指向窗口本身是 104x20 像素,阴影位于窗口本身之外。 (这与 CS_DROPSHADOW
一致。)
接下来我可以看看 tooltips
窗口类的样式:
Windows Styles: 94000001
WS_POPUP 80000000
WS_VISIBLE 10000000
WS_CLIPSIBLINGS 4000000
TTS_ALWAYSTIP 1
Extended Styles: 00080088
WS_EX_LAYERED 80000
WS_EX_TOOLWIN 80
WS_EX_TOPMOST 8
有趣的是,它不使用 CS_SAVEBITS
(0x800
) ;这对于小型、短寿命的窗口很有用。
它也不使用 CS_DROPSHADOW
(0x20000
)。所以现在我想知道它是如何在自己的窗口外面绘制的?
注意: 透明分层窗口被记录为优于区域的首选技术。
编辑: 分层Windows 已随Windows 2000 出现。CS_DropShadow 是随XP 添加的。
i've created a layered window by adding the the WS_EX_LAYERED extended style:
wndClass.ExStyle = wndClass.ExStyle | WS_EX_LAYERED;
Windows will use black as the chroma key color value. i'm going to leave a large border of black to make the problem obvious:
After the window is constructed, i tell it to use black as a chroma-key color:
SetLayeredWindowAttributes(hwnd, 0x00000000, 255, LWA_COLORKEY);
Now the popup layered window appears partially transparent:
The problem is the final step. i want to use CS_DROPSHADOW class style, available since Windows XP, to create a drop-shadow:
wndClass.Style = wndClass.Style | CS_DROPSHADOW;
The drop shadow appears, but the shadow surrounds the original rectangular window, and doesn't take into account the window's transparency provided by the layered window:
Does anyone know what magical option i've missed somewhere that will make the drop shadow honor the non-rectangular layered window?
Another example of where this issue appears is when you don't include the 6px padding/margin. The hint window as drawn by Windows® themes is non-rectangular. This leaves a small visible gap where the window is transparent, but the drop shadow does not appear:
Microsoft has managed to make it work, as you can see from this hint from Internet Explorer:
Looking closer at a Windows tooltips
class hint window. Using SpyXX - i can get its window rect, and class styles:
SpyXX says:
Rectangle: (440, 229)-(544, 249), 104x20
Restored Rect: (440, 229)-(544, 249), 104x20
Client Rect: (0, 0)-(104, 20), 104x20
So everything points to the window itself being 104x20 pixels, with the drop shadow outside the window itself. (Which is consistent with CS_DROPSHADOW
.)
Next i can look at the styles of the tooltips
window class:
Windows Styles: 94000001
WS_POPUP 80000000
WS_VISIBLE 10000000
WS_CLIPSIBLINGS 4000000
TTS_ALWAYSTIP 1
Extended Styles: 00080088
WS_EX_LAYERED 80000
WS_EX_TOOLWIN 80
WS_EX_TOPMOST 8
Interestingly, it doesn't use CS_SAVEBITS
(0x800
); which is useful for small, short-lived, windows.
Nor does it use CS_DROPSHADOW
(0x20000
). So now i wonder how is it drawing outside its own window?
Note: Transparent layered windows is documented as the preferred technique over regions.
Edit: Layered Windows have been around with Windows 2000. CS_DropShadow was added with XP.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
然而,
CS_DROPSHADOW
确实关注区域。如果您使用区域裁剪或以其他方式塑造窗口,则投影将遵循新的轮廓。幸运的是,您可以使用具有分层窗口的区域,并通过将两者结合起来获得您想要的效果。
顺便说一句:tooltips_class32确实使用CS_DROPSHADOW - 您不会在窗口样式中看到它,因为它是类样式,而不是窗口样式。
However,
CS_DROPSHADOW
does pay attention to regions. If you crop or otherwise shape your window using a region, the drop-shadow will follow the new outline.Fortunately, you can use regions with layered windows, and by combining the two get the effect you're looking for.
BTW: tooltips_class32 does use CS_DROPSHADOW - you won't see it in the window styles because it's a class style, not a window style.
为什么不使用 LWA_ALPHA 并将阴影构建到图像中?
编辑以回应您的评论:
A)不会阻止您仅将 alpha 通道 PNG 用于阴影。将 2 个图像合并在一起并用作单个图像。
B) 生成阴影并不难。在图像中,您发布了具有 3 个不同 alpha 值的黑色。
C) 但这不起作用,不是吗?即发挥创意的时间。
D) 那么就不要试图让 Windows 做一些它不会为你做的事情。
E) 完全无关。分层窗口可以为您处理这个问题。
我强烈建议您了解有关分层窗口的更多信息,因为它们可以帮助您实现目标。
Edit2:你有位图。扫描图像并找到哪些位将被颜色键控(通过自己识别黑色)相当容易,然后将其修改为 alpha 为 0,而其他所有内容的 alpha 为 255(注意:您可能必须转换将图像从较低颜色格式转换为 32 位图像,您可以通过创建新的 DC 并复制图像来完成此操作)。这将为您提供与 LWA_ALPHA 和 LWA_COLORKEY 相同的效果。从那里可以很容易地识别边缘处的像素,其中颜色变为(R = 0,G = 0,B = 0,A = 0)。然后,将第一个像素的 alpha 值更改为 192,将其更改为 128,将下面的更改为 64。现在,图像下方有一个 alpha 渐变,看起来像阴影。您可以调整 Alpha 以获得您想要的效果。
Why don't you use LWA_ALPHA and build the shadow into the image?
Edit in reponse to your comment:
A) Doesn't stop you using an alpha channeled PNG for a shadow only. Blt the 2 images together and use as one single image.
B) Its not hard to generate a drop shadow. In the image you posted its black with 3 different alpha values.
C) But it doesn't work does it? ie Time to get creative.
D) Then don't try and get windows to do something it won't do for you.
E) Is entirely irrelevant. Layered windows handle that for you.
I strongly recommend you learn more about layered windows because they CAN help you to your goal.
Edit2: You have the bitmap. Its fairly easy to scan over the image and find which bits will be colour keyed (by identifying the black yourself) and hen modify that to have an alpha of 0 where everything else will have an alpha of 255 (Not: You may have to convert the image to a 32-bit image from a lower colour format, you can do this by creating a new DC and copying the image). This will give you the same effect with LWA_ALPHA as with LWA_COLORKEY. From there its fairly easy to identify the pixel at the edge, where the color changes to (R = 0, G = 0, B = 0, A = 0). You then change that first pixel to have a n alpha of 192, the one blow it to 128 and the one below to 64. You now have an alpha'd gradation below the image that will look like the shadow. You can adjust the alpha to get the effect you want.
CS_DROPSHADOW
仅适用于标准矩形窗口。WS_EX_LAYERED
窗口并不支持所有功能。它们更多的是一种低级的自助方法,可以准确地绘制您想要的内容。要获得投影,您必须自己从图像中的 Alpha 通道生成投影。
CS_DROPSHADOW
only works with standard rectangular windows.WS_EX_LAYERED
windows don't support everything. They are more of a low-level, self-service method to draw exactly what you want.To get a drop shadow, you'll have to generate the drop-shadow yourself from the alpha channel in the image.