Click here to Skip to main content
Click here to Skip to main content

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

By , 6 Jun 2006
 
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

public partial class ButtonMenu : CheckBox

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

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!

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:

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:

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:

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)

About the Author

lbenini
Italy Italy
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
General.Net 1.1 [modified]memberzohre_j14 Jul '06 - 19:06 
GeneralRe: .Net 1.1memberBen3.Tyo23 Jan '08 - 16:15 
QuestionClick Event?memberDoncp6 Jun '06 - 7:54 
AnswerRe: Click Event?memberlbenini6 Jun '06 - 22:01 
GeneralRe: Click Event?memberDoncp7 Jun '06 - 3:16 
GeneralRe: Click Event?memberlbenini7 Jun '06 - 4:01 
GeneralNot bad... :)memberBlackTigerAP6 Jun '06 - 0:02 
GeneralRe: Not bad... :)memberlbenini6 Jun '06 - 0:20 
Automatic it's a good idea, but automatic by parent window or by screen x / y?
It's useful... but i've started to work on it to develop a deskbar, so my ideas were limited by it's look-and-feel (stay update, i'll upload the code...)

GeneralRe: Not bad... :)memberBlackTigerAP6 Jun '06 - 3:27 
GeneralRe: Not bad... :) [modified]memberBlackTigerAP6 Jun '06 - 3:33 
GeneralRe: Not bad... :) [modified]memberlbenini6 Jun '06 - 8:47 
GeneralRe: Not bad... :) [modified]memberlbenini6 Jun '06 - 22:44 

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 7 Jun 2006
Article Copyright 2006 by lbenini
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid