Layered Windows
Windows Forms applications regularly use
the LayeredWindow API when translucent forms are used but the control over it is
rudimentary only allowing you to set the opacity of a given window. The
LayeredWindow API is much more useful than that and is easy to use even though
there is no direct support for it in the .NET framework and we are forced to
resort to interop to get it going.
This article will deal with the simpler
of the two LayeredWindow API calls, SetLayeredWindowAttributes.
Essentially, a layered window is a form
of double buffering. The WM_PAINT call for a layered window is fired as normal
but the hDC returned by the BeginPaint method call refers to an in-memory bitmap
that used to store the contents of the window. That back-buffer can then be
drawn to the screen with an element of transparency by setting the alpha level
of the window. This is the way that Form.Opacity works. The other thing the
SetLayeredWindowAttributes API can do is create a non-rectangular window by
using a transparency colour key. Layered windows with transparent areas defined
in this way are also transparent to mouse clicks in those areas so you can put
layered windows to all sorts of interesting uses. Furthermore, because the alpha
of a layered window may be adjusted at any time, you can create fade-in or out
effects that soften the appearance or disappearance of a window.
HandyClock.
Displaying the time on the taskbar isn't
mandatory and many people chose not to see it forever presented on the screen.
On-screen clock applications are quite commonplace but tend to take up a lot of
screen real-estate for such an infrequently used function. The demo application
for this article shows off a novel use of layered windows in a Windows Forms
control that provides a tiny clock which has hidden powers. Figure 1 shows the
application running the handy clock control.

Figure 1. The handy clock.
Notice how the little clock-face
displays the time. This is updated with the system clock and is dynamic. It's
just about readable at a glance and only takes up 400 pixels of screen
real-estate. If you ever want to get a real view of the time though you only
need to float your mouse over the clock and the image in Figure 2 will give you
a great representation instantly.

Figure 2. The HandyClock's hidden talent.
The big clock fades into view in the
center of the screen, waits for a few seconds and fades away again. It also
fades away if you float the mouse over any part of the clock. This stops if from
interfering with the work you're doing.
Creating the window
If you wish to use the LayeredWindow
system, the window must be created or adjusted to have the WS_EX_LAYERED style.
This can be done by setting up a CreateParams class to contain the correct
settings. In this example, the window is based on NativeWindow and uses the
tooltips_class32 window class for conveinience because it doesn't show up in the
task-bar. This code shows how the CreateParams
are initialized for the creation of the window.
Setting the attributes
There are two distinct settings you can
force onto a layered window. The transparency key colour and the level of alpha.
Under normal circumstances, the window will be rectangular or conform to a
window region if you choose to create one. In the case of the handy clock, the
white background is nominated as the transparent colour. The alpha setting
affects all of the non-transparent pixels and enable you to set the level of
opacity in a range of 0-255 where 0 is fully transparent and 255 is fully
opaque.
The code for the clock uses a timer that
fires 20 times a second to refresh the big clock display. It only remains
on-screen for about four seconds and the clock gradually increases opacity,
remains fully opaque and then fades back to complete transparency before being
destroyed. This code services the timer-tick event and
performs the function of refreshing the clock and setting the attributes.
The tiny clock
This simple class does very little except display a few lines
by calculating the positions and angles of the hands for the clock face and
services the holder of end to create the larger window.
This listing shows the HandyClock control.
The Big Clock
This listing shows the code for the
big clock. For variety, the method of rotating the hands has been changed
form that of the HandyClock class. Matrices are used instead. The principles are
fairly simple. A window with the WM_EX_TRANSPARENT style is created and a timer
is set up to fire at regular intervals. When the timer fires, the current
transparency setting of the window is calculated enabling it to fade in, rest
for a few seconds and fade out again. When the window is painted the white
background is made transparent. White was chosen because a garish colour such as
Magenta which is often used for transparency keys prevents the use of
antialiasing in the draw routine. If Magenta is used all the clock components
seem to have a pink halo around them. Remeber to have a good look at the
Interop explanations and code.
You can find the Source Code files here.
Return to the main index.