Issue dated - 19th January 2004

-


Previous Issues

CURRENT ISSUE
NEWS ANALYSIS
INDIA NEWS
COLUMNS
TECH FORUM

THE C# COLUMN

BETWEEN THE BYTES
TECHNOLOGY
SPECIALS <NEW>
Symantec Report
Security Headquarters
JobsDB
MINDPRINTS
HMA BANKBIZ
EC SERVICES
ARCHIVES/SEARCH
IT APPOINTMENTS
Openings At Jobstreet.com
WRITE TO US
SUBSCRIBE/RENEW
CUSTOMER SERVICE
ADVERTISE
ABOUT US

 Network Sites
  IT People
  Network Magazine
  Business Traveller
  Exp. Hotelier & Caterer
  Exp. Travel & Tourism
  Exp. Pharma Pulse
  Exp. Healthcare Mgmt.
  Express Textile
 Group Sites
  ExpressIndia
  Indian Express
  Financial Express

 
Front Page > TechSpace > Story Print this Page|  Email this page

The C# coloum

Creating owner-drawn menus

Most of the times menu items are strings, but sometimes pictures make more sense than text strings. For example, a color menu should show colors rather than text strings containing names of various colors. It would make more sense for the user if colors like magenta and cyan are shown as they are going to look, rather than as strings saying “Cyan” and “Magenta”. If the colors were shown, their meaning would be crystal clear.

Unfortunately, the MenuItem class does not provide a standard way to display pictures/icons. For example, there is no Icon property you set to display an icon automatically. However, the MenuItem class provides the capability for non-standard drawing, often called “owner-drawing”.

Every menu item has a property called OwnerDraw. When the OwnerDraw property is set to true, it indicates that the user, not Windows, will handle all drawing of the menu item. .NET IDE gives full support for creating the owner-drawn menus.

In this article we will create a WinForm application with an owner-drawn menu. The menu titled ‘Color’ will display three menu items having icons plus text. The icons will represent colors ‘Red’, ‘Green’ and ‘Magenta’. On clicking the menu items, the background of the form gets filled with the selected color.

Create a WinForm application and add a Menu control to the form. Name the control as m. Add the menu item ‘Color’ to the menu m. Add three menu items to the ‘Color’ menu item. Name them as m1, m2 and m3 respectively. Set the OwnerDraw property of these menu items to True.

When a menu is pulled down, the Framework first calls the MeasureItem event handler for each owner-drawn menu item to determine how big the menu needs to be. Then it calls the DrawItem event handler for each owner-drawn menu item to actually do the drawing. That’s why we need to add event handlers for both these events. We must add the event handlers for all the three menu items. This will add total of six functions to the Form1 class. Let’s now add code to these handlers. Look at the MeasureItem event handler for the m1 menu item.

private void m1_MeasureItem ( object sender, MeasureItemEventArgs e )

    {
                e.ItemHeight = 20 ;
                e.ItemWidth = 80 ;
     }

The MeasureItemEventArgs class provides data for the MeasureItem event. The properties we need to set are ItemHeight and ItemWidth. We will need the height of the menu item, which is the greater than the icon height or the font height plus a few pixels, and the width of the menu. We will do the actual drawing in the DrawItem event handler. The handler is given below.

private void m1_DrawItem ( object sender, DrawItemEventArgs e )

      {
          e.Graphics.FillRectangle ( SystemBrushes.Control, e.Bounds ) ;
          e.Graphics.DrawIcon ( new Icon ( “C:\\icon1.ico” ), e.Bounds.Left + 3, e.Bounds.Top + 3 ) ;
          Brush br = new SolidBrush ( Color.Blue ) ;
          e.Graphics.DrawString ( “Red”, new Font ( “Courier New”, 9 ), br,
          ( float )( e.Bounds.Left + 35 ), ( float )
          ( e.Bounds.Top + 2 ) ) ;
       }

The DrawItemEventArgs class contains all the information needed for the user to paint the specified item, including the item index, the Rectangle and the Graphics on which the drawing should be done. In this handler, firstly, we have filled the bounds of the menu item with the standard control color. This is necessary to display the bounding rectangle around the icon. Otherwise the icons will get mixed up.

