Search Forum
(57415 Postings)
Search Site/Articles

Archived Articles
712 Articles

C# Books
C# Consultants
What Is C#?
Download Compiler
Code Archive
Archived Articles
Advertise
Contribute
C# Jobs
Beginners Tutorial
C# Contractors
C# Consulting
Links
C# Manual
Contact Us
Legal

GoDiagram for .NET from Northwoods Software www.nwoods.com


              
Printable Version

OwnerDraw Menu Items in C#
By Shripad Kulkarni

Download : SouceCode

Windows applications, which focuses mainly on its GUI aspects , can make use of the ownerdraw properties of the various forms components. Once such component that allows us to define our own drawing and painting of items is the Menu component of Windows Forms.

This article will explain to you how we can draw our own menu items with our own fonts , pictures , background color and other graphics objects.

Step 1 : Create a simple windows form application.

Click File - > New -> Project - >

Create new application OD_Menu.

In the designer view for the default form created , add a new "Main Menu" component from the Windows Forms Toolbox.

Using the designer , create menu and menu items

 

We need to ownerdraw not only the top level menu items, but also all the submenu items.

For every menu item select the "Properties" and set the OwnerDraw option to 'True".

For every owerdraw menu item the application will call 2 functions..

  • DrawItem . This function will do the actual painting and drawing of the intended menu item.
  • Measure Item . This function is called to set the height / width of the menu item.

We need to add these 2 events from the "Events" tab of the menu properties.

Select the properties for the "File" menu item.

Click on the Events tab.

Double Click the Draw Item option. It will add a default handler to handle the drawing of the "File" menu item.

  • private void menuItem1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)

Double Click the MeasureItem otpion. It will add a default handler

  • private void menuItem1_MeasureItem(object sender, System.Windows.Forms.MeasureItemEventArgs e)

Now we need to add the sametype of DrawItem and MeasureItem for the sub menu items. We are creating a different event handler for the subitems , since we need to do some more fancy stuff with the sub items like drawing icons or bitmaps.

Select the first subitem "Open" and add the same 2 events for this item.

  • private void menuItem1_MeasureItem(object sender, System.Windows.Forms.MeasureItemEventArgs e)
  • private void menuItem2_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)

Important : Since we need to have a DrawItem and MeasureItem for each and every item , it does not make sense to duplicate the events for every menu item. We can have the mainmenu items ( File / Options / Help ) be handle via a common event handler and we can have the submenu items like ( Open /Close ... About ) be routed through another common event handler.

Here is how to do this..

For every other main menu item like "Options and Help". Select the item in designer. Click proerties. Click the Events tab.

Click the listbox next to the DrawItem and select the menuItem1_DrawItem option from the list.

Click the listbox next to the MeasureItem and select the menuItem1_MeasureItem option from the list.

For every other sub menu items like "Close / Exit / Security / Network / About". Click proerties. Click the Events tab.

Click the listbox next to the DrawItem and select the menuItem2_DrawItem option from the list.

Click the listbox next to the MeasureItem and select the menuItem2_MeasureItem option from the list.

We are all set to add our own code the handle the drawing and paiting of the TopLevel Menu Items and the SubItems.
Here is the code for the Top Level menu Items
private void menuItem1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
    {
      Rectangle rc = new Rectangle(e.Bounds.X+1 , e.Bounds.Y+1, 
                 e.Bounds.Width-5, e.Bounds.Height-1);
      e.Graphics.FillRectangle(new SolidBrush(Color.LightGray) , rc);
      MenuItem s = (MenuItem)sender ;
      string s1 = s.Text ;
      StringFormat sf = new StringFormat();
      sf.Alignment = StringAlignment.Center ;
      e.Graphics.DrawString(s1 , new Font("Ariel" ,10), new SolidBrush(Color.Black) , rc , sf );
      Console.WriteLine(e.State.ToString());
      if ( e.State ==  (DrawItemState.NoAccelerator | DrawItemState.Selected)  ||  
        e.State ==  ( DrawItemState.NoAccelerator | DrawItemState.HotLight)  ) 
      {
        e.Graphics.FillRectangle(new SolidBrush(Color.CornflowerBlue) , rc);
        e.Graphics.DrawString( s1 , new Font("Veranda" , 10) , 
                         new SolidBrush(Color.Black), rc ,sf);
        e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Black)), rc );
      }
      e.DrawFocusRectangle();
      e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Black), 2 ), rc );
    }

    private void menuItem1_MeasureItem(object sender, System.Windows.Forms.MeasureItemEventArgs e)
    {
      e.ItemWidth = 75 ;
      e.ItemHeight = 25 ;
    }
Here is the code for the Sub menu Items
    private void menuItem2_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
    {
      Rectangle rc = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height);
      e.Graphics.FillRectangle(new SolidBrush(Color.LightGray) , rc);
      MenuItem s = (MenuItem)sender ;
      string s1 = s.Text ;
      StringFormat sf = new StringFormat();
      sf.Alignment = StringAlignment.Far ;
      sf.LineAlignment  = StringAlignment.Center;
      Rectangle rcText = rc ;
      rcText.Width-=5 ;
      e.Graphics.DrawString(s1 , new Font("Veranda" ,10), 
                     new SolidBrush(Color.Blue) , rcText, sf );
      e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.LightGray)), rc );

      if ( e.State == ( DrawItemState.NoAccelerator | DrawItemState.Selected)) 
      {
        e.Graphics.FillRectangle(new SolidBrush(Color.CornflowerBlue) , rc);
        e.Graphics.DrawString( s1 , new Font("Veranda" , 10 , 
                        FontStyle.Bold | FontStyle.Underline
                 ) , new SolidBrush(Color.Yellow), rcText,sf);
        e.Graphics.DrawRectangle(new Pen(new SolidBrush(Color.Black)), rc );
        e.DrawFocusRectangle();
      }
      
      Image useImage = null ;

      if ( s1 == "Open" ) 
      {
        useImage = img_fileopen;
      }
      if ( s1 == "Close" )
      {
        useImage = img_close;
      }
      if ( s1 == "Exit" )
      {
        useImage = img_exit;
      }
      if ( s1 == "Security" )
      {
        useImage = img_security;
      }
      if ( s1 == "Network" )
      {
        useImage = img_network;
      }
      if ( s1 == "About" )
      {
        useImage = img_about;
      }

      if ( useImage != null ) 
      {
        SizeF sz = useImage.PhysicalDimension;
        e.Graphics.DrawImage(useImage, e.Bounds.X+5 
                                , ( e.Bounds.Bottom + e.Bounds.Top ) /2 - sz.Height/2);
      }

    }

    private void menuItem2_MeasureItem(object sender, System.Windows.Forms.MeasureItemEventArgs e)
    {
      e.ItemWidth = 75 ;
      e.ItemHeight = 25 ;  
    }
Compile and execute the application.