Menu

Per Pixel Alpha on VB.NET Forms

January 20, 2013 - .NET, Programming, Visual Basic
Note: This Post has been (partly) superceded by the implementation described in the more recent Alpha blended forms revisited Post.

One common problem that comes up in the creation of stylized windows such as Splash screens is the desire to have parts of the form be “shadowed” or, in other words, blend with the forms behind them. You can see this effect in action with other application splash screens, such as photoshop:

Photoshop Splash Screen in front of a dead-sexy website

Photoshop Splash Screen in front of a dead-sexy website

What witchcraft is this? How does Photoshop do it? One of the first things you might try with .NET is something like the TransparencyKey of the form. Of course, this doesn’t work, instead you get this unsightly ring of the transparency key around it.

The solution, of course, is a bit more complicated.

Starting with Windows 2000, the Win32 API and Window Manager has supported the idea of “layered” Windows. Before this, Windows had concepts known as “regions”; this basically allowed you to define regions of your window where the background would show through. This didn’t allow for per-pixel blending, but that sort of thing was not widely supported (or even conceived of, really) by most graphics Adapters. The “Layered” Windowing API basically provided a way to allow Per-pixel Alpha. Which is what we want.

Windows Forms, however, does not expose this layered window API through it’s methods or properties, with the exception of the opacity property. I don’t recall if WPF does either, but I would be surprised if it’s capabilities exposed more of the Layered Windowing API. Basically- we’re on our own

So what exactly do we need to do? Well, one thing we need to do is override the CreateParams property of the desired form, so that it adds the WS_EX_LAYERED style to the window, letting the Windowing Manager know it has to do more work with this window. Since we would like a neatly decoupled implementation, we are going to create a class that derives from Form, but use that as the base class for another form. This let’s us override the CreateParams property within that base class, but this has a bit of a caveat as well, since I’ve found that makes the Designer a bit annoyed and it complains and won’t let you use the designer. So you will have to deal with that particular point yourself. (I imagine there is a way to make it work, but I don’t want to bloat the class with such functionality). If necessary, the appropriate functions and the CreateParams override can be put into the classes that need this functionality instead.

Here is the PerPixelAlphaForm class. By the way, I’m going with Visual Basic.NET because there are already a million hits for this functionality with C#:

This provides the core implementation. The “Win32” class here provides the needed API declarations.

In order to use this, we need to make our form derive from it, and then use the inherited SetBitmap function:

(Here I just used an image on my second Hard disk that had a transparency channel, but the Bitmap constructor parameter can easily be changed.). The result:

The code in action

The code in action:

The Project I used for this can be downloaded from here. This was created using Visual Studio Professional 2012, Update 1- other editions or earlier versions may have problems with the project or source files.

Have something to say about this post? Comment!

13 thoughts on “Per Pixel Alpha on VB.NET Forms

Emths

Hello,

(Sorry, my english is poor…)

I have a lot of problems with the transparancy key and your solution seems really excellent!

But I have a problem : I work in a company using Visual Studio 2010 Ultimate Edition with the .NET Framework 4, and it doesn’t work with this configuration. Do you know a solution for this configuration?

Thanks a lot,

Emths

BC_Programming

I was able to get this working in Visual Studio 2010 Ultimate With framework 4. Anything specific going wrong?

Emths

These are the two errors it appears :

Error 1 Base class ‘PerPixelAlphaForm’ specified for class ‘Form2’ cannot be different from the base class ‘System.Windows.Forms.Form’ of one of its other partial types. C:\Users\xavier.jacquet\AppData\Local\Temporary Projects\WindowsApplication1\Form2.vb 3 14 WindowsApplication1

Error 2 ‘SetBitmap’ is not declared. It may be inaccessible due to its protection level. C:\Users\xavier.jacquet\AppData\Local\Temporary Projects\WindowsApplication1\Form2.vb 18 9 WindowsApplication1

Emths

In fact, I worked for about 15 years in Visual Basic 6 and just begin to work with OOA and OOD. So I have maybe do something wrong…

BC_Programming

Ahh OK, I got that error too. I think I fixed it with Resharper. You can fix it manually by clicking the “Show All Files” button on the Solution Explorer; The Form will now have a drop-down and you can edit the .Designer.vb file and change it to Inherit from the PerPixelAlphaForm.

Emths

Ok! Thanks a lot! I will test it as soon as possible (I’m not at work this afternoon…) I’ll tell you my results! 🙂

Emths

Hello,
I was very busy since I began to work on it, but I’ve tried and it works perfectly! Thanks a lot!
But I have a last question : could I add some controls (like a ProgressBar) on it? I’ve tried to do it creating the progress bar in code, but it doesn’t work… Do you know a solution?
Have a nice day!

BC_Programming

Ideally you would design the form first (with the controls on the form as desired) and then swap the base class. I tried fiddling with it to get the Designer to work with the PerPixelAlphaForm class, but wasn’t able to get that to work. If it’s already swapped over you’d probably add code to the InitializeComponent() method and create appropriate fields for new controls, and assign them much in the manner that the Designer-Generated code does.

Emths

Yes, it’s exactly what I thought. I’m going to test it as soon as possible. Thanks a lot for your help! 😉

dde

Hi,

first thank you for your code, it helped me very much. But i got a problem that all controls i add to my form are not visible.

Do you know why?

Thank you very much!

Omega

Hello,
Thanks alot for providing this code! Unfortunatelly I dont get it to run properly. I am aswell using vb.net 2010 (express) so I had the same issues Emths had at first.

when I open the .Designer.vb and replace

Inherits System.Windows.Forms.Form
with
Inherits PerPixelAlphaForm
vb throws the following error:

Der Designer kann keine Instanz des Typs WindowsApplication1.PerPixelAlphaForm erstellen, da dieser als abstrakt deklariert ist.

? Translation: The designer was not able to generate an instance of type WindowsApplication1.PerPixelAlphaForm, due of its abstract declaration.

I hope you can help me on this!

thanks in advance

Omega

Hello

thanks alot you for this code! unfortunatelly I was not able to execute it poperly.
I am using Visual Basic 2010 .net so experienced the same issues Emths did.
However I was not able to debug the code after replacing:

Inherits System.Windows.Forms.Form

with

Inherits PerPixelAlphaForm

in the .Design.vb

Instead VB throws the following warning:

Der Designer kann keine Instanz des Typs WindowsApplication1.PerPixelAlphaForm erstellen, da dieser als abstrakt deklariert ist.

Translated:
The designer was not able to create an instance of type WindowsApplication1.PerPixelAlphaForm, due of its abstract declaration

Please help me solve this issue

Regards

Omega

BC_Programming

Hi, Thanks for reading! This is unfortunately a limitation of the implementation here which prevents the form from being used in the designer. That’s the issue I mentioned regarding designing the class. One approach would be to keep the form deriving from “Form” until you are finished using the designer, then swap the base class for the replaced one afterwards. A less-than-perfect solution. However thinking about it I’m not sure why the class I created needs to be set to “MustInherit” I’m not in a position to give it a try at this moment but you could try removing MustInherit from the PerPixelAlphaForm class declaration. and seeing if that allows you to use the designer.

Comments are closed.