Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

ButtonMenu - a.k.a. A Simple Hack For A Nice GUI

2.95/5 (11 votes)
6 Jun 2006CPOL2 min read 1   1.3K  
Developing a nice menu look using only C#
Sample Image - ButtonMenu.jpg

Introduction

One of my favourite desktop gadgets is/was Google Deskbar, but because Google staff decided to stop its development, I've decide to build up a clone of it.

Looking at its GUI, the first problem that emerges is the toggle like button for menu displaying. I've Googled a lot seeking a similar if not equal component but without success, so I've started to think about the way that I must follow to develop a component with the same look and feel.

A first choice was, naturally, to use a ToggleButton but also this component is not directly available in .NET, but only as a COM component. Using a COM component can, if not needed, reduce the cleanness of the code. Some tests have revealed that a component with a toggle-like feel is available as a special appearance of a checkbox. So we can start coding...

The Code

C#
public partial class ButtonMenu : CheckBox

In the constructor, I set up basic look oriented properties:

C#
this.Appearance = Appearance.Button;
this.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.FlatStyle = FlatStyle.Popup;

Using CheckBox as base class grants me the ability to reduce the code I need to write to reach my goal. The only code I need to add will be menu-specific.... Well put in this menu!

C#
private ContextMenuStrip menu=null;
public ContextMenuStrip Menu
{
    get
    {
        return menu;
    }
    set
    {
        /*
         * If menu != null then we have a menu to clean before to change
         */
        if(menu!=null)
            menu.Closed -= menu_Closed;
        
        menu = value;
        if(menu != null)
            menu.Closed += menu_Closed;
    }
}

Using a property gives me two advantages:

  1. I can change it at design time
  2. I can administer in a simple way the adding and the removing of event handler

In the precedent code, we have introduced the method menu_Closed. It's something like:

C#
private bool frombutton = false;
void menu_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
    /*
     * Popup Menu closing... raise the button
     */
    if(!frombutton)
        Checked = false;
    
}

The boolean flag frombutton is used to check the reason of menu closing, in details it's true if menu has been closed due to a button event and it's false if it's closed by focus lost. The main method is simple... after you have understood the behavior of the Show method:

C#
private void DisplayMenu()
{
    // No menu...
    if (menu == null)
        return;
    
    Point offset = new Point();
    switch (direction)
    {
        case ToolStripDropDownDirection.AboveLeft:
            offset.X = menu.Width;
            offset.Y = 0;
            break;
        case ToolStripDropDownDirection.AboveRight:
            offset.X = this.Width-menu.Width;
            offset.Y = 0;
            break;
        case ToolStripDropDownDirection.BelowLeft:
            offset.X = menu.Width;
            offset.Y = this.Height;
            break;
        case ToolStripDropDownDirection.BelowRight:
            offset.X = this.Width - menu.Width;
            offset.Y = this.Height;
            break;
        case ToolStripDropDownDirection.Default:
            offset.X = (this.Width - menu.Width)/2;
            offset.Y = this.Height;
            break;
        case ToolStripDropDownDirection.Left:
            offset.X = 0;
            offset.Y = 0;
            break;
        case ToolStripDropDownDirection.Right:
            offset.X = this.Width;
            offset.Y = 0;
            break;    
    }
    
    menu.Show(this, offset, direction);

In the code above, direction is a value in ToolStripDropDownDirection enumeration accessible with a standard get/set pair.

Usage

As code, also the instructions are really simple, after you've added ButtonMenu component to toolbox, drag it on your form and set Menu property from property page (or via code). Enjoy. EDIT: I've merged code for autoplacing written by BlackTigerAP (I've done a little "case compression" to reduce code replication. I've added a new property public ButtonMenuStyle Style to switch between flat and button styles from design. Of course:

C#
public enum ButtonMenuStyle
{
  Flat = 0,
  Button = 1,
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)