Next, we have drawn the icon on the menu item using the DrawIcon( ) method. We have left the suitable number of pixels from left and top of the icon. Next to the icon we have displayed the string mentioning the color name. While drawing the string, we must leave the space where the icon has been drawn. We must also keep suitable distance from the icon. That’s why we have left 35 pixels from left side of the menu item bounds.

The MeasureItem and DrawItem event handlers for the other two menu items are same. Only the icon files are different.

Add the Click event handlers for the menu items and set the BackColor property of the form to respective color.

Creating one menu item having three owner drawn menu items is quite manageable, although it results into repetition of code. We can avoid this by inheriting a class from the MenuItem class and handling the event handlers in it.

Create our own iconmenuitem class derived from the MenuItem class. This class is given below.

class iconmenuitem : MenuItem

{
        Icon m_icon ;
        string mtext ;
        public iconmenuitem( )

        {

         }

       public iconmenuitem ( string menutext,
       EventHandler eh, Shortcut sh,
       Icon ico ) : base ( menutext, eh, sh )

        {
            this.OwnerDraw = true ;
            this.DrawItem += new DrawItemEventHandler ( drawitem ) ;
            this.MeasureItem += new MeasureItemEventHandler ( measureitem ) ;
            m_icon = ico ;
            mtext = menutext ;
         }

       private void drawitem ( object sender,DrawItemEventArgs e )

        {
            e.Graphics.FillRectangle ( SystemBrushes.Control, e.Bounds ) ;
            e.Graphics.DrawIcon ( m_icon, e.Bounds.Left + 3, e.Bounds.Top + 3 ) ;
            Brush br = new SolidBrush ( Color.Blue ) ;
            e.Graphics.DrawString ( mtext, new Font ( “Courier New”, 10 ), br,
            ( float )( e.Bounds.Left + this.m_icon.Width + 5 ),
            ( float ) ( e.Bounds.Top + 2 ) ) ;
        }

          private void measureitem ( object sender, MeasureItemEventArgs e )

          {
               e.ItemHeight = 20 ;
               e.ItemWidth = 80 ;
           }

}

In this class we have provided the default constructor and a four-argument constructor. To this constructor we have passed the menu text and the icon to be displayed. We have set the OwnerDraw property to true and added the DrawItem and MeasureItem event handlers. We have stored the icon and menu text passed to the constructor to some data members of iconmenuitem class. The event handlers drawitem( ) and measureitem( ) contains the same code we saw above.

We would have a Menu control named m. The menu m will have one menu item m1 titled ‘Color’ and ‘Color’ menu item will have menu items m2 and m3. The m1 menu item is created by calling default constructor as shown below.

m1 = new ownerdrawn.iconmenuitem( ) ;

Now create the menu items m2 and m3 using the iconmenuitem class as shown below. Add this code to the constructor of the Form1 class after the call to the InitializeComponent( ) method.

Icon i1 = new Icon ( “C:\\icon1.ico” ) ;
m2 = new iconmenuitem ( “Red”,
new EventHandler ( m2_click ),
new Shortcut( ), i1 ) ;
Icon i2 = new Icon ( “C:\\icon2.ico” ) ;
m3 = new iconmenuitem ( “Green”,
new EventHandler ( m3_click ),
new Shortcut( ), i2 ) ;
m1.MenuItems.AddRange ( new
System.Windows.Forms.MenuItem[ ]
{ m2, m3 } ) ;

Add m1, m2 and m3 as data members of type iconmenuitem to the Form1 class.

The Click event handler for the m2 menu item is given below. In the same way add the event handler for the m3 menu item.

private void m2_click ( object sender, System.EventArgs e )

{
     BackColor = Color.Red ;
}

The output of the program is shown below.

Yashavant Kanetkar, one of the first Express Computer columnists, is an established software expert, speaker and author with several best-sellers to his credit, including titles like “Let Us C” and the “Fundas” series. Contact him at kanetkar@dcubesoft.com

 

<Back to top>


© Copyright 2003: Indian Express Group (Mumbai, India). All rights reserved throughout the world. This entire site is compiled in
Mumbai by The Business Publications Division of the Indian Express Group of Newspapers.
Please contact our Webmaster for any queries on this site.