Non-Rectangular Form
The question for this article was how to make nonsquare 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.
Create a WinForm app (NonSquareForm). And immediately add a class to it.
This is were 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.
To start, we begin with 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, where we will add all our non-transparent pixels to.
// 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 got a non-rectangular form!
Ofcourse 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.