Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Transparency Tutorial with C# - Part 3

0.00/5 (No votes)
23 Mar 2004 6  
An article on Compositing, ColorMatrix, and ImageAttributes

Introduction

As in the earlier tutorial, we consider the ‘what’ before the ‘how’. That is, a discussion is presented of the concepts behind the code, and then at the end, we look at the code behind the concepts.

Fade Concepts

Fades are commonly used as transitions between images on TV or in the movies to soften the switch between scenes. We can simulate this effect by stacking images on a form and increasing the alpha value for each image sequentially causing them to fade away until the last image is shown. Figure 1 illustrates this technique using some excellent renderings of a generic luxury car generously provided by Kevin Hulsey, www.khulsey.com (the images, not the luxury car ;).

Important Note:

Png images have per pixel alpha and are large, so to conserve space they are zipped separately. For the programs with separate images, the images must be in the same directory as the exe file. To run the demo, put the images in the directory with it. To run the source code, the images MUST be put in the \bin\debug directory before running the source code.

  1. Open the project
  2. Put the images in the \bin\debug directory
  3. Run the code.

Figure 1 Image Fade

Figure 1 Image Fade

Form Concepts

You can do fades with entire forms using the opacity. Just step the property between 0 and 1 for transparent to opaque. Figure 2 illustrates a timer based splash screen that fades in.

Figure 2 Using Form Opacity to fade in a splash screen

Figure 2 Using Form Opacity to fade in a splash screen

Having areas of full transparency and full opacity takes a little more work. Figure 3 shows an irregular shaped form with a progress bar that could be used for a splash screen. We use a panel control to hold the image and set the panel’s backcolor property to transparent. The form’s transparency key is also set to the forms backcolor, which in this case is white. Since we aren’t doing much painting in this application, we don’t bother with the flicker-free additions and let C# do the painting for us.

Figure 3 Transparent Form Background With Image, example #1

Figure 3 Transparent Form Background With Image, example #1

Figure 4 carries the idea further by using an image and letting it start small and grow to full size. This requires lots of paints so we go back to using the flicker-free techniques. This application might make an interesting splash screen while your real application is doing something in the background. Then again, it might just be annoying.

Figure 4 Transparent Form Background With Image, expample #2

Figure 4 Transparent Form Background With Image, expample #2

Now we step gingerly outside the safe world of C# and GDI+ into the truly dark and dangerous forest of the Win32 API. We previously visited the twilight shadows at the edge of this forest with the WhatColor demo, but now we plunge straight in and hope none of the low-level MS beasties gets us. Figure 5 is an implementation of the coding ideas that got me going down this muddy and rutted road in the first place. I’d read Rui Lope’s article on Per Pixel Alpha Blend in C#. That article gave just enough information to whet my appetite, but my skill level wasn’t advanced enough to make any real use of it. The studies documented in these tutorials led to my being able to use and somewhat understand his code. And I was able to modify it so that I could get a variable transparency form that responds to mouse events. I don’t know what I’ll do with this new knowledge, but I personally think the effect is pretty cool.

Figure 5 Perpixel Form Transparency With Image

Figure 5 Perpixel Form Transparency With Image

The Code

As mentioned in the first tutorial, we’ll only look at code that introduces new concepts.

Image Fade

Figure 1 Image Fade, introduces a shortcut in the use of ColorMatrix. Each of the elements of the matrix are individually accessible as ColorMatrix.MatrixXY where XY is a number for the row and column. ColorMatrix.Matrix33 is the alpha diagonal member and is used in this code instead of the entire matrix.

  <span class="cs-comment">//Set alpha in the ColorMatrix</span>
  middleColorMatrix.Matrix33 = middleTransparency;

The middleTransparency variable is set by the timer to sequentially change the alpha for the entire image until the image becomes fully transparent. The other functions are as discussed before.

Form Fade

