Is there a way to get mouse position without attaching a event handler?
I'm trying to get a box to appear where the mouse is.
Thanks
Sp
Wouldn't you rather want it on a mouse-up or mouse-down event? Here are a few drag-and-drop tutorials that might help with ideas for capturing mouse positions:
http://msdn.microsoft.com/en-us/library/cc189066%28vs.95%29.aspx
(SL 1, but still good) http://blogs.msdn.com/b/nickkramer/archive/2007/06/27/drag-drop-with-feedback.aspx
Unfortunately, I think you'll have no other way than using the MouseMove event. You can attach it to the Application.Current.RootVisual (or any other layout root) though, so you should be able to implement your scenario.
Related
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:
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.
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.
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.
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
I have a small video app that i would like to give vlc-like functionality. By that, I mean having a certain element disappear and appear on mouse move or mouse not moving. I have a rough concept of how to do this but I have no ideea how i coul detect if the mouse is moving or not. I thought about using the GetPosition function but that will just give me the mouse's position and won't let me know if the cursor is moving or not. I would like to use a timer to count down 2-3 seconds after the mouse has stopped moving and then either fade out the control or just make it collapse without further ado. I can't check the value of the position variable every milisecond. Is there some other way to do this ?
You can use a hook functionality so you will be notified when a mouse move, I use to use this free opensource library.
How to use it:
using Gma.UserActivityMonitor.GlobalEventProvider;
GlobalEventProvider _globalEventProvider1
= new Gma.UserActivityMonitor.GlobalEventProvider();
this.globalEventProvider1.MouseMove += HookMouseMove;//to listen to mouse move
Capture the mouse. Release the capture if the user actually clicks anywhere else. Then you can use the standard WPF mouse move event.
myElement.MouseMove += (my MouseMove handler)
Mouse.Capture(myElement);
I have some straight WPF 3.5 controls handling left mouse clicks that I need to use within a Surface app (SDK 1.0). The problem I am facing is that do not work by default. I am thinking of wrapping each control in a SurfaceContentControl and translating ContactTouchDown or ContactTapGesture events to corresponding MouseDown events.
The problem boils down to - how to "inject" or simulate arbitrary routed mouse events? I have tried InputManager.Current.ProcessInput() but didn't get very far. Any help is appreciated.
Try to use AutomationPeer classes. For example ButtonAutomationPeer is for Button. The code below initiates a click.
ButtonAutomationPeer peer = new ButtonAutomationPeer(button);
IInvokeProvider provider = (IInvokeProvider)peer.GetPattern(PatternInterface.Invoke);
provider.Invoke();
evpo's idea is an interesting one (though if you're working with custom controls, they rarely come with AutomationPeer classes).
You can't simply 'inject' mouse input by sending WM_MOUSE* events to your app... WPF would indeed process the message but when it goes to figure out the position of mouse for that event, it will query the actual mouse API instead of trying what you stick in the WM.
So really all you can do is tell windows to move the actual mouse cursor and act as though the button is being clicked/released. Some code you can use for that is in http://www.codeproject.com/KB/system/globalmousekeyboardlib.aspx
That said, while you can technically do this, it sucks... you've got an expensive multitouch device but are 1) showing a mouse cursor on it 2) limiting arbitrary parts of it to being used 'single touch' (and only one of those arbitrary parts at a time and 3) coming up with an arbitrary method of determining which finger you will treat as the mouse-controlling one
Hallo,
I am trying to keep track of the mouse position and also its delta position. Is there any nicer way of doing this then implementing all the mouse events for all my forms in my window?
The problem with using the MouseMove event is that as soon as the mouse moves outside of the form it stops working properly. Implementing the mouseEnter, mouseLeave improves it somewhat, but it does still not feel perfect. Any ideas?
Regards,
You have to handle lower level windows events.
Check out this example: http://www.codeproject.com/KB/cs/globalhook.aspx
I have a canvas object and I am sprinkling fantastic controls all over it. I'm using a ScaleTransform object to scale the canvas so I can zoom in/out.
I have wired up the controls so that I can drag them around, and the drag and drop works well by using MouseLeftButtonDown, MouseLeftButtonUp, and MouseMove. Now, I want to work on enabling an event when I click only on the Canvas. When I read the docs for the canvas object, I see that the MouseLeftButtonDown event only fires when it's over a UIElement.
Occurs when the left mouse button is
pressed (or when the tip of the stylus
touches the tablet PC) while the mouse
pointer is over a UIElement.
(Inherited from UIElement.)
Unfortunately, I want the opposite behavior. I want to know when the mouse is clicked on the Canvas while the mouse pounter isn't over any controls. Since I'm new to Silverlight, I could be doing this the wrong way. Is there something I have overlooked? Am I going about this the wrong way? I'm looking for a little help, and perhaps a lot of direction.
I'm no Silverlight guru, but could you add a transparent UIElement to the Canvas, below all other UIElements, and use it to determine if the user has clicked outside of any of the other drag/drop-able elements.
You want to know when a click happens on the Canvas and isn't over other controls?
The most natural thing is to capture the Canvas's MouseLeftButtonDown. Inside of that event, take a peak to see where the click happened. Then peak at the UIElements under the click. I recommend you keep everything in absolute coordinates to keep things straight. Something like:
void Page_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(null);
var elements = VisualTreeHelper.FindElementsInHostCoordinates(p, App.Current.RootVisual);
foreach (var element in elements)
{
//Figure out if you're over a particular UI element
}
}
I think you may be interpreting the documentation wrong. According to MSDN, Canvas itself is an implementation of a UIElement:
System.Windows.UIElement
System.Windows.FrameworkElement
System.Windows.Controls.Panel
System.Windows.Controls.Canvas
From my experience, and correct me if I'm wrong, MouseLeftButtonDown usually only fires for the top-most UIElement clicked. So if you implement MouseLeftButtonDown for your Canvas, it should only fire when the Canvas is clicked, and NOT when the buttons are clicked. I'd say try it out first.
In WPF, I think this would be easily solved by routed events. However, Silverlight didn't get this feature. You may want to check out VisualTreeHelper.FindElementsInHostCoordinates. This article covers it a little bit.
http://www.andybeaulieu.com/Default.aspx?tabid=67&EntryID=95