Single click on notifyicon menu item produces two events

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • starrysky
    New Member
    • Dec 2009
    • 10

    Single click on notifyicon menu item produces two events

    I have a program which puts an icon in the notification area and has a menu associated with it available by right clicking on the icon. I want the menu items to be selected by single left clicks but I also want the user to be able to single left click on the icon itself to do some other functionality.

    Here's the problem - the single click on the menu first fires the notifyicon1_cli ck() routine and then the menuitem1_click () routine. How do I know in the notifyicon1_cli ck() whether it has been called from a menu click or a click on the icon itself?

    the following piece of test code duplicates the problem

    Code:
    Imports System
    Imports System.Drawing
    Imports System.Windows.Forms
    
    Public NotInheritable Class Form1
        Inherits System.Windows.Forms.Form
    
        Private contextMenu1 As System.Windows.Forms.ContextMenu
        Friend WithEvents menuItem1 As System.Windows.Forms.MenuItem
        Friend WithEvents notifyIcon1 As System.Windows.Forms.NotifyIcon
        Private components1 As System.ComponentModel.IContainer
    
        <System.STAThread()> _
        Public Shared Sub Main()
            System.Windows.Forms.Application.Run(New Form1)
        End Sub 'Main
    
        Public Sub New()
    
            Me.components = New System.ComponentModel.Container
            Me.contextMenu1 = New System.Windows.Forms.ContextMenu
            Me.menuItem1 = New System.Windows.Forms.MenuItem
    
            ' Initialize contextMenu1
            Me.contextMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() _
                                {Me.menuItem1})
    
            ' Initialize menuItem1
            Me.menuItem1.Index = 0
            Me.menuItem1.Text = "E&xit"
    
            ' Set up how the form should be displayed.
            Me.ClientSize = New System.Drawing.Size(292, 266)
            Me.Text = "Notify Icon Example"
    
            ' Create the NotifyIcon.
            Me.notifyIcon1 = New System.Windows.Forms.NotifyIcon(Me.components)
    
            ' The Icon property sets the icon that will appear
            ' in the systray for this application.
            notifyIcon1.Icon = New Icon("myicon.ico")
    
            ' The ContextMenu property sets the menu that will
            ' appear when the systray icon is right clicked.
            notifyIcon1.ContextMenu = Me.contextMenu1
    
            ' The Text property sets the text that will be displayed,
            ' in a tooltip, when the mouse hovers over the systray icon.
            notifyIcon1.Text = "Form1 (NotifyIcon example)"
            notifyIcon1.Visible = True
    
            notifyIcon1.BalloonTipIcon = ToolTipIcon.Info
            notifyIcon1.BalloonTipTitle = " this is the balloon title "
            notifyIcon1.BalloonTipText = " this is the ballon tip text "
            notifyIcon1.ShowBalloonTip(30)
    
        End Sub 'New
    
    
    
        Private Sub notifyIcon1_Click(ByVal Sender As Object, ByVal e As EventArgs) Handles notifyIcon1.Click
    
            ' Show the form when the user double clicks on the notify icon.
    
            ' Set the WindowState to normal if the form is minimized.
            If (Me.WindowState = FormWindowState.Minimized) Then _
                Me.WindowState = FormWindowState.Normal
    
            ' Activate the form.
            Me.Activate()
        End Sub
    
        Private Sub menuItem1_Click(ByVal Sender As Object, ByVal e As EventArgs) Handles menuItem1.Click
    
            ' Close the form, which closes the application.
            Me.Close()
        End Sub
    
     End Class 'Form1
    Last edited by tlhintoq; Dec 17 '09, 04:07 PM. Reason: [CODE] ...Your code goes between code tags [/CODE]
  • tlhintoq
    Recognized Expert Specialist
    • Mar 2008
    • 3532

    #2
    TIP: When you are writing your question, there is a button on the tool bar that wraps the [code] tags around your copy/pasted code. It helps a bunch. Its the button with a '#' on it. More on tags. They're cool. Check'em out.

    Comment

    • tlhintoq
      Recognized Expert Specialist
      • Mar 2008
      • 3532

      #3
      How do I know in the notifyicon1_cli ck() whether it has been called from a menu click or a click on the icon itself?
      Would it be simpler to just not use the menuitem1_click for anything else?

      Comment

      • starrysky
        New Member
        • Dec 2009
        • 10

        #4
        Thanks for responding.

        The code snippet I submitted was just an example that will illustrate the problem, it is not the application I am working on. That application needs an icon with a menu containing several menu items and to do something different when there is a single click on the icon itself. I want it to behave like most other icons in the windows notification area
        eg the volume control icon
        • single click on icon - produces the slider
        • right click on icon - produces menu
        • single click on menu - selects option (eg open volume mixer)


        Most vb.net source examples I have seen on the internet get round the problem by using a doubleClick event to identify the icon click. But I dont want the user having to do something different for my icon when all other icons in the notification area respond to single clicks

        Any ideas?

        Comment

        • tlhintoq
          Recognized Expert Specialist
          • Mar 2008
          • 3532

          #5
          Here's the problem - the single click on the menu first fires the notifyicon1_cli ck() routine and then the menuitem1_click () routine.
          You've already described the problem. You do realize that THIS is the problem, right? Clicking on the menu should NOT also fire the first menu item. That would be like Clicking on "File" also automatically fires "Open..."
          The code snippet I submitted was just an example that will illustrate the problem
          I suspect that the actual application has a logic/flow problem that causes the method for "MenuItem1" to be executed.

          Comment

          • starrysky
            New Member
            • Dec 2009
            • 10

            #6
            I think we are at cross-purposes so to be clear ( humour me ) :

            It is my understanding that a single click on the menu item ( menuitem1 in the above test code ) should only produce a single click event for the menuitem and not a click event for anything else. eg in the test code supplied above clicking the "Exit" menu item should fire menuitem1_click () and nothing else.

            What is happening ( and I dont want it to happen, it is the problem ) is that notifyicon1_cli ck() event fires as well

            If you agree with all that :

            The solutions I see are either:
            1/ stop noitfyIcon1_cli ck() firing
            2/ or determine from inside noitfyIcon1_cli ck() if the routine was called by clicking the "Exit" menu item or clicking the icon itself. If it was by clicking the menu item then I wish to immediately exit the noitfyIcon1_cli ck() routine without doing anything.

            If there is logic problem then the logic problem exists in the supplied test code above also, as it exhibits the same problem. Please examine it and let me know.

            Comment

            • tlhintoq
              Recognized Expert Specialist
              • Mar 2008
              • 3532

              #7
              Maybe this helps...
              .Click will fire if you ...
              • Click it once with the left mouse button
              • Click it once with the right mouse button... also opening the context menu
              • Double click... Cause the click to fire twice and the .DoubleClick to fire once


              If you want to have a behavior for .Click that ignores if the context menu was opened then I suggest your NotifyIcon.Clic k handler should check if the right mouse button is down. (or if the ContextMenuStri p is opening)

              Personally I think it is far easier to ignore the .Click event because it gets fired too often. Either react to menu choices or .DoubleClick

              Use the .Click to do something like... dynamically remove menu options based on criteria before the context menu is drawn.

              Comment

              • starrysky
                New Member
                • Dec 2009
                • 10

                #8
                My investigations have not resulted in a way of detecting if menu is up when the
                notifyicon_clic k() fires ( not sure it would be up at that point anyway ie. following a menuitem click) nor a way of determining if the mouse is over the icon at the time of the click ( and this may not always be reliable as it could be over it even after a menuitem click anyway ).

                However I have used a timer to wait to see if a menuitem click follows the notifyicon click, if not then I take it as a pukka click on the icon itself. This relies on the notificationico n click firing before a menuitem click. But it seems to work well. See snippet below - I will use this unless someone comes up with the 'proper way' to get this single click functionality.


                Code:
                   Private Sub notifyIcon1_Click(ByVal Sender As Object, ByVal e As EventArgs) Handles notifyIcon1.Click
                
                        Timer_wait_for_menu_click.Interval = 300
                        Timer_wait_for_menu_click.Start()
                
                    End Sub
                
                    ''' <summary>
                    ''' If this timer event occurs then we take it that the notifyicon1_click event  was for a single click on the icon
                    ''' and not a menuitem click 
                    ''' </summary>
                    ''' <param name="sender"></param>
                    ''' <param name="e"></param>
                    ''' <remarks></remarks>
                    Private Sub Timer_wait_for_menu_click_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer_wait_for_menu_click.Tick
                
                        Timer_wait_for_menu_click.Stop()  
                
                        do_notifyIcon1_Click()
                
                    End Sub
                
                    ''' <summary>
                    ''' We have determined that the  icon has been clicked
                     ''' </summary>
                    ''' <remarks></remarks>
                    Private Sub do_notifyIcon1_Click()
                
                        ' do the click icon functionality here
                
                   End sub
                
                   Private Sub menuItem1_Click(ByVal Sender As Object, ByVal e As EventArgs) Handles menuItem1.Click
                
                        Timer_wait_for_menu_click.Stop()  ' got a menu click - so prevent responding to icon click event
                
                        ' Close the form, which closes the application.
                        Me.Close()
                    End Sub

                Comment

                • starrysky
                  New Member
                  • Dec 2009
                  • 10

                  #9
                  All problems solved when I discovered the ContextMenuStri p and used that instead of the ContextMenu control

                  Case closed!

                  Comment

                  Working...