Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Context Menu and Event Handling in Visual Basic .NET

0.00/5 (No votes)
8 Nov 2004 1  
This article describes ContextMenu and event handling in Visual Basic .NET.

Contents

Introduction

This article targets those who have not yet worked with ContextMenu in .NET environment and would like to understand a little easy way of how ContextMenu and its associated event handler works. How can a context menu for a notify icon be programmatically generated when the user right clicks on the notify icon? As a prerequisite, you should have a little bit idea of object oriented programming.

This Windows application feature allows gives you the ability to right-click on any control of your Windows Form and get a context-sensitive menu. If a user right-clicks or left-clicks in a .NET application, the form shows its own menu. This is very helpful for the user to know what options are attached to a particular control or an object.

ContextMenu in .NET

A ContextMenu is a shortcut menu, which you can use to give context-specific menu options of a specified object item to the user. You can write the code to display the shortcut menu whenever the user right-clicks on a specified control such as TextBox, ListBox, ListView etc. Typically, a shortcut menu is displayed when a user clicks the right mouse button over a control or the form itself. The beauty of .NET in terms of ContextMenu is that it is possible to use one ContextMenu in more than one control. What you need to do is set the ContextMenu property of each control to ContextMenu class. Even you can also create nested submenus in a ContextMenu.

ContextMenu is in some ways simpler than MainMenu, mostly because it is smaller, and sometimes contains only a list of menu items without any submenus.

Example

The following example gives a step by step instruction to use a shortcut menu assigned to the ListView and TextBox control to display some of the menu items based on the user right-click event of the mouse in a specified control. This means the context menu will be changed based on each control. This example creates an event handler for the PopUp event of the ContextMenu. The code in the event handler determines which of two controls, a ListView named listView1 and a TextBox named textBox1, is the control displaying the shortcut menu. Depending on which control caused the ContextMenu to display its shortcut menu, the control adds the appropriate MenuItem objects to the ContextMenu. This example assumes that you have an instance of the ContextMenu class, named contextMenu1, defined within the form. This example also assumes that you have a TextBox and ListView added to a form, and that the ContextMenu property of these controls is set to ContextMenu1.

