Click here to Skip to main content
15,886,362 members
Articles / Programming Languages / C#
Article

A Simple Bitmap Button Implementation

Rate me:
Please Sign up or sign in to vote.
4.63/5 (17 votes)
2 Jul 20034 min read 171.9K   2.5K   65   20
A small class that provides a pure bitmapped button capability for WinForms.

Sample Image - screenshot.jpg

Introduction

It appears after some minor searching that nobody has written a BitmapButton for The Code Project (or anywhere else).  WiB's excellent XP style button control solves the problem of XP style buttons with icons.  But what if you want to control the entire appearance of the button using a bitmap, regardless of OS, manifest, theme, etc.?  This control does provides that ability.  Mind you that this class is pretty bare bones--I haven't made any effort to make is usable with a form designer.  If anyone wants to update the code with this capability, I'll be more than happy to add them as a co-author.

Using The BitmapButton

Specifying Button State Images

 The BitmapButton class uses a single bitmap comprised of one or more images, where each image represents the button in one of five states.  The images must be placed contiguously from left to right.  For example:

Image 2

represents the bitmap of a button with five states:

  1. up
  2. down
  3. focused
  4. mouse-over
  5. disabled

Initializing The BitmapButton

The button is initialized in the usual manner with the additional line of code to specify the bitmap file:

bitmapButton=new BitmapButton();
bitmapButton.Location=new Point(232, 32);
bitmapButton.Size=new Size(32, 32);
bitmapButton.TabIndex=0;
bitmapButton.Text="&Down";
bitmapButton.Image=new Bitmap("downArrow.bmp");

Three important notes:

  1. The Text field is used exclusively to specify the keyboard shortcut for the button;
  2. The button width should be the same as the width of a single state image in the bitmap (all images should be the same width and height);
  3. The button height should be the same as the bitmap height.

That's it.  (If you forget the image, the program will generate an exception).

Behind The Scenes

Button State

Button state is a complicated thing when considering the dual user interface of keyboard and mouse.  For example, the user may have the mouse over the button but be using the tab key to navigate between the controls.  A complete state diagram appears as follows:

Image 3

This diagram represents the state transitions that must be considered when using the mouse and the keyboard together.  It's fairly complicated!

Button State Using The Keyboard

If the keyboard is being used, the state diagram is much simpler (the Disabled state has been removed for clarity only):

Image 4

Button State Using The Mouse

If the mouse is being used, the state diagram has some missing state transitions (again, the Disabled state has been removed for clarity only):

Image 5

Event Handlers

To manage all the events that can occur and properly transition between different states, several event handlers must be defined:

Paint+=new PaintEventHandler(BitmapButton_Paint);
MouseDown+=new MouseEventHandler(BitmapButton_MouseDown);
MouseUp+=new MouseEventHandler(BitmapButton_MouseUp);
GotFocus+=new EventHandler(BitmapButton_GotFocus);
LostFocus+=new EventHandler(BitmapButton_LostFocus);
MouseEnter+=new EventHandler(BitmapButton_MouseEnter);
MouseLeave+=new EventHandler(BitmapButton_MouseLeave);
KeyDown+=new KeyEventHandler(BitmapButton_KeyDown);
KeyUp+=new KeyEventHandler(BitmapButton_KeyUp);
EnabledChanged+=new EventHandler(BitmapButton_EnabledChanged);
PaintResponsible for painting the button in all its different states.
MouseDownTransitions into the "Clicked" state.
MouseUpTransitions into the "Has Focus" state.
GotFocusTransitions into the "Has Focus" state (got focus through keyboard, for example)
LostFocusTransitions into the "Button Up" or "Mouse Over" state.
MouseEnterIf in the "Button Up" state, transitions to the "Mouse Over" state.
MouseLeaveIf in the "Mouse Over" state, transitions to the "Button Up" state.
KeyDownTransitions to the "Clicked" state when the user presses the spacebar while the button has focus.
KeyUpTransitions to the "Has Focus" state when the user releases the spacebar while the button has focus.
EnabledChanged  Transitions to the "Disabled" state or back to the "Button Up" state when the Enabled state of the button is changed.

Drawing The Image

While double buffering is not required, since the entire state image is drawn on the surface of the button, it is implemented in case the control is enhanced to include additional drawing effects.  Double buffering is specified with the SetStyle method, which is a protected member, because someone decided that, since the control will have its own Paint handler, it should not be settable without sub-classing the control.  Never mind that the Paint event handler could be implemented in a completely separate class!

SetStyle(ControlStyles.UserPaint |
              ControlStyles.AllPaintingInWmPaint |
              ControlStyles.DoubleBuffer, true);
