Click here to Skip to main content
15,868,016 members
Articles / Programming Languages / Visual Basic

Dynamic Submenus on Context Menus

Rate me:
Please Sign up or sign in to vote.
4.72/5 (8 votes)
15 Apr 2010CPOL5 min read 51K   1.4K   16   4
Adding a Submenu to a Context Menu via Visual Basic

Introduction

Many of us have gotten so used to using the graphical development tools to place elements on our Windows forms, we have either forgotten or never learned how to write our own code to build these elements. This article shows how to dynamically add a submenu to a context menu and how to attach code to process the events generated by a submenu item. This could be useful, for example, in opening recently viewed files.

Background

Recently, I received an email from a colleague who wished to dynamically add a submenu to a context menu. My colleague added the context menu with the main items using the graphical tools, and then ran into difficulties. The submenu items to be added, although almost identical to the user, had different processing requirements.

I believe that if one person asks a question, many others have the same question but are afraid to ask for the fear of looking foolish. Thus, I have written this article.

I have simplified the problem to its most basic form, both to hide any reference to my colleague or my colleague's employer, thus preserving confidentially, and for ease of understanding.

The Plan

We will begin using the traditional visual tools to create the basic Windows form and context menu. In the handlers for the context menu, we will add the submenu items and their handlers.

As this article is written with beginners in mind, I often state that which should be obvious to more experienced readers. Please forgive me if I appear to insult your intelligence or experience.

The Traditional Part

Adding the Context Menu

Start a new project and, using the tool box, select the context menu strip tool and add it to the form. Then, using the area marked "Type Here", add the following three context menu items:

  • Add Menu Item
  • Show Menu Items
  • Clear Menu Items

For convenience and ease of reading, I recommend naming these miAddItem, miShowItems and miClearItems, respectively.

For beginners, and those who have never worked with context menus before, I will step you through the process of creating the standard handlers for context menu items. Those with more experience should skip to the next section.

Double-click on the "Add Menu Item" item and the appropriate handler will be automatically generated in the Visual Basic file:

VB.NET
Private Sub miAddItem_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles miAddItem.Click

End Sub     ' miAddItem_Click

Double-click on the "Clear Menu Items" item and the appropriate handler will be automatically generated in the Visual Basic file:

VB.NET
Private Sub miClearItems_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles miClearItems.Click

End Sub     ' miClearItems_Click

At this point, we could also add a handler for the "Show Menu Items". This would catch all clicks to mkShowItems, but not to the submenu items. This does not provide the behavior we desire.

Add the Other Visual Items

I have added a few sample Visual Basic controls to the main window, Form1. These are controlled by the event handlers that we will create later. Please refer to the source code for more details.

The Submenu Items

Two sets of objects must be added next: the menu item handlers and the submenu item handlers. To avoid some extraneous error messages, let us begin with the submenu handlers.

Adding the Submenu Item Handlers

For this problem, we will add two event handlers, one for all submenu items and one for the third submenu item only. These will handle the selection of the submenu items that we will create at run-time. Notice that unlike Visual Basic generated event handlers, these handlers do not have a Handles clause in the subroutine definition.

Handler for Every Submenu Item

All this handler does is take the number of the submenu and display it in a text box on the main form. Obviously, this can be replaced with a handle which actually performs a useful function, perhaps selecting a file to open.

The parameters for the handler are determined by the event that the handler is going to capture. For a click event, the parameters are the object clicked on, called the sender, and a set of event arguments. The sender tells us which submenu item was clicked. The event arguments are usually empty.

VB.NET
Private Sub myPrivateMenuItemHandler(ByVal sender As Object, ByVal e As EventArgs)
    Dim i As Integer
    Dim myItem As ToolStripMenuItem

    ' Extract the tag value from the item received.
    myItem = CType(sender, ToolStripMenuItem)
    i = CInt(myItem.Tag)

    ' Display the item number as the last item seen.
    Me.txtLastItemViewed.Text = i.ToString

End Sub     ' myPrivateMenuItemHandler

Handler for the Third Submenu Item

Again, this handler is just a toy. It simply checks a box and changes the background color.