Steps to create the context menu

  1. Placing ContextMenu Control:

    Drag and drop a ContextMenu on to your form from the toolbox.

    Simply, if you want to place a context menu on your form, just drop a ContextMenu object from the form designer toolbox on to the Form object, then type in the choices you want to present. Bring up the menu in your program, and respond to the events fired when the user clicks on a context menu choice.

  2. Placing ListView and TextBox Controls:

    Drag and drop a ListView and a TextBox control onto your form.

  3. Setting ContextMenu Property:

    Add a ContextMenu to your form and set the ContextMenu property of your TextBox and ListBox to it. Then, in the PopUp event of your ContextMenu, you can dynamically create the MenuItems as shown below. You can trap which menu item was selected using an old school Select Case based on the MenuItem text:

    Set the ContextMenu property of each control to ContextMenu1.

    A ContextMenu is associated with a control by changing the ContextMenu property of a control. The properties for the ContextMenu are both in the properties for the control and the ContextMenu component.

  4. MouseUp Event Routine:

    What kind of events are you firing and what will you be doing with ContextMenu control? As you can see from the code in the next section, you can determine which item was clicked by casting the "sender" variable to a MenuItem and querying the Text property. You can use that value to pass to another function or do something with it.

    Write a routine on the �MouseUp� event on your control. This will happen if the right mouse button was clicked and released; display the context menu assigned to the listView1 or TextBox1 control.

    Private Sub listView1_MouseUp(Byval Sender as Object, _
           Byval e As System.Windows.Forms.MouseEventArgs) _
           Handles listView1.MouseUp
      'Checking the Mouse right Button
    
      If e.Button = MouseButtons.Right Then
        ContextHandler(listView1,e)
        listView1.ContextMenu.Show(listView1, New Point(e.X,e.Y))
      End if
    End sub
    
    Private Sub TextBox1_MouseUp(Byval Sender as Object, _
           Byval e As System.Windows.Forms.MouseEventArgs) _
           Handles TextBox1.MouseUp
    
      'Checking the Mouse right Button
    
      If e.Button = MouseButtons.Right Then
        ContextHandler(TextBox1,e)
        TextBox1.ContextMenu.Show(TextBox1, New Point(e.X,e.Y))
      End if
    End sub

    Based on your programming skills, you can even reduce the number of lines of your source code by putting this event in a separate procedure and calling this procedure in control mouse up event. For example, I have recreated this source code in a different way, which you can see below:

    Private Sub HandleMouseUp(Byval Control as Object, _
           Byval e As System.Windows.Forms.MouseEventArgs) 
    
      'Checking the Mouse right Button
    
      If e.Button = MouseButtons.Right Then
        ContextHandler(Control,e)
        Control.ContextMenu.Show(Control, New Point(e.X,e.Y))
      End if
    End sub

    Call the routine �HandleMouseUp� to your MouseUp event of ListView1 control.

    Private Sub listView1_MouseUp(Byval Sender as Object, _
           Byval e As System.Windows.Forms.MouseEventArgs) _
           Handles listView1.MouseUp
      HandleMouseUp(listView1,e)
    End sub

    Similarly, call the HandleMouseUp procedure in TextBox1 MouseUp event:

    Private Sub TextBox1_MouseUp(Byval Sender as Object, _
           Byval e As System.Windows.Forms.MouseEventArgs) _
           Handles TextBox1.MouseUp
      HandleMouseUp(listView1,e)
    End sub

    Wow, it reduced a lot of lines in your source code and looks neat. Right! As I mentioned earlier, you can write your own procedure in your source code based on your programming expertise or skills and appropriate coding standards. I would prefer to create a catalog of functions, and then, depending on the text in your new menu item, you can handle it with only one handler that checks the text of the sender as shown above.

    It won�t bother to walk you through this process, as it is very intuitive. However, one change that you need to be aware of is that context menus are no longer taken from a form�s main menu. Instead, you now add a separate ContextMenu control for each context menu. To edit a context menu, click to select the corresponding ContextMenu control from the component tray. The menu will appear at the top as though it were a normal drop-down menu, except that you�ll be able to edit it as needed.

  5. Writing ContextHandler Procedure:

    Next step is to write a �ContextHandler� routine.

    Protected Sub ContextHandler (ByVal sender As System.Object, _
           ByVal e As System.EventArgs)
    
      'ListView Menu Captions
    
      Const LVW_NEW_MENU = "&New"
      Const LVW_OPEN_MENU = "&Open File"
      Const LVW_PREVIEW = "&Preview"
      Const LVW_DELETE = "&Delete"
    
      'Text Menu Captions
    
      Const TEXT_MENU1 = "Text Menu&1"
      Const TEXT_MENU11 = "Text Menu1&1" �Sub Menu 1
      Const TEXT_MENU12 = "Text Menu1&2" �Sub Menu 2
      Const TEXT_CUT = "&Cut"
      Const TEXT_COPY = "&Copy"
      Const TEXT_PASTE = "&PASTE"
      Const TEXT_SELECT_ALL = "&Select All"
    
      Const SEPARATOR = "-"
    
      Const LIST_VIEW_NAME=�listView1�
      Const TEXT_BOX_NAME=�TextBox1�
    
      ' Clear all previously added MenuItems.
    
      ContextMenu1.MenuItems.Clear()
    
      If sender.name = LIST_VIEW_NAME Then 
      'ContextMenu1.SourceControl is
    
    
      'Define the MenuItem object to display for the ListView1.
    
    
      Dim menuItem1 As New MenuItem(LVW_NEW_MENU)
      Dim menuItem2 As New MenuItem(LVW_OPEN_MENU)
      Dim menuItem3 As New MenuItem(SEPARATOR)
      Dim menuItem4 As New MenuItem(LVW_PREVIEW)
      Dim menuItem5 As New MenuItem(SEPARATOR)
      Dim menuItem6 As New MenuItem(LVW_DELETE)
      
      ' Add MenuItems to display for the TextBox.
    
      ContextMenu1.MenuItems.Add(menuItem1)
      ContextMenu1.MenuItems.Add(menuItem2)
      ContextMenu1.MenuItems.Add(menuItem3)
      ContextMenu1.MenuItems.Add(menuItem4)
      ContextMenu1.MenuItems.Add(menuItem5)
    
      If listView1.FocusedItem Is Nothing Then
        menuItem2.Enabled = False
        menuItem4.Enabled = False
        menuItem6.Enabled = False
      End If
       
      ElseIf sender.name = TEXT_BOX_NAME Then 
      'ContextMenu1.SourceControl is
    
    
        'Define the MenuItem object to display for the TextBox1.
    
    
        Dim menuItem7 As New MenuItem(TEXT_MENU1)
        Dim menuItem8 As New MenuItem(TEXT_MENU11)
        Dim menuItem9 As New MenuItem(SEPARATOR)
        Dim menuItem10 As New MenuItem(TEXT_MENU12)
        Dim menuItem11 As New MenuItem(SEPARATOR)
        Dim menuItem12 As New MenuItem(TEXT_CUT)
        Dim menuItem13 As New MenuItem(TEXT_COPY)
        Dim menuItem14 As New MenuItem(TEXT_PASTE)
        Dim menuItem15 As New MenuItem(SEPARATOR)
        Dim menuItem16 As New MenuItem(TEXT_SELECT_ALL)
    
        'Set the checked property to true since 
    
        'this is the default value.
    
        menuItem8.Checked = True
        'Define a shortcut key combination for the menu item.
    
        menuItem9.Shortcut = Shortcut.CtrlS
    
        'Add menuItem8 and menuItem9 to menuItem7's 
    
        'list of menu items or sub menus.
    
        MenuItem7.MenuItems.Add(menuItem8)
        MenuItem7.MenuItems.Add(SEPARATOR)
        MenuItem7.MenuItems.Add(menuItem9)
    
        'Add MenuItems to display for the TextBox.
    
    
        ContextMenu1.MenuItems.Add(menuItem7)
    
        ContextMenu1.MenuItems.Add(menuItem10)
        ContextMenu1.MenuItems.Add(menuItem11)
        ContextMenu1.MenuItems.Add(menuItem12)
        ContextMenu1.MenuItems.Add(menuItem13)
        ContextMenu1.MenuItems.Add(menuItem14)
        ContextMenu1.MenuItems.Add(menuItem15)
        ContextMenu1.MenuItems.Add(menuItem16)
    
        'If no text, disable the cut, copy, paste menus
    
        If TextBox1.Text = �� Then
          MenuItem12.Enabled=false
          MenuItem13.Enabled=false
          MenuItem14.Enabled=false
          MenuItem16.Enabled=false
        End If
      End If
    End Sub

    As I mentioned earlier, you can even reduce the number of lines in your source code breaking it into different functions. The above line of code is split into different sub routines. This is listed below:

    A new procedure called AddContextMenu will add a MenuItem to the context menu based on the Caption parameter. The details are listed in the following block of code:

    Private Sub AddContextMenu(ByVal Caption As String, _
           Optional ByVal IsEnabled As Boolean = True)
    
      Dim objMenuItem As MenuItem
    
      objMenuItem = New MenuItem
      objMenuItem.Text = Caption
      objMenuItem.Enabled = IsEnabled
      ContextMenu1.MenuItems.Add(objMenuItem)
      ' Handling Popup menu item click event
    
      AddHandler objMenuItem.Click, AddressOf CMenuClick
    End Sub

    The AddHandler routine will execute with ContextHandler object event at any time during program execution. AddHandler routine details are explained in the consuming events section, which is described at the end of this article.

    Based on the new procedure �AddContextMenu�, which we created above, we can modify the �ContextHandler� procedure as well.

    Protected Sub ContextHandler (ByVal sender As System.Object, _
             ByVal e As System.EventArgs)
    
      'ListView Menu Captions
    
      Const LVW_NEW_MENU = "&New"
      Const LVW_OPEN_MENU = "&Open File"
      Const LVW_PREVIEW = "&Preview"
      Const LVW_DELETE = "&Delete"
    
      'Text Menu Captions
    
      Const TEXT_MENU1 = "Text Menu&1"
      Const TEXT_MENU11 = "Text Menu1&1" �Sub Menu 1
      Const TEXT_MENU12 = "Text Menu1&2" �Sub Menu 2
      Const TEXT_CUT = "&Cut"
      Const TEXT_COPY = "&Copy"
      Const TEXT_PASTE = "&PASTE"
      Const TEXT_SELECT_ALL = "&Select All"
    
      Const SEPARATOR = "-"
    
      Const LIST_VIEW_NAME=�listView1�
      Const TEXT_BOX_NAME=�TextBox1�
    
      ' Clear all previously added MenuItems.
    
      ContextMenu1.MenuItems.Clear()
    
      If ContextMenu1.SourceControl is listView1 Then
        'or sender.name = LIST_VIEW_NAME
    
        ' Define the MenuItem object to display for the ListView1.
    
        AddContextMenu(LVW_NEW_MENU)
        AddContextMenu(LVW_OPEN_MENU, listView1.FocusedItem Is Nothing)
        AddContextMenu(SEPARATOR)
        AddContextMenu(LVW_PREVIEW, listView1.FocusedItem Is Nothing)
        AddContextMenu(SEPARATOR)
        AddContextMenu(LVW_DELETE, listView1.FocusedItem Is Nothing)
       
      ElseIf ContextMenu1.SourceControl is TextBox1 Then
        'or sender.name = TEXT_BOX_NAME Then 'ContextMenu1.SourceControl is
    
        ' Define the MenuItem object to display for the TextBox1.
    
    
        ' Set the checked property to true since this is the default value.
    
        SubmenuItem1.Checked = True
        ' Define a shortcut key combination for the menu item.
    
        SubmenuItem2.Shortcut = Shortcut.CtrlS
    
        ' Add menuItem8 and menuItem9 to menuItem7's 
    
        ' list of menu items or sub menus.
    
        ' My AddContextMenu procedure is not handling
    
        ' to support nested submenu creation
    
        MenuItem1.MenuItems.Add(SubmenuItem1)
        MenuItem1.MenuItems.Add(SEPARATOR)
        MenuItem1.MenuItems.Add(SubmenuItem2)
    
        ' Add MenuItems to display for the TextBox.
    
        ContextMenu1.MenuItems.Add(menuItem)
        AddContextMenu(SEPARATOR)
        AddContextMenu(LVW_NEW_MENU)
        AddContextMenu(TEXT_CUT, TextBox1.Text = ��)
        AddContextMenu(TEXT_COPY, TextBox1.Text = ��)
        AddContextMenu(TEXT_PASTE, TextBox1.Text = ��)
        AddContextMenu(SEPARATOR)
        AddContextMenu(TEXT_SELECT_ALL, TextBox1.Text = ��)
      End If
    End Sub

    In the following HandleMouseUp event, you need to remove the ContextHandler method in order to use ContextMenu1.SourceControl method because the function MenuSelected will automatically handle the event ContextMenu1.Popup. The revised procedure is shown below:

    Private Sub HandleMouseUp(Byval Control as Object, _
          Byval e As System.Windows.Forms.MouseEventArgs)
    
      ' Checking the Mouse right Button
    
      If e.Button = MouseButtons.Right Then
        Control.ContextMenu.Show(Control, New Point(e.X,e.Y))
      End if
    End sub

    Again, in order to get fully functional, you need to add a new handle for ContextMenu1 popup, which I created below and named as �HandlePopup�.

    Private Sub HandlePopup(ByVal sender As Object, _
           ByVal e As System.EventArgs) Handles ContextMenu1.Popup
      MyPopupEventHandler(sender, e)
    End Sub

    Note 1: I used a constant name called �SEPARATOR� for separating menu items, which is same as the old version of VB. You can even use Break or BreakLine method from the ContextMenu class to include a separator into menu items.

    Note 2: I replaced Sender.Name method with ContextMenu1.SourceControl. The Sender.Name will also function as same as the ContextMenu1.SourceControl, but, I personally feel this is much better to handle context menu in the right place. If you are using Sender.Name instead of ContextMenu1.SourceControl, you need to add the following lines of code in each of the control event.

    Note 3: The AddContextMenu procedure does not support adding nested sub menus.

  6. Consuming Events:

    An event is an action that informs an application that something has happened in the object. For example, when you click a particular menu item from the ContextMenu in order to fire the associated event, you need to define a new EventHandler routine into your program.

    To consume a ContextMenu event in this application, you must provide an event handler (an event-handling method) that executes program logic in response to the event, and register the event handler with the event source.

    To wire an event handler to the ContextMenu, you must create an instance of EventHandler that takes a reference to ContextMenu_Clicked in its argument, and add this delegate instance to the PopUp_Click event of the ContextMenu, as shown in the following example.

    AddHandler method associates an event with an event handler, and it allows you to start event handling at any time during program execution.

    Please go through the program listed in, which is shown below:

    Private Sub AddContextMenu(ByVal Caption As String, _
            Optional ByVal IsEnabled As Boolean = True)
    
      Dim objMenuItem As MenuItem
    
      objMenuItem = New MenuItem
      objMenuItem.Text = Caption
      objMenuItem.Enabled = IsEnabled
      ContextMenu1.MenuItems.Add(objMenuItem)
      ' Handling Popup menu item click event
    
      AddHandler objMenuItem.Click, AddressOf CMenuClick
    
    End Sub

    The AddHandler statement in the above code will fire an event whenever a user clicks on the menu item, and executes the procedure cMenuClick which is listed below:

    Private Sub CMenuClick(ByVal sender As Object, _
            ByVal e As System.EventArgs)
    
      'Point to menu item clicked
    
      Dim objCurMenuItem As MenuItem = CType(sender, MenuItem)
      'create the submenu based on whatever selection is being made, mnuSelection
    
      Select Case objCurMenuItem.Text
        Case LVW_NEW_MENU: Msgbox(�New Menu�) 
        Case LVW_NEW_MENU: Msgbox(�New Menu�)
        Case LVW_OPEN_MENU: Msgbox(�New Menu�)
        Case LVW_PREVIEW: Msgbox(�New Menu�)
        Case LVW_DELETE Msgbox(�New Menu�)
        Case TEXT_CUT: Msgbox(�New Menu�)
        Case TEXT_COPY: Msgbox(�New Menu�)
        Case TEXT_PASTE: Msgbox(�New Menu�)
        Case TEXT_SELECT_ALL: Msgbox(�New Menu�)
      End Select
    
      objCurMenuItem = Nothing
    
    End Sub

Sample Screenshots

Requirements

  • Namespace: System.Windows.Forms.
  • Platforms: Windows 98, Windows NT 4.0, Windows Millennium Edition, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003 family, .NET Compact Framework - Windows CE .NET.
  • Assembly: System.Windows.Forms (in System.Windows.Forms.dll).

Summary

Microsoft has invested heavily in Visual Studio .NET. Visual Studio .NET lets users easily tailor the tool to their personal working style and enables them to accommodate team practices. The Visual Basic 7.0 language gains several major features and many smaller enhancements that together provide significant increases in ease of use and developer productivity. With VB.NET, Microsoft has adopted a whole new philosophy. Rather than specific tools that do specific things, they give you objects that do the basic things. There are menu objects instead.

This article showed how to implement a simple context menu for the ListBox and TextBox controls. The definitions of ContextMenu, MainMenu, and MenuItem in VB.NET show that all are derived from the Menu abstract class. A lot of the great performance that you can get from menus is based on extending the properties and methods in these classes.

My next article is going to explain about Context Menu Extension in Windows Explorer.

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