Figure 2, shows a splash screen fading up from fully transparent to fully opaque. This is very easy to accomplish in C# using the form’s Opacity property. We us a timer to change it from 0.0f to 1.0f in 0.03f steps

  <span class="cs-keyword">private</span> <span class="cs-keyword">float</span> opacity = <span class="cs-literal">0</span>;
  <span class="cs-keyword">private</span> <span class="cs-keyword">void</span> timer1_Tick(<span class="cs-keyword">object</span> sender, System.EventArgs e)
  {
    opacity += <span class="cs-literal">0</span>.03f;
    <span class="cs-keyword">this</span>.Opacity = opacity;
    <span class="cs-keyword">if</span>(opacity > <span class="cs-literal">1.0</span>)
    {
      timer1.Enabled = <span class="cs-keyword">false</span>;
      buttonAgain.Show();
      buttonQuit.Show();
    }
    Invalidate();
  }

And we use DrawImage in the OnPaint override, as before.

We also add a useful bit of code that has nothing to do with transparency, but allows us to grab the form and drag it around.

  <span class="cs-comment">// Drag it around the screen</span>
  <span class="cs-keyword">private</span> <span class="cs-keyword">const</span> <span class="cs-keyword">int</span> WM_NCHITTEST = <span class="cs-literal">0x84</span>;
  <span class="cs-keyword">private</span> <span class="cs-keyword">const</span> <span class="cs-keyword">int</span> HTCAPTION = <span class="cs-literal">0x2</span>;
  <span class="cs-keyword">protected</span> <span class="cs-keyword">override</span> <span class="cs-keyword">void</span> WndProc(<span class="cs-keyword">ref</span> Message m)
  {
    <span class="cs-keyword">if</span>(m.Msg == WM_NCHITTEST)
      m.Result = <span class="cs-keyword">new</span> IntPtr(HTCAPTION);
    <span class="cs-keyword">else</span>
      <span class="cs-keyword">base</span>.WndProc(<span class="cs-keyword">ref</span> m);
  }

Form Transparency

Figure’s 3 and 4 Transparent Form Background With Image #1 and #2 show two hypothetical splash screens with full transparency allowing a non rectangular shape. The first has a progress bar and the second grows the image to mark time. The first doesn’t do much painting so no flicker-free techniques are used. The second does a lot of painting so the flicker-free techniques are used.

This code may be a bit of a kludge in that a panel is docked to the center of the form, it’s backcolor is set to transparent and it’s backgroundimage is set to the stump. The form itself has it’s transparency key set to its backcolor. It might seem that it would be eaiser to dispense with the panel and use the form’s backgroundimage property, but for some reason I didn’t fathom, I couldn’t get that to work. Kludges? Maybe, but it works. The Lunatics, Inc demo had an annoying flash at the start that I never figured out how to get rid of (anybody know how?) so I decided to start the thing minimized, then maximize it before starting the animation.

<span class="cs-comment">// Starting minimized is hacking crap done to get rid of the initial</span>
<span class="cs-comment">// flashing of garbage when the program first starts. We still see a</span>
<span class="cs-comment">// bit of a title bar zipping around, </span>
<span class="cs-comment">// odd since this form border style is none.</span>
<span class="cs-comment">// ANYBODY KNOW HOW TO DO THIS CORRECTLY?</span>
  <span class="cs-keyword">private</span> <span class="cs-keyword">void</span> Form1_Load(<span class="cs-keyword">object</span> sender, System.EventArgs e)
  {
    <span class="cs-keyword">this</span>.WindowState = FormWindowState.Normal;
  }

I still got a bit of a title bar flying about at the start, but that is much less annoying than the other way.

Per pixel form transparency

Figure 5 Shows a demo splash screen for Aqua Mala (guaranteed 90% pure water). The base software is entirely a rip of Rui Lopes’ article, but with enough extra added so that I could understand it and actually make something that I consider potentially useful out of it. We have now left the cuddly world of proper C# and are using the win32 API via COM interoperability. And, yes, I do believe that there are actually people who fully understand that concept. I, however, am content to hack it and hope.

I split up the original into a class with the win32 stuff and a class with the C# stuff. I added an accessor to set the form size, but hardwired the hotspot size. If I were to do further work on this, I’d change the hotspot to regions and just load their bitmap, rather than all the redundant image data in two almost identical bitmaps. I should do a lot of documentation here about the code, but I’m going to let source do it’s own talking and hope I get time later to do a more thorough job.

That’s the end of these tutorials. I hope it helps the reader avoid some of the pitfalls I fell into and perhaps some readers will be willing to share with me better methods and coding techniques than I worked out.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here