Skip to content
David Cumps
Non-Rectangular Form

Non-Rectangular Form

Originally published on my old blog at cumps.be on February 25, 2004.

I received some good feedback from my previous article (A Console IRC Bot) and here is the next one.

The question for this article was “How to make non-square windows?”.

It’s actually very easy according to the MSDN site. You add this piece of code to your form and voila, non-square.

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
    System.Drawing.Drawing2D.GraphicsPath shape = new System.Drawing.Drawing2D.GraphicsPath();
    shape.AddEllipse(0, 0, this.Width, this.Height);
    this.Region = new System.Drawing.Region(shape);
}

But that’s too easy, right? Well, actually, the setting is easy, it’s creating the Region that’s difficult. You could go looking for tutorials on how to draw shapes, but it could take a long time before you create your Region with shapes.

So, what we’ll do here is create a class that will allow us to make an image in any graphics program, that will represent our visible area.

Let’s start with drawing something we want to use as a form.

Glass shape used as the form background, with magenta as the transparent colour

Create a WinForm app (NonSquareForm). And immediately add a class to it.

This is where we begin:

using System;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace System.Drawing.Drawing2D {
      public class RegionConvert {

      } /* RegionConvert */
} /* System.Drawing.Drawing2D  */

The first method we’ll create is ConvertFromTransparentBitmap which will take a Bitmap and a Color. The Color indicates which area will be removed from the resulting Region.

We start by finding the dimensions of our image.

// First we get the dimensions of our image
GraphicsUnit aPixel = GraphicsUnit.Pixel;
RectangleF imageBoundsF = imageRegion.GetBounds(ref aPixel);
int imageWidth = Convert.ToInt32(imageBoundsF.Width);
int imageHeight = Convert.ToInt32(imageBoundsF.Height);

As you can see from the above MSDN example, we need a GraphicsPath, to which we will add all our non-transparent pixels.

// This will be the path for our Region
GraphicsPath regionPath = new GraphicsPath();

And for the logic of our method, we’ll loop over the image pixel per pixel and determine if it’s transparent or not.

// We loop over every line in our image, and every pixel per line
for (int intY = 0; intY < imageHeight; intY++) {
      for (int intX = 0; intX < imageWidth; intX++) {
            if (imageRegion.GetPixel(intX, intY) != transparentColor) {
                  // We have to see this pixel!
                  regionPath.AddRectangle(new Rectangle(intX, intY, 1, 1));
            }
      }
}

When we have all our pixels in our path, we’ll create a Region out of it, and return it.

Region formRegion = new Region(regionPath);
regionPath.Dispose();
return formRegion;

Now we go to our Form, you’ll have to set the FormBorderStyle property to None.

Add the following code to your Form constructor:

// Read the background file
FileStream imageStream = File.OpenRead("Glass.bmp");
Bitmap imageBackground = (Bitmap)Bitmap.FromStream(imageStream);
Color transparentColor = Color.FromArgb(0xFF, 0x00, 0xFF);

// Make our form fit the background
this.Width = imageBackground.Width;
this.Height = imageBackground.Height;

// Apply custom region with FF00FF as transparent color
this.Region = RegionConvert.ConvertFromTransparentBitmap(imageBackground, transparentColor);
this.BackgroundImage = imageBackground;

Glass.bmp is a bitmap that lives next to your .exe file. Now you have a non-rectangular form!

Of course you will have to add your own methods of minimizing, closing and moving the form now.

I uploaded the project as an example. You can drag it around and press ‘Q’ to quit.

Stay tuned for more! ;)

Update: I wrote an article about how to include the bitmap in the .exe, check it out: Including Resources in .exe.

You May Also Like

A Console IRC Bot

A Console IRC Bot

Getting on IRC with C#: a console bot that connects, logs in, joins a channel and reacts to server and user commands.

Basic C# Examples

Basic C# Examples

Most posts here assume a lot of background, so I asked fellow students for their C# questions and answered them with basic examples.