Posted by: MarcoWarm in: JEDI Windows API Headers
“Have you ever seen the rain (on your background image through a Delphi window)?” Ok, sorry to all the Creedence Clearwater Revival fans out there . Today we wanna talk about how to achieve translucent Delphi windows with Windows Vista. I know this does not sound like a big deal for all the lucky owners of Delphi 2007 since this feature is already implemented in this release.
Now let’s have a look at the Desktop Window Manager (DWM) API. The DWM is responsible for the composition of windows on the desktop and the DWM API allows developers to control how composition affects a particular window. As you will see, the DWM is responsible for much more than just “glass”.
When it comes to graphics, the terms can be confusing. Before working with transparency and translucency in Windows we should clarify some of them.
Transparency – Refers to the ability to see through something clearly and without obstruction. Think of it as clear glass. Some applications and APIs use the term transparency to refer to a scale that ranges from “completely” transparent to “completely” opaque.
Translucency – People often use translucency and transparency interchangeably but they actually mean very different things. Translucency refers to the ability to see through something where the background appears unclear whether it is out-of-focus or simply blurry in some way. Windows Vista refers to the glass effect as “transparent glass” when it technically should be called translucent glass.
Opacity – Opacity refers to the state of being opaque and opaque refers to something that is neither transparent nor translucent. Some applications and APIs use the term opacity to refer to a scale that ranges from completely opaque to completely transparent.
Alpha Channel – An alpha channel provides additional information for each pixel in an image that facilitates compositing images together.
Window Regions – A window’s region determines the area within the window where system permits painting. Although Windows 95 supported window regions, it was not until Windows XP that the default theme used regions to present windows with rounded corners. Although the default Windows Vista theme also presents windows with rounded corners, regions are no longer used unless you resort to the Windows Vista Basic theme.
Glass – Glass is the catchy marketing terms that Windows Vista uses to refer to translucency.
Blur – Some of the DWM APIs refer to blur and again this indicates translucency. Presumably, the Windows developers felt it was easier to spell and comprehend.
Desktop Composition – The DWM performs desktop composition, enabling visual effects on the desktop such as glass, 3D window transitions, etc.
RGB – RGB is short for Red, Green and Blue. RGB values are typically packed into a COLORREF (which is just a Cardinal) as follows: $00BBGGRR. As you can see, the first byte is always zero and the remaining three bytes store the individual red, green and blue values in reverse order. Each color value ranges from zero through 255. If all three values are zero then the result is black. If all three values are 255 then the result is white. For example, to represent red specify $000000FF. As you can see, RGB does not provide an alpha channel.
ARGB – ARGB is short for Alpha, Red, Green and Blue. ARGB values are typically packed into an ARGB (which is just a Cardinal) as follows: $AARRGGBB. The first byte stores the alpha value and the remaining three bytes store the red, green and blue values. Note that the color values are stored in the opposite order to RGB.
GDI – The Windows Graphics Device Interface (GDI) API is the original graphics interface used for 2D drawing in Windows. With the exception of a few newer functions, the GDI API does not honor the alpha channel in images. GDI uses RGB values to represent color. The GDI API is wrapped in our beloved Graphics unit.
GDI+ – GDI+ was introduced with Windows XP (and Windows Server 2003) to provide a more capable programming model for 2D drawing, imaging and typography and fully supports alpha blending. GDI+ uses ARGB values to represent color. Although it is not necessary to have GDI+ support in Delphi it is a nice feature and you will need it for drawing black lines and text on “glass” windows. Why is that? You will see. You can obtain the units for GDI+ at http://www.progdigy.com/modules.php?name=gdiplus
If you do not want to read the following stuff you may want to look at the example project at: http://theunknownones.googlecode.com/svn/Libraries/DWMHelper/
The first thing you’ll need is to put the following units in your uses clause
The most important one of them is the first one since it wraps up all the DWM API has to offer. Let us now look how to achieve things. Don’t be afraid of looking into JwaDwmApi.pas. It looks much more complicated than it is. As always Microsoft developers seem to love passing records to their functions. I don’t love that all to much so I wrote some helper functions to make live easier. Those can also be found in TUO’s SVN http://theunknownones.googlecode.com/svn/Libraries/DWMHelper/
The simplest thing to do is to blur the background behind a window:
You can call the function this way:
Now your window looks like this, easy isn’t it`?
HELP!!! My Window is opaque and/or white!!! What did I do wrong?
There can be different reasons for that
As we have learned in the terminology section Delphi and Windows Vista use different color values (RGB vs. ARGB, remember?) Now Delphi draws only RGB colors with the help of GDI routines. Windows however expects ARGB values and assumes to receive one. So the color Windows assumes to be the right one is in most cases the wrong one, due to different byte order and missing alpha value.
How can we pass a valid value to Windows? As we want to receive a translucent window the color we should set to the window is transparent. The ARGB value for transparent is $00000000. Which color could we take in RGB to represent transparent? Right: BLACK. This is a major drawback for us. Most of the labels, buttons and edits etc. use black as their default foreground color. Now They all will become transparent. You may have or will read various attempts using SetLayeredWindowAttributes in order to change the transparent color but it seems this worked with some preview releases of Vista only.
How can you draw something black, transparent etc. on the window? Use GDI+…
The vigilant reader may have observed that DWM_EnableBlurBehind takes a region as parameter. With this parameter you can pass a more or less complicated region to the DWM to tell it where do draw translucent. Try the following:
In order to control the drawing of the blurred window frame you gotta consider another function called DwmExtendFrameIntoClientArea. Because of my lazyness I introduces a little helper:
Result := DwmExtendFrameIntoClientArea(hwnd, lMargins);
Calling it this way
Leads to that result:
Sometimes this effect is referred to as “Sheet Of Glass” I don’t know how Microsoft developers call it since they ‘abuse’ one of their own functions to reach that effect. I personally would have introduced a distinct function for that. But it shows that people at Microsoft put on their pants one leg at a time as well.
Now you sould see something like that:
There isn’t really more magic behind it than that. Of course this is a very raw approach. For example the effect will collapse as soon as the screensaver switched on and back off. One could call the DWM_* routines in CreateWindowHandle for example.