2

I have the following event handler for a NotifyIcon within a WPF application using Forms integration:

void MyNotifyIcon_MouseDown(Object sender, System.Windows.Forms.MouseEventArgs e)
{
    ShowSettingsWindow();
}

However, e.Location = {X=0,Y=0} always. Is there a way to make this work?

Update

Oddly enough, people have voted to close this question and have downvoted it. However, its clearly not working and simple enough to create a new NotifyIcon inside of a WPF application's App.xaml.cs file and try it out for yourselves.

Update

As Hans pointed out, this is by design. It still doesn't answer the question of what possible workarounds are. Furthermore, this is a bad design, because:

  1. This event occurs on a MouseDown, which means it should have some context of the mouse position when it was clicked in order for it to have occurred. The WmMouseDown handler for NotifyIcon does have the ref Message m property which other controls use to establish the correct position, however it seems to disregard this property and not use it in the event handler. I'd call this a major bug.

  2. Since its post-mortem, getting the Cursor.Position inside of MouseDown will not give you the exact last location in which the MouseDown was raised after the tray icon is clicked. There is a small delay between you clicking it, and it raising the event in which you can further move the mouse. You can test this out yourself with an application that gets the mouse coordinates by quickly moving the mouse after clicking the tray and getting its location within the MouseDown handler. A workaround (which answers my question) would be to save the last location on every MouseMove using Cursor.Position instead and using this last location on MouseDown as the location that clicked the icon. All of which spells out a clear need for the mouse location of when the event actually occurred.

Apparently, I am the only one who cares about these inconsistencies in .NET while a lot of people seem to tolerate them or not understand their implications properly.

Alexandru
  • 12,264
  • 17
  • 113
  • 208
  • 2
    This is entirely [by design](http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/NotifyIcon.cs,7942e6855936067a). – Hans Passant Apr 30 '15 at 02:15
  • @HansPassant Bad design. – Alexandru Apr 30 '15 at 02:33
  • Of course it is not, the mouse position is meaningless when the icon can randomly change position at any moment. – Hans Passant Apr 30 '15 at 02:39
  • @HansPassant What?! It's on a MouseDown event, which should have some context of the mouse position when it was clicked. For it to have occurred, it must have been clicked at some point obviously. – Alexandru Apr 30 '15 at 02:47
  • @HansPassant The `WmMouseDown` handler for `NotifyIcon` does have the `ref Message m` property which other controls use (http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/TreeView.cs,48ef6b4e087de4f8) to establish the correct position, however it seems to disregard this property and not use it in the event handler. Bad design. I'd even call it a major bug. – Alexandru Apr 30 '15 at 03:37
  • @Alexandru `Winform Controls` return the location relative to their own top left corner, but it doesn't make sense to need to know where on the icon's image the mouse was clicked, only that it was clicked. Other controls like a `Button` may have a drop down splitter, so in that case the mouse location might be needed. You can always use `Cursor.Position` if you need the absolute mouse location. – Loathing Apr 30 '15 at 04:24
  • @Loathing Since its post-mortem, `Cursor.Position` will not give you the exact last location in which the `MouseDown` was raised after the tray icon is clicked. You can test this out yourself with an application that gets the mouse coordinates by quickly moving the mouse after clicking the tray and getting its location within the `MouseDown` handler. A workaround would be to save the last location on every `MouseMove` using `Cursor.Position` instead and using this last location on `MouseDown`. All of this spells out a clear need for the mouse location of when the event actually occurred. – Alexandru Apr 30 '15 at 04:28
  • @Alexandru By the way, it's not specific to `WPF`. The location is `{0, 0}` in `Winforms` also, so maybe your question should be edited. Just out of curiosity, what is the actual need to know where the click happened on the icon? – Loathing Apr 30 '15 at 04:38
  • @Loathing Although it's not relevant, I have an application-specific need, but I pray that you can brainstorm at least a handful of specific needs for accurate icon mouse click coordinates, ranging from animations and trajectories to coordinates for window presentation and location-based tray icon bitmap changes. – Alexandru Apr 30 '15 at 04:48

2 Answers2

0

Its not ideal because the framework is designed to not send proper mouse event arguments as Hans pointed out, but one workaround is to save the last location on every MouseMove using Cursor.Position and using this last location on MouseDown as the location that contextually clicked the icon.

Alexandru
  • 12,264
  • 17
  • 113
  • 208
0

Have you considered setting a global mouse hook? It would bypass the typical WPF event model, and you would have to manually determine coordinates. This may involve additional API calls.

Details can be found in this post Global mouse event handler

Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76