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.
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
.
- 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.
- Placing ListView and TextBox Controls:
Drag and drop a ListView
and a TextBox
control onto your form.
- 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 MenuItem
s 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.
- 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
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
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)
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.
- Writing ContextHandler Procedure:
Next step is to write a �ContextHandler
� routine.
Protected Sub ContextHandler (ByVal sender As System.Object, _
ByVal e As System.EventArgs)
Const LVW_NEW_MENU = "&New"
Const LVW_OPEN_MENU = "&Open File"
Const LVW_PREVIEW = "&Preview"
Const LVW_DELETE = "&Delete"
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�
ContextMenu1.MenuItems.Clear()
If sender.name = LIST_VIEW_NAME Then
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)
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
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)
menuItem8.Checked = True
menuItem9.Shortcut = Shortcut.CtrlS
MenuItem7.MenuItems.Add(menuItem8)
MenuItem7.MenuItems.Add(SEPARATOR)
MenuItem7.MenuItems.Add(menuItem9)
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 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)
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)
Const LVW_NEW_MENU = "&New"
Const LVW_OPEN_MENU = "&Open File"
Const LVW_PREVIEW = "&Preview"
Const LVW_DELETE = "&Delete"
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�
ContextMenu1.MenuItems.Clear()
If ContextMenu1.SourceControl is listView1 Then
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
SubmenuItem1.Checked = True
SubmenuItem2.Shortcut = Shortcut.CtrlS
MenuItem1.MenuItems.Add(SubmenuItem1)
MenuItem1.MenuItems.Add(SEPARATOR)
MenuItem1.MenuItems.Add(SubmenuItem2)
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)
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.
- 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)
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)
Dim objCurMenuItem As MenuItem = CType(sender, MenuItem)
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
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.
My next article is going to explain about Context Menu Extension in Windows Explorer.