Introduction
With this article, i want to describe a very simple way to create interactive bitmap buttons for WinForm applications. The problem was, that WinForm doesn't supply a decent way to create bitmap buttons. At least not for lag free applications.
The first thing that everyone had at least tried once, is the approach over a flat Button, but sooner or later ran into some styling issues, the image wasn't correctly placed, etc... At least this was a big problem for me.
Next up was a PictureBox, it worked... but somehow there was a slight delay until the image was changed into the proper one. Ok, you might say thats a small issue and it wont stick out as much. But this is a huge issue for high quality applications.
So, to eliminate the "lag", i decided to use a ImageList for my bitmaps and like magic, the issue was gone. And on the plus side, it doesn't take much work to use this method.
Using the code
As usual, we start with a new solution in VS and chose C# -> Windows Forms-Application as our project type. Within the draft-mode of Form1, we switch to the event pane and double click on Behavior -> Load. This should generate the following code within the Form1.cs:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Application
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
We leave this as it is, at least for now.
Now we add a PictureBox to Form1
in draft mode. Leave everything as it is, except the Size
and SizeMode
. For the Size
we enter the size of our bitmap and we set the SizeMode
to CenterImage
.
At this point we should add our bitmap to the resources. In total 3 bitmaps for the states normal, hover and down. If you don't know how to add resources to your project, you should read this article on MSDN: Adding and Editing Resources (Visual C#)
Now on to the Form1.cs, there we add a new property of the ImageList type and initialize right away.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Application
{
public partial class Form1 : Form
{
private ImageList _btnImage = new ImageList();
public Form1()
{
InitializeComponent();
}
}
}
What is an ImageList?
Basically it is an array of images, but the object itself contains some additional data, like ColorDepth
and Size
. Both should be specified before you add images, otherwise you can run into some problems.
Also it provides a consistent way to store and access images with different states, like buttons.
After we defined and initialized the ImageList, we can now add all the images and define the ColorDepth
and Size
.
namespace Application
{
public partial class Form1 : Form
{
private ImageList _btnImage = new ImageList();
private void Form1_Load(object sender, EventArgs e)
}
this._btnImage.ImageSize = new Size(26, 26);
this._btnImage.ColorDepth = ColorDepth.Depth32Bit;
this._btnImage.Images.Add("normal", Resources.NormalImage);
this._btnImage.Images.Add("hover", Resources.HoverImage);
this._btnImage.Images.Add("down", Resources.DownImage);
this.ImageButton.Image = this._btnImage.Images["normal"];
}
}
}
The rest if relatively straight forward, so i won't go into the details.
namespace Application
{
public partial class Form1 : Form
{
private void ImageButton_MouseEnter(object sender, EventArgs e)
{
this.ImageButton.Image = this._btnImage.Images["hover"];
}
private void ImageButton_MouseLeave(object sender, EventArgs e)
}
this.ImageButton.Image = this._btnImage.Images["normal"];
}
private void ImageButton_MouseDown(object sender, MouseEventArgs e)
{
if(MouseButtons.Equals(MouseButtons.Left, e.Button))
{
this.ImageButton.Image = this._btnImage.Images["down"];
}
}
private void ImageButton_MouseUp(object sender, MouseEventArgs e)
{
if(MouseButtons.Equals(MouseButtons.Left, e.Button))
{
this.ImageButton.Image = this._btnImage.Images["hover"];
}
}
private void ImageButton_Click(object sender, EventArgs e)
{
}
}
}
Now you just have to assign the corresponding methods, to the PictureBox events. Keep in mind, that i renamed the PictureBox to ImageButton
for this example, you have to use the name you entered in the Name
field.
Points of Interest
On the first look it seems like quite a lot of work, just to make one bitmap button. But if you're using the same bitmap all over the place, you'll find this method quite simple and time saving. Especially if you use the same basic image, but with different states.
There is one thing you should keep in mind, you definitely have to define the ColorDepth
, otherwise the image will be rendered in the lowest available ColorDepth
and that can result in funny renderings.
History
First release.