Scott Hanselman

Learning WPF with BabySmash - Making a Transparent Window with Substance

July 19, '08 Comments [9] Posted in BabySmash | Windows Client | WPF
Sponsored By

NOTE: If you haven't read the first post in this series, I would encourage you do to that first, or check out the BabySmash category. Also check out http://windowsclient.net/ for more developer info on WPF.

BACKGROUND: This is one of a series of posts on learning WPF. I wrote an application for my 2 year old using WPF, but as I'm a Win32-minded programmer, my working app is full of Win32-isms. It's not a good example of a WPF application even though it uses the technology. I'm calling on community (that's you, Dear Reader) to blog about your solutions to different (horrible) selections of my code. You can get the code http://www.codeplex.com/babysmash. Post your solutions on your blog, in the comments, or in the Feedback and we'll all learn WPF together. Pick a single line, a section, or subsystem or the whole app!

Someone wanted the BabySmash Window to have the option to be transparent. I figured, hey, WPF must be good at that, transparency at all. I bet it'll be like one line of code.

I went into my MainWindow.xaml and added these attributes:

Background="Transparent" AllowsTransparency="True" WindowStyle="None" 

Bam! Right? Well, kind of. This made the Window Transparent, but "hollow" in that I couldn't click on it. It was totally invisble, except for my little bit of text at the top. I could "click through" the application to the desktop below.

image

Well, here's why, and if I'd read 4 chapters into Chris Sell's book, I'd have figured this out. ;)

Per Dwayne Need on the WPF Team:

"Windows treats fully transparent layered-windows windows as hollow."

This was interesting because everywhere else in WPF if you have a Brush that is null, that's "hollow" and Transparent is solid. Again, Dwayne:

"This is because a layered window is represented to the OS as a bitmap, so all it can do is look at the pixel values.  It [Windows] cannot differentiate between null and Transparent."

Ah, makes sense. This is where WPF meets the rest of Windows. Ok, but I have complete control over my Brushes and their colors. I can make a Brush that is not just #000000 (Black) but also #01000000 (really really transparent black. Like 1/255th transparent). You've got not just RGB, you've got an Alpha Channel PLUS RGB.

Now if I set my Window's background to this Brush:

new SolidColorBrush(Color.FromArgb(1,0,0,0))

I get the look of transparency, except the Window is still there and I can click on it.

"Your almost-transparent brush fails the Windows transparency test, so windows delivers events to it. If something is 100% transparent then hit testing is bypassed.  If you want transparency and hit testing, define a color with minimal alpha just as you have done.

This was an interesting edge class where WPF's definition of Transparent didn't quite line up with Window's definition.

Once you've created a Window that is transparent like my funky full-screen one,,,

MainWindow m = new MainWindow(this)
{
WindowStartupLocation = WindowStartupLocation.Manual,
Left = s.WorkingArea.Left,
Top = s.WorkingArea.Top,
Width = s.WorkingArea.Width,
Height = s.WorkingArea.Height,
WindowStyle = WindowStyle.None,
Topmost = true,
AllowsTransparency = Settings.Default.TransparentBackground,
Background = (Settings.Default.TransparentBackground ? new SolidColorBrush(Color.FromArgb(1,0,0,0)) : Brushes.WhiteSmoke)
};

...you can't change the Transparency after you've shown it...or else...

image

Chris Sells suggested I set my Window to AllowsTransparency = True all the time, then make a Canvas over the top of it that had an opaque Brush with color and transparency I could change as I liked as it'd be "inside" WPF world and not have to deal with any underlying limitations in Win32.

For now, my not-quite-transparent brush got me the feature I wanted - BabySmash over an existing desktop.

image

Cool.

Technorati Tags: ,,

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Sunday, July 20, 2008 6:08:18 AM UTC
OT, but, I heard on the podcast that you had trouble disabling some keys on the keyboard (win key etc.), you should be able to do this with a low level keyboard hook, not in icky bloated .net of course, but using the raw power of old school win32, you would have to create a win32 dll and call SetWindowsHookEx(... WH_KEYBOARD_LL ...) with pInvoke
Sunday, July 20, 2008 6:26:08 AM UTC
Anders - Take a look a the code...I did use SetWindowsHookEx and set a global keyboard hook but you still (on Vista) can't hook some keys, like Windows-L. The code is at http://www.codeplex.com/babysmash.
Scott Hanselman
Sunday, July 20, 2008 6:44:04 AM UTC
That is a in process hook tho, I can't remember if it applies to LL hooks, but atleast for some of the other hooks, they need to be in a dll and not in process to hook into every process. If that does not work, you would have to write a driver probably (I remember back in the day, the NT kernel power toys (can't remember the exact name of this pack) had an app that would disable the win key for use with games etc.)
Sunday, July 20, 2008 8:01:07 PM UTC
Nice application to get me stared with WPF!
Sunday, July 20, 2008 10:22:01 PM UTC
I seem to get an error when using transparence

check the link below.
link
Friday, July 25, 2008 4:36:09 PM UTC
Have you experienced the ambiguous "Invalid Operation" error with transparencies? I'm working with my first WPF app using a transparent background as well as some transparent controls (ListBox, etc..) and I receive the error at random times.

I've read that it's a bug with multiple transaparent brushes, but haven't been able to get rid of it yet, even with the Beta SP of the 3.5 framework.
Wednesday, August 13, 2008 8:20:04 AM UTC
Scott,

Has this behaviour changed with .NET 3.5 SP1? I've had some problems today with transparent elements that used to let mouse clicks through but don't any longer (preventing me from clicking on the object underneath them now).

Matt
Wednesday, August 13, 2008 8:23:06 AM UTC
Nope. Not to the best of my knowledge. Not behavior changes. Just remember that only window backgrounds act different, not elements.
Wednesday, August 13, 2008 8:24:01 AM UTC
undocnet - wow, that's weird. I wonder if that's Video Driver specific...
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.