VB.NET
Private Sub mySpecialMenuItemHandler(ByVal sender As Object, ByVal e As EventArgs)

    ' Flag the checkbox
    Me.cbxItem3Seen.Checked = True
    Me.cbxItem3Seen.BackColor = Color.LightCyan

End Sub     ' mySpecialMenuItemHandler

Adding the Submenu Items

When the Add Menu Item is selected, we need to create a new submenu item, label it with some text and attach the handler. The text we will use is just Menu item # and a number.

VB.NET
Private Sub miAddItem_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles miAddItem.Click
    Dim i As Integer
    ' Create a new submenu item
    Dim myMenuItem As New ToolStripMenuItem

    ' Get the submenu item number from the menu item itself
    i = Me.miShowItems.DropDownItems.Count + 1

    ' Set up the label and set the tag to a value that the handler can use
    myMenuItem.Text = "Menu item #" & i.ToString
    myMenuItem.Tag = i
				
    ' Attach the primary handler
    AddHandler myMenuItem.Click, AddressOf Me.myPrivateMenuItemHandler

    ' Add an additional handler to the third submenu item only
    If i = 3 Then
        AddHandler myMenuItem.Click, AddressOf mySpecialMenuItemHandler
        Me.cbxItem3Seen.Enabled = True
        Me.cbxItem3Seen.Checked = False
        Me.cbxItem3Seen.BackColor = Color.LawnGreen
    End If

    ' Add the new submenu item to the menu item
    Me.miShowItems.DropDownItems.Add(myMenuItem)

    ' Set the visible submenu item counter
    Me.txtItemCount.Text = Me.miShowItems.DropDownItems.Count.ToString

End Sub     ' miAddItem_Click

The AddHandler statement requires the event you want to capture and the address of the handler subroutine. In our case, we want to capture the click event.

The submenu items are a simple list attached to the miShowItems menu item. This is done with the standard add method.

Clearing the Submenu Items

To remove all of submenu items, just clear the list attached to the miShowItems menu item, using the clear method. The system garbage collector will dispose of the submenu items for us.

VB.NET
Private Sub miClearItems_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles miClearItems.Click

    ' Clear the list of subitems
    Me.miShowItems.DropDownItems.Clear()

    ' Reset the count of subitems
    Me.txtItemCount.Text = Me.miShowItems.DropDownItems.Count.ToString

    ' Reset the checkbox
    Me.cbxItem3Seen.Checked = False
    Me.cbxItem3Seen.BackColor = SystemColors.Control
    Me.cbxItem3Seen.Enabled = False

End Sub     ' miClearItems_Click

Using the Code

The attached code is a zipped copy of the Visual Basic solution directory. I have used VB2005 to make the solution easily available to the widest audience. The executable is in the ./MenuMadness/bin/Debug subdirectory. Execute it by double-clicking on it from Windows Explorer or from the My Computer icon.

Points of Interest

Although this demonstration project only captures the click event for a submenu item, the AddHandler statement can be used to capture any event from almost any object and send it to a custom handler. It does not matter whether the sending object is defined at design time or defined dynamically.

History

This is a running update of any changes or improvements I have made.

03-27-2010Text reviewed and revised
02-04-2010Initial version

License

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


Written By
Software Developer (Senior) S & D Acres
United States United States
BSEE 1972, Polytechnic Institute of Brooklyn, Brooklyn, NY
MSCS 1978, Stevens Institute, Hoboken, NJ

Now, I live in Texas with my wife and children and raise non-dairy (aka "meat") goats and chickens for fun and (maybe next year) profit.

As a hobby (we all need one, don't we?? Smile | :) ), I write agriculture-related software and play with O-gauge trains.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Member 767017618-Jul-12 16:46
Member 767017618-Jul-12 16:46 
QuestionWhat Code? Pin
Johnny J.11-Apr-10 21:21
professionalJohnny J.11-Apr-10 21:21 
AnswerRe: What Code? Pin
Jalapeno Bob12-Apr-10 4:55
professionalJalapeno Bob12-Apr-10 4:55 
AnswerRe: What Code? Pin
Jalapeno Bob12-Apr-10 8:22
professionalJalapeno Bob12-Apr-10 8:22 

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.