This is a simple project that demonstrates how easy it is to create a custom shaped form that has a drop down in .NET using very little code.
Introduction
This is a VS2003 project but it should work in VS2005 or C# Express with few modifications.
I had found code that demonstrated the basic principle, but I needed something with the potential to be dynamic. Transparency did not work for most of the samples I found in 32 bit mode so I went searching on MSDN and found a code snippet that loaded images with transparency, and it was all done in C#.
What you see above is the initial screen when the program loads. What you don't see is the actual size of the form which is actually 300 pixels by 200 pixels, much larger than the image above. Also when you run it, clicking around the image will either bring up the window behind the image, or in this case do nothing since there is no window behind it. When you mouse over it, you will see a drop down which is also click-able.
Some of you may recognize the images. In fact, this started out as an older VB7 project created by somebody else (I can't remember who) which demonstrated what this project does. However, transparency did not work in 32 bit mode plus it had an additional class to handle the clipping and graphics, most of which I discovered you don't need.
Using the Code
To start with, create a borderless form of any size. It must be big enough to hold the largest image. Borderless allows for invisibility.
Set the transparency key of the form to some color you won't be using elsewhere. It is not necessary to set it to the same transparency color as the image(s).
The heart of the code is five lines as shown below (excluding comments) executed in the paint
event.
bmp
is a private bitmap variable declared at the class level.
private void Form1_Paint(object sender, PaintEventArgs e)
{
ImageAttributes attr = new ImageAttributes();
attr.SetColorKey(bmp.GetPixel(0, 0), bmp.GetPixel(0, 0));
e.Graphics.FillRectangle(Brushes.Transparent,this.DisplayRectangle);
GraphicsUnit pu = GraphicsUnit.Pixel;
e.Graphics.DrawImage((Image)bmp, Rectangle.Truncate(
bmp.GetBounds(ref pu)), 0F, 0F, (float)bmp.Width,
(float)bmp.Height,
GraphicsUnit.Pixel, attr);
}
To make the drop down, I actually load a different image that includes the original image. I do this with the MouseEnter
event of the form.
private void Form1_MouseEnter(object sender , EventArgs e )
{
bmp = (Bitmap)Bitmap.FromFile("Sonique Small Extended.bmp");
this.Invalidate();
}
I then switch back to the original image on the MouseLeave
event of the form.
private void Form1_MouseLeave(object sender , EventArgs e )
{
bmp = (Bitmap)Bitmap.FromFile("Sonique Small.bmp");
this.Invalidate();
}
I also included some code to simulate an exit button, which is the "x" button on the drop down image.
private void Form1_MouseUp(object sender,
System.Windows.Forms.MouseEventArgs e)
{
Point p=new Point(e.X,e.Y);
if (ExitButton(p))
this.Close();
}
private bool ExitButton(Point p)
{
int left = 157;
int right = 168;
int top = 28;
int bottom = 39;
return (p.X >= left && p.X <= right
&& p.Y >= top && p.Y <= bottom);
}
Points of Interest
Comment out the line that draws the image. When you run it, you will never see the form plus you can't click on it, as if it didn't exist.
Also notice I don't have any code to set the region and clipping - it's not needed. Moreover, I don't use any calls to the Win32 API - it is all C#.
Possible Improvements
There is a lot missing here. My point was to show how to create a custom form, but you will undoubtedly need more controls. You could add custom controls, examples of which you can find on CodeProject, or make use of my example here. I also included a simple project to determine the mouse boundaries needed for this example.
If you do add custom controls, you need to modify either the MouseLeave
or MouseEnter
events so the particular image will stay put while you process control events.
I load the images in real time, and you will see it is pretty snappy.
If, when you experiment, you find it slows down because of large images or too many images, try creating a bitmap array on Form_load
and keep them in memory, and if needed use double buffering. There is a lot you can do to improve this.
History
- 5th March, 2007: Initial version
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.