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

Iconized MenuItem

Rate me:
Please Sign up or sign in to vote.
4.70/5 (11 votes)
28 Nov 20051 min read 49.8K   1.7K   63   1
How to implement a full-featured iconized menu item in C#

Sample Image - wpm_ss.gif

Introduction

This is a simple application and was written only as an example for using the iconized menu items written in C#. The main thing this app can do is restart a service or process if it was stopped or killed. Also, it can show some information about a process or service and can act with it - kill a process, start a new process or start/stop/pause/resume/restart a Windows service if possible.

Iconized Menu Items

There are only two methods to override to implement an iconized menu item: OnDrawItem and OnMeasureItem. Here is how to do it:

C#
protected override void OnDrawItem(DrawItemEventArgs e)
{
    try
    {
        e.Graphics.FillRectangle(sbBackground, e.Bounds.X, 
                   e.Bounds.Y, e.Bounds.Width+1, e.Bounds.Height+1);
        e.Graphics.FillRectangle(sbIconBackground, e.Bounds.X, 
                   e.Bounds.Y, 20, e.Bounds.Height+1);
        if(base.Text == "-")
        {
            e.Graphics.FillRectangle(sbIconBackground, e.Bounds.X+20, 
                       e.Bounds.Y+2, e.Bounds.Width-20, e.Bounds.Height-2);
        }
        else
        {
            Rectangle rIcon = new Rectangle(e.Bounds.X+1, e.Bounds.Y+2, 16, 16);
            if(iImage != null) e.Graphics.DrawIconUnstretched(iImage, rIcon);
            if((base.Checked)&&(iChecked != null))
                e.Graphics.DrawIconUnstretched(iChecked, rIcon);
            e.Graphics.DrawString(base.Text, fnt, sbTextColor, 
                                 e.Bounds.X+22, e.Bounds.Y+2);
            if((e.State & DrawItemState.Selected) != 0)
            {
                e.Graphics.FillRectangle(sbSelected, e.Bounds);
                e.Graphics.DrawRectangle(pBorder, e.Bounds.X, 
                           e.Bounds.Y, e.Bounds.Width-1, e.Bounds.Height-1);
            }
        }
    }
    catch(Exception x)
    {
        System.Diagnostics.Trace.WriteLine(x.ToString(), 
                           "WpmMenuItem ("+this.Text+"): Drawing ");
    }
}

protected override void OnMeasureItem(MeasureItemEventArgs e)
{
    try
    {
        if(base.Text == "-")
        {
            e.ItemHeight = 4;
        }
        else
        {
            e.ItemHeight = 18;
            e.ItemWidth = Convert.ToInt32(e.Graphics.MeasureString(this.Text, 
                                                              fnt).Width)+30;
        }
    }
    catch(Exception x)
    {
        System.Diagnostics.Trace.WriteLine(x.ToString(), 
               "WpmMenuItem ("+this.Text+"): Measuring ");
    }
}

All the properties used are private class members.

C#
private Font fnt;
private Icon iImage;
private Icon iChecked;
private SolidBrush sbSelected;
private SolidBrush sbIconBackground;
private SolidBrush sbBackground;
private SolidBrush sbTextColor;
private Pen pBorder;

These properties are used to change background color, fore color, font, etc. In our case, only the icon and the "checked" icon properties have been made public.

C#
public System.Drawing.Icon Icon
{
    get { return iImage; }
    set
    {
        try
        {
            if(value != null)
            {
                iImage = new Icon(value, 16, 16);
            }
        }
        catch
        {
            iImage = null;
        }
    }
}

public System.Drawing.Icon CheckedIcon
{
    get { return iChecked; }
    set
    {
        try
        {
            if(value != null) iChecked = new Icon(value, 16, 16);
        }
        catch
        {
            iChecked = null;
        }
    }
}

Another thing to implement is the standard MenuItem behavior - make it act as a separator, or as checked or enabled, etc. We also implement a new feature - to be able to make it a "header" (line with some right-aligned text).

There is only one problem I did find with the class - I had an exception from the System.Drawing.Icon class when creating too many icons. But for static menus, the class is really customizable and useful.

Thanks to Joel Matthias for his NotifyIconEx class.

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
Web Developer
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionWhat version of .Net? Pin
Paul A. Howes6-Dec-05 0:24
Paul A. Howes6-Dec-05 0:24 

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.