The button image is displayed in the Paint event handler. Given the state, it determines the index of the requested image. The bitmap does not need to include all the image states, as long as the image states provided are contiguous (meaning, you can't have button up, button down, and disabled image states, leaving focused and mouse-over empty--if you want an image for the disabled state, then you have to provide images for all the other states as well).
private void BitmapButton_Paint(object sender, PaintEventArgs e)
{
    Graphics gr=e.Graphics;
    int indexWidth=Size.Width*(int)imgState;

    if (Image.Width > indexWidth)
    {
        gr.DrawImage(Image, 0, 0,
                     new Rectangle(new Point(indexWidth, 0), Size),
                     GraphicsUnit.Pixel);
    }
    else
    {
        gr.DrawImage(Image, 0, 0,
                     new Rectangle(new Point(0, 0),
                     new Size(Size.Width, Size.Height)),
                     GraphicsUnit.Pixel);
    }
}

Conclusion

Wow, that's probably one of the shortest articles I've written in recent times! Bitmap buttons can have a lot more complexity to them than I have implemented here.  For example, what if your images don't have borders, and you'd like the control to generate a 3D style border by itself?  There's also considerations for different button state sizes and transparency, for example.  Hopefully, this article will give the reader the basis for customizing the bitmap control to his/her needs.

 

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


Written By
Architect Interacx
United States United States
Blog: https://marcclifton.wordpress.com/
Home Page: http://www.marcclifton.com
Research: http://www.higherorderprogramming.com/
GitHub: https://github.com/cliftonm

All my life I have been passionate about architecture / software design, as this is the cornerstone to a maintainable and extensible application. As such, I have enjoyed exploring some crazy ideas and discovering that they are not so crazy after all. I also love writing about my ideas and seeing the community response. As a consultant, I've enjoyed working in a wide range of industries such as aerospace, boatyard management, remote sensing, emergency services / data management, and casino operations. I've done a variety of pro-bono work non-profit organizations related to nature conservancy, drug recovery and women's health.

Comments and Discussions

 
GeneralImage problem on some screen resolutions Pin
john newton29-Jul-05 9:28
john newton29-Jul-05 9:28 
GeneralRe: Image problem on some screen resolutions Pin
Ritcho1-Jan-06 20:24
Ritcho1-Jan-06 20:24 
GeneralRe: Image problem on some screen resolutions Pin
rambutan8-Nov-07 13:56
rambutan8-Nov-07 13:56 
GeneralHot area addition Pin
Lasse Johansen9-Sep-04 6:13
Lasse Johansen9-Sep-04 6:13 
QuestionCopyright ? Pin
blero200028-Apr-04 1:34
blero200028-Apr-04 1:34 
AnswerRe: Copyright ? Pin
Marc Clifton28-Apr-04 11:45
mvaMarc Clifton28-Apr-04 11:45 
Generalc# & pop_up menue Pin
amjadqaqa15-Dec-03 23:39
amjadqaqa15-Dec-03 23:39 
Generalfocus rectangle Pin
mastercl30-Oct-03 16:06
mastercl30-Oct-03 16:06 
GeneralRe: focus rectangle Pin
Marc Clifton30-Oct-03 16:39
mvaMarc Clifton30-Oct-03 16:39 
GeneralRe: focus rectangle Pin
mastercl31-Oct-03 3:15
mastercl31-Oct-03 3:15 
GeneralRe: focus rectangle Pin
_eulogy_10-Apr-05 12:37
_eulogy_10-Apr-05 12:37 
GeneralQuestion... Pin
Wooseok Seo3-Jul-03 18:49
Wooseok Seo3-Jul-03 18:49 
GeneralRe: Question... Pin
Marc Clifton4-Jul-03 1:11
mvaMarc Clifton4-Jul-03 1:11 
GeneralRe: Question... Pin
Kant4-Jul-03 3:29
Kant4-Jul-03 3:29 
GeneralRe: Question... Pin
Marc Clifton4-Jul-03 7:35
mvaMarc Clifton4-Jul-03 7:35 
GeneralOoo nice pictures Pin
leppie3-Jul-03 11:29
leppie3-Jul-03 11:29 
GeneralRe: Ooo nice pictures Pin
Marc Clifton3-Jul-03 11:54
mvaMarc Clifton3-Jul-03 11:54 
GeneralSimple and Cool Pin
Kant3-Jul-03 9:28
Kant3-Jul-03 9:28 
GeneralRe: Simple and Cool Pin
Marc Clifton3-Jul-03 9:48
mvaMarc Clifton3-Jul-03 9:48 
GeneralRe: Simple and Cool Pin
Daniel Turini28-Apr-04 2:08
Daniel Turini28-Apr-04 2:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.