Click here to Skip to main content
15,867,966 members
Articles / Desktop Programming / Win32

Fading Forms and Setting Opacity Without Flicker Using the Layered Windows API

Rate me:
Please Sign up or sign in to vote.
3.58/5 (10 votes)
14 Oct 2009CPOL3 min read 60.5K   2.1K   44   25
Get more control over your forms opacity by manually creating a wrapper to the Layered Windows API

Introduction

Everyone has seen the Opacity property in the Visual Studio property inspector when a form is selected. But few people realize exactly how that works behind the scenes, or even how poorly it is implemented. Windows 2K Microsoft has used the Layered Window API to snazzy up the mouse cursor with a little transparent drop shadow. This is done in the same fashion as the opacity setting in .NET Windows Forms. When changing the opacity of a form via its opacity property, the form makes a Windows API call behind the scenes, yep that's right, its just a simple winAPI wrapper smashed into a single property. Obviously you lose a little control. Let's get some back.

Background

Before the .NET Framework, transparent windows were done the same way as they are now, It just took quite a few more lines of code. When setting the opacity to a value besides 100%, the .NET Framework makes a call to SetWindowLong and throws a flag to toggle on the WS_EX_LAYERED API. Layered windows are a very powerful tool, but we will be talking about just the simplest use of it, setting a forms's Opacity, afterward SetLayeredWindowAttributes is called, passing to it a byte value indicating the level of opacity. 0 for transparent and 255 for opaque.

Sounds simple enough, but, Windows doesn't like that change, when you make the transition between not layered and layered windows, your form flickers black. And that's not attractive. and every time you alter the opacity property between 100% and any other valid value, the switch is made and you run the almost inevitable chance of seeing the infamous black flicker.

The trick here is to just keep the form a layered window all the time, your form will use a little more system resources, but not enough to make a real difference. Your computer is already making hundreds of calls to the layered window API, just a few more won't make any significant differences.

Using the Code

Included in the source download is my class called DDFormFader. It's a Layered Window wrapper class that handles all the trouble for you! You simply construct it passing the Handle to the form you want to control the opacity of and they use its pubic functions to manipulate the transparency effects.

C#
DDFormsExtentions.DDFormFader FF; 
 public Form1()
  {
   InitializeComponent();

    //pass the class constructor the handle to the form
    FF = new DDFormsExtentions.DDFormFader(Handle);

    //set the form to a Layered Window Form
    FF.setTransparentLayeredWindow();

    //sets the length of time between fade steps in Milliseconds 
    FF.seekSpeed = 5;  
    
    // sets the amount of steps to take to reach target opacity    
    FF.StepsToFade = 8; 

    FF.updateOpacity((byte)0, false); // set the forms opacity to 0;

    Load += new EventHandler(Form1_Load);
   }

   void Form1_Load(object sender, EventArgs e)
    {
      FF.seekTo((byte)255); // fade the form to full 
                            //opacity on load, cleanly with no flicker.
    } 

You can easily change the form's opacity using the UpdateOpacity method, and fade to any opacity using the seekTo method.

But enough of that. Let's see the real code!

First we interlop the user32 methods responsible for setting the flags that make the magic happen:

C#
//gets information about the windows
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);

//sets bigflags that control the windows styles
DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

//changes flags that modify attributes of the
//layered window such as alpha(opacity)
[DllImport("user32.dll")]
static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey,
 byte bAlpha, uint dwFlags); 

And set up the flags you will need:

C#
//WS_EX constants
private const int GWL_EXSTYLE = (-20);
private const int WS_EX_LAYERED = 0x80000;
private const long LWA_ALPHA = 0x2L; 

Now we toggle on the Layered window style with a simple call to the setWindowLong function, followed by a call to SetLayeredWindowAtrributes where the 3rd param is a byte representing the level of opacity, 0 for transparent, 255 for Opaque, and any number in between. Much finer control than .NET's percent system.

C#
SetWindowLong(frmHandle, GWL_EXSTYLE, 
	GetWindowLong(frmHandle, GWL_EXSTYLE) ^ WS_EX_LAYERED);
SetLayeredWindowAttributes(frmHandle, 0, _currentTransparency, (uint)LWA_ALPHA);

To disable the Layered window and revert to a standard window, you simply call the SetWindowLong method again with the same params. The DDFormFader class included has more functionality and is completely commented. Thanks!

Points of Interest

One thing to note that threw me for a loop was immediately after calling setWindowLong it is necessary to call SetLayeredWindowAttributes. If it's not immediately after the form will stop painting correctly and crazy things will happen, just remember to call SetLayeredWindowAttributes on the very next line. Or of course just use my class, it handles it all for you. :)

History

  • Current Version 1.0 Original release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
I am a part time programmer, The more I learn, the more I need to learn, the best of which I will share here on codeproject!

Visit my site and blog

