DatLicht
DatLicht

Reputation: 148

How can I find the sender of ContextMenuStrip?

Situation:

I have a context menu in a VB.NET form with fires an event handler on ItemClicked. The auto-generated subroutine receives sender and e as parameters. As I don't reinvent the wheel multiple times, I linked this context menu to three text boxes. Let's name them Textbox1, Textbox2 and Textbox3.

Problem: How can I figure out in which textbox the menu was opened?

Okay, what did I already try?

Upvotes: 3

Views: 2688

Answers (2)

The ContextMenuStrip has a SourceControl property which contains a reference to the control which opened the menu. The event fires from one of the ToolStripMenuItems in the ContextMenuStrip, so you have to get the "parent" first:

' cast sender to menuitem
Dim mi = CType(sender, ToolStripMenuItem)
' cast mi.Owner to CMS
Dim cms = CType(mi.Owner, ContextMenuStrip)

' the control which opened the menu:
Console.WriteLine(cms.SourceControl.Name)

Under certain conditions the SourceControl can get lost but you can track it yourself with a variable and the parent ContextMenuStrip Opening event:

' tracking var:
Private MenuSourceControl As Control
Private Sub cms_Opening(sender As Object, e As CancelEventArgs) Handles cms.Opening
    ' set reference in case/before it is lost
    MenuSourceControl = CType(sender, ContextMenuStrip).SourceControl
End Sub

Private Sub CutToolStripMenuItem_Click(sender...
    If MenuSourceControl IsNot Nothing Then
        ' do your stuff

        ' optionally clear the tracking var
        MenuSourceControl = Nothing
    End If
End Sub

It should be also easier to get the SourceControl when dealing with sub items


You can also capture the related control in the MouseDown event of the related Control in cases where the same menu is used with different controls:

Private Sub lv2_MouseDown(sender As Object, 
         e As MouseEventArgs) Handles lv2.MouseDown,
                  myLV.MouseDown, lv1.MouseDown ...

    If e.Button = Windows.Forms.MouseButtons.Right Then
        MenuSourceControl = DirectCast(sender, Control)
    End If
End Sub

Upvotes: 2

DatLicht
DatLicht

Reputation: 148

Okay, I found a solution that works fine, and here's the code for all VB.NET coders that have the same problem.

The context menu is linked in TextBox1, so we need to add another event handler that saves the sending control into the menu:

Private Sub TextBox1_MouseUp(sender As Windows.Forms.Control, e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseUp
    If e.Button = Windows.Forms.MouseButtons.Right Then
        ContextMenu.Tag = sender
    End If
End Sub

And this is the code of the event handler when clicking a menu item:

Private Sub ContextMenu_ItemClicked(sender As System.Object, e As System.Windows.Forms.ToolStripItemClickedEventArgs) Handles ContextMenu.ItemClicked
    ContextMenu.Close()

    If ContextMenu.Tag Is Nothing Then
        Debug.Print("debug info: forgot to set sender? well ... KABOOM!")
        Exit Sub
    End If

    Dim oParent As Windows.Forms.Control
    Try
        oParent = ContextMenu.Tag
    Catch ex As Exception
        Debug.Print("debug info: tag contains data other than sender control. well ... KABOOM!")
        Exit Sub
    End Try

    ' Do fancy stuff here.

    ' Release sender
    ContextMenu.Tag = Nothing
End Sub

Upvotes: 2

Related Questions