vb.netcontextmenucontextmenustriptoolstripmenu

Avoid toolstripmenu closed on item selected


I have a system tray application on vb.net. This app has a menu with several options. There is an option to select the language app. This language option has three submenus: english, french and spanish.

Below is the snipet code of the three submenus:

submnuEnglish = New ToolStripMenuItem(rm.GetString("ContextMenusToolStripMenuItemLangEnglish"))
submnuEnglish.Image = My.Resources.en
submnuEnglish.CheckOnClick = True

submnuSpanish = New ToolStripMenuItem(rm.GetString("ContextMenusToolStripMenuItemLangSpanish"))
submnuSpanish.Image = My.Resources.es
submnuSpanish.CheckOnClick = True

submnuFrench = New ToolStripMenuItem(rm.GetString("ContextMenusToolStripMenuItemLangFrench"))
submnuFrench .Image = My.Resources.fr
submnuFrench .CheckOnClick = True

In rutime, each time I select a language from the language option menu, app main menu is closed automatically after selection so I need to do a right-click on system tray app to access again to the app main menu. I would like to be able to select language without the language submenu/main app menu gets closed on every selection.

How can I do this?

SOLUTION - UPDATED: Below mngLanguage corresponds to a ToolStripMenuItem object which contains the options submnuEnglish, submnuSpanish and submnuFrench of type ToolStripMenuItem.

MainMenu is the app main menu of type ContextMenuStrip.

Private Sub ToolStripMenuItem_Click(ByVal sender As Object, ByVal e As System.EventArgs)

    ' uncheck the old ones
    Dim selectedLanguage As ToolStripMenuItem = CType(sender, ToolStripMenuItem)
    For Each language As ToolStripMenuItem In mnuLanguage.DropDownItems
        If Not Object.Equals(selectedLanguage, language) Then
            language.CheckState = CheckState.Unchecked
        End If
    Next

    ' check the new one
    selectedLanguage.CheckState = CheckState.Checked

    ' Prevents language menu from being hiding
    ' Thanks to Crush Sundae ;) that guide me in the right direction with his comment
    Me.mnuLanguage.DropDown.Show()
End Sub

Private Sub MainMenu_Closing(ByVal sender As Object, _
                             ByVal e As System.Windows.Forms.ToolStripDropDownClosingEventArgs) _
Handles MainMenu.Closing

    ' Avoid main menu for closing on language selection
    If submnuEnglish.Pressed Or _
       submnuSpanish.Pressed Or _
       submnuFrench.Pressed Then

        e.Cancel = True
    End If

End Sub

Below event is necessary to refresh UI on language item clicked. If it is not implemented then when an item is checked (language) the previous one is not unchecked after mouse is moved.

Private Sub mnuLanguage_DropDownItemClicked( _
    ByVal sender As Object, _
    ByVal e As System.Windows.Forms.ToolStripItemClickedEventArgs) _
Handles mnuLanguage.DropDownItemClicked

    ' Refresh language selection on dropdown menu
    If e.ClickedItem.Equals(submnuEnglish) Then
        ' English language selected
        submnuSpanish.Checked = False
        submnuFrench.Checked = False
    ElseIf e.ClickedItem.Equals(submnuSpanish) Then
        ' Spanish language selected
        submnuEnglish.Checked = False
        submnuFrench.Checked = False
    Else
        ' French language selected
        submnuEnglish.Checked = False
        submnuSpanish.Checked = False
    End If

End Sub

With above implentation it works like a charm!

Before implementing above solution I was trying to solve it using:

mnuLanguage.DropDown.AutoClose = True or False depending on the case

but doing so was cause UI behaves abnormally, weird behavior, for example, menus with submenus were not being dropdown automatically on mouse over. From my point of view it is not recommended to use it.


Solution

  • Open it again after you clicked it.

    Since I can't see more from your code, just use this as a reference of what I'm saying.

    Private Sub TestToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TestToolStripMenuItem.Click
         Me.ToolStripDropDownButton1.ShowDropDown()
    EndSub