简体   繁体   中英

Draw semi transparent shadow around Window

I'm trying to do something like what Auslogics Disk Defrag does with its custom 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. The problem is, I can't find a way to paint anything transparent around a 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. 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.

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.

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.

Refer: Drawing in the Extended Frame 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.

So, I'm using a layered window with per pixel 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. Either way I simply recreate the shadow with the right dimensions when the window is resized, and call UpdateLayeredWindowIndirect. Both methods seem to be working well on Windows 7 and 10, and so far I haven't found any glitches.

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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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