Comments and Discussions

 
QuestionHow to use in VB.Net Pin
RUrry3-May-10 6:33
RUrry3-May-10 6:33 
QuestionFor a form not shown in taskbar? Pin
l30to111-Feb-10 8:49
l30to111-Feb-10 8:49 
AnswerRe: For a form not shown in taskbar? Pin
Diamonddrake11-Feb-10 10:25
Diamonddrake11-Feb-10 10:25 
QuestionIt`s Great! Pin
avionov11-Nov-09 19:06
avionov11-Nov-09 19:06 
AnswerRe: It`s Great! Pin
Diamonddrake13-Nov-09 11:22
Diamonddrake13-Nov-09 11:22 
GeneralThorough and Well Written Pin
KentuckyEnglishman20-Oct-09 2:59
KentuckyEnglishman20-Oct-09 2:59 
GeneralRe: Thorough and Well Written Pin
Diamonddrake20-Oct-09 11:07
Diamonddrake20-Oct-09 11:07 
Generala few suggestions Pin
BillWoodruff16-Oct-09 2:16
professionalBillWoodruff16-Oct-09 2:16 
GeneralRe: a few suggestions Pin
Diamonddrake16-Oct-09 10:38
Diamonddrake16-Oct-09 10:38 
GeneralRe: a few suggestions Pin
BillWoodruff19-Oct-09 21:14
professionalBillWoodruff19-Oct-09 21:14 
GeneralRe: a few suggestions Pin
Tom Donchez2-Feb-10 8:15
Tom Donchez2-Feb-10 8:15 
GeneralI think there's a workaround with no need for interop Pin
User 113800015-Oct-09 12:42
User 113800015-Oct-09 12:42 
GeneralRe: I think there's a workaround with no need for interop Pin
Diamonddrake15-Oct-09 16:38
Diamonddrake15-Oct-09 16:38 
GeneralMessage Closed Pin
16-Oct-09 2:59
User 113800016-Oct-09 2:59 
GeneralRe: I think there's a workaround with no need for interop Pin
Diamonddrake16-Oct-09 10:30
Diamonddrake16-Oct-09 10:30 
GeneralMessage Closed Pin
16-Oct-09 12:43
User 113800016-Oct-09 12:43 
GeneralRe: I think there's a workaround with no need for interop Pin
Diamonddrake16-Oct-09 13:16
Diamonddrake16-Oct-09 13:16 
GeneralRe: I think there's a workaround with no need for interop Pin
Tom Spink19-Oct-09 21:49
Tom Spink19-Oct-09 21:49 
GeneralRe: I think there's a workaround with no need for interop Pin
Diamonddrake20-Oct-09 10:49
Diamonddrake20-Oct-09 10:49 
Tom Spink wrote:
You are *so* wrong. That is exactly what the .NET framework is meant to solve... NOT having to write multiple classes to port your application to a multitude of operating systems.


No sir, you are entirely wrong, the .net framework was written by Microsoft so that developers using the 3 different MICROSOFT WINDOWS DOT NET PROGRAMMING LANGUAGES running on MS WINDOWS could write applications and libraries that cooperate with each other, seamlessly as if they were the same programming language.

It includes sets of useful libraries that make application develop FASTER. by each program not having to worry about how to save an image as a jpeg, or url encode a string. Its an amazing asset to any programmer. but IT WAS NEVER INTENDED TO ALLOW APPLICATIONS TO SPAN OPERATING SYSTEMS. that whole thing is just something the mono project people did with it.

MONO is just a platform independent copy of what Microsoft come up with. They may have expanded it a bit. but regardless. It was micrsoft's idea, they did it first, they developed VB.net and C#. C# is a hybrid of C++ and VB. both Microsoft languages.

MONO is a neat idea. but all operating systems work differently. A program should be tailored to its operating system. That's my opinion as a developer. No open source framework that allows applications to run on multiple operating systems is going to change that to me.

Here is an example. using my article. Say you are developing a program that is a windows application. the MS dot net framework makes a call to setWindowLong to change your form to a layered window in order to alpha blend your form. to get more power for this, you do this manually, because the framework exposes a minimalistic methodology. now, a particular Linux distribution may Nativity support alpha blending, so it its always on, you just update the forms opacity value. the framwork would handle this differently depending on which version of the framework your application used, the windows, or Linux versions of MONO. Problem is. since you had to do it the framework's way. now you are LIMITED to the framework's methodology. Even though its a program that would really target windows, and you want to do something on windows related, just so you can hope it would work on linux too, you bail on what could be a great windows related asset.

what limits a program from running on different applications is how it communicates with hardware and how its code communicates with the environment that the operating system creates for it. the CLR is all that is really needed to be platform independent. its the CLR that in realtime converts the Intermediate language that managed applications compile to into something really understandable by the operating system. the framework around it just to make programming easier and faster.

My article isn't about easy. Is about knowing how WINDOWS WORKS, and how to take advantage of its features.

If you use MONO, don't bother reading my articles, Its not tailored to you.
GeneralRe: I think there's a workaround with no need for interop Pin
Tom Spink20-Oct-09 21:31
Tom Spink20-Oct-09 21:31 
GeneralRe: I think there's a workaround with no need for interop Pin
Diamonddrake21-Oct-09 10:37
Diamonddrake21-Oct-09 10:37 
GeneralRe: I think there's a workaround with no need for interop Pin
Tom Spink21-Oct-09 11:16
Tom Spink21-Oct-09 11:16 
GeneralRe: I think there's a workaround with no need for interop Pin
Diamonddrake21-Oct-09 13:17
Diamonddrake21-Oct-09 13:17 
GeneralSounds like that would fix another annoyance Pin
supercat915-Oct-09 8:18
supercat915-Oct-09 8:18 
GeneralRe: Sounds like that would fix another annoyance Pin
Diamonddrake15-Oct-09 10:08
Diamonddrake15-Oct-09 10:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.