By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,106 Members | 2,335 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,106 IT Pros & Developers. It's quick & easy.

Single click on notifyicon menu item produces two events

P: 10
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_click() routine and then the menuitem1_click() routine. How do I know in the notifyicon1_click() 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

Expand|Select|Wrap|Line Numbers
  1. Imports System
  2. Imports System.Drawing
  3. Imports System.Windows.Forms
  4.  
  5. Public NotInheritable Class Form1
  6.     Inherits System.Windows.Forms.Form
  7.  
  8.     Private contextMenu1 As System.Windows.Forms.ContextMenu
  9.     Friend WithEvents menuItem1 As System.Windows.Forms.MenuItem
  10.     Friend WithEvents notifyIcon1 As System.Windows.Forms.NotifyIcon
  11.     Private components1 As System.ComponentModel.IContainer
  12.  
  13.     <System.STAThread()> _
  14.     Public Shared Sub Main()
  15.         System.Windows.Forms.Application.Run(New Form1)
  16.     End Sub 'Main
  17.  
  18.     Public Sub New()
  19.  
  20.         Me.components = New System.ComponentModel.Container
  21.         Me.contextMenu1 = New System.Windows.Forms.ContextMenu
  22.         Me.menuItem1 = New System.Windows.Forms.MenuItem
  23.  
  24.         ' Initialize contextMenu1
  25.         Me.contextMenu1.MenuItems.AddRange(New System.Windows.Forms.MenuItem() _
  26.                             {Me.menuItem1})
  27.  
  28.         ' Initialize menuItem1
  29.         Me.menuItem1.Index = 0
  30.         Me.menuItem1.Text = "E&xit"
  31.  
  32.         ' Set up how the form should be displayed.
  33.         Me.ClientSize = New System.Drawing.Size(292, 266)
  34.         Me.Text = "Notify Icon Example"
  35.  
  36.         ' Create the NotifyIcon.
  37.         Me.notifyIcon1 = New System.Windows.Forms.NotifyIcon(Me.components)
  38.  
  39.         ' The Icon property sets the icon that will appear
  40.         ' in the systray for this application.
  41.         notifyIcon1.Icon = New Icon("myicon.ico")
  42.  
  43.         ' The ContextMenu property sets the menu that will
  44.         ' appear when the systray icon is right clicked.
  45.         notifyIcon1.ContextMenu = Me.contextMenu1
  46.  
  47.         ' The Text property sets the text that will be displayed,
  48.         ' in a tooltip, when the mouse hovers over the systray icon.
  49.         notifyIcon1.Text = "Form1 (NotifyIcon example)"
  50.         notifyIcon1.Visible = True
  51.  
  52.         notifyIcon1.BalloonTipIcon = ToolTipIcon.Info
  53.         notifyIcon1.BalloonTipTitle = " this is the balloon title "
  54.         notifyIcon1.BalloonTipText = " this is the ballon tip text "
  55.         notifyIcon1.ShowBalloonTip(30)
  56.  
  57.     End Sub 'New
  58.  
  59.  
  60.  
  61.     Private Sub notifyIcon1_Click(ByVal Sender As Object, ByVal e As EventArgs) Handles notifyIcon1.Click
  62.  
  63.         ' Show the form when the user double clicks on the notify icon.
  64.  
  65.         ' Set the WindowState to normal if the form is minimized.
  66.         If (Me.WindowState = FormWindowState.Minimized) Then _
  67.             Me.WindowState = FormWindowState.Normal
  68.  
  69.         ' Activate the form.
  70.         Me.Activate()
  71.     End Sub
  72.  
  73.     Private Sub menuItem1_Click(ByVal Sender As Object, ByVal e As EventArgs) Handles menuItem1.Click
  74.  
  75.         ' Close the form, which closes the application.
  76.         Me.Close()
  77.     End Sub
  78.  
  79.  End Class 'Form1
Dec 17 '09 #1
Share this Question
Share on Google+
8 Replies


tlhintoq
Expert 2.5K+
P: 3,525
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.
Dec 17 '09 #2

tlhintoq
Expert 2.5K+
P: 3,525
How do I know in the notifyicon1_click() 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?
Dec 17 '09 #3

P: 10
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?
Dec 18 '09 #4

tlhintoq
Expert 2.5K+
P: 3,525
Here's the problem - the single click on the menu first fires the notifyicon1_click() 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.
Dec 18 '09 #5

P: 10
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_click() event fires as well

If you agree with all that :

The solutions I see are either:
1/ stop noitfyIcon1_click() firing
2/ or determine from inside noitfyIcon1_click() 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_click() 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.
Dec 21 '09 #6

tlhintoq
Expert 2.5K+
P: 3,525
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.Click handler should check if the right mouse button is down. (or if the ContextMenuStrip 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.
Dec 21 '09 #7

P: 10
My investigations have not resulted in a way of detecting if menu is up when the
notifyicon_click() 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 notificationicon 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.


Expand|Select|Wrap|Line Numbers
  1.    Private Sub notifyIcon1_Click(ByVal Sender As Object, ByVal e As EventArgs) Handles notifyIcon1.Click
  2.  
  3.         Timer_wait_for_menu_click.Interval = 300
  4.         Timer_wait_for_menu_click.Start()
  5.  
  6.     End Sub
  7.  
  8.     ''' <summary>
  9.     ''' If this timer event occurs then we take it that the notifyicon1_click event  was for a single click on the icon
  10.     ''' and not a menuitem click 
  11.     ''' </summary>
  12.     ''' <param name="sender"></param>
  13.     ''' <param name="e"></param>
  14.     ''' <remarks></remarks>
  15.     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
  16.  
  17.         Timer_wait_for_menu_click.Stop()  
  18.  
  19.         do_notifyIcon1_Click()
  20.  
  21.     End Sub
  22.  
  23.     ''' <summary>
  24.     ''' We have determined that the  icon has been clicked
  25.      ''' </summary>
  26.     ''' <remarks></remarks>
  27.     Private Sub do_notifyIcon1_Click()
  28.  
  29.         ' do the click icon functionality here
  30.  
  31.    End sub
  32.  
  33.    Private Sub menuItem1_Click(ByVal Sender As Object, ByVal e As EventArgs) Handles menuItem1.Click
  34.  
  35.         Timer_wait_for_menu_click.Stop()  ' got a menu click - so prevent responding to icon click event
  36.  
  37.         ' Close the form, which closes the application.
  38.         Me.Close()
  39.     End Sub
Dec 23 '09 #8

P: 10
All problems solved when I discovered the ContextMenuStrip and used that instead of the ContextMenu control

Case closed!
Feb 3 '10 #9

Post your reply

Sign in to post your reply or Sign up for a free account.