The way I thought it should be done (but it’s wrong):
Point mousePoint = Mouse.GetPosition(this); MyWindow win = new MyWindow(); win.Left = mousePoint.X; win.Top = mousePoint.Y; win.ShowDialog();
“Mama Freeda! Dang window won’t go where I put it!”
Okay, maybe I didn’t say “Mama Freeda” nor “Dang” but none the less it
seems like when getting a mouse position in WPF and trying to open a new
window relative to the mouse click is a pain.
Ah Luigi, but I have the solution 🙂
When setting the left and top properties in a wpf window they relate to
the desktop coordinates. The new window could careless that it’s being
popped up from a control underneath it.
The problem is that Mouse.GetPosition(this) returns the position
relative to the “this” which is most likely the control that is trying
to open the new window. Now if the control is the only control in the
window, there is only one screen, the application is running on the
primary screen and the application is maximized then your golden.
But screw that.
Well, how about using Mouse.GetPosition(Window.GetWindow(this))?
That returns the point relative to the window of the control (this).
That should work won’t it? That only eliminates a single concern of
ours, if the control is the only control in the window. There is still
that the application must be only one screen, the application is running
on the primary screen and the application must be maximized.
Brian, cut the Brother Stuart and just give us the simple answer!
Um, who’s Brother Stuart?
And why am I talking to myself like this?
The great thing about wpf controls is that they have the ability given a
point to convert that point to screen (i.e. desktop) coordinates.
So here is easy answer (The way it should be done):
Point mousePoint = this.PointToScreen(Mouse.GetPosition(this)); MyWindow win = new MyWindow(); win.Left = mousePoint.X; win.Top = mousePoint.Y; win.ShowDialog();
Basically get the mouse position relative to this control and then
convert it out to the desktop coordinates so I can then use it when
setting the left and top properties of a new window. This is great for
pop-up windows that need to be close to a mouse click. The great thing
about this is that since the mouse click position is now relative to the
desktop this works on multi-screen monitors regardless of which monitor
you have the application running on.
Later ‘yall,
Brian
ref:
Visual.PointToScreen
http://msdn.microsoft.com/en-us/library/system.windows.media.visual.pointtoscreen.aspx
Mouse.GetPosition
http://msdn.microsoft.com/en-us/library/system.windows.input.mouse.getposition.aspx
Window.Top
http://msdn.microsoft.com/en-us/library/system.windows.window.top.aspx
Help me figure out why you’re here 🙂 Of all my posts this is by far the most popular. I regularly get ~150 unique hits a month to this post alone. Did this answer some problem you were having? Was there some obscure issue with mouse position this helped answer? Please leave a comment, no registration required. Maybe I need more posts like this one.
Thanks,
Brian
I’ll bite.
My WPF application allows the user to zoom and pan a larger control they are working with, and because it deals with image editing, mouse coordinates are very important. Anyhow, whenever I maximize the Window, the control starts reporting incorrect mouse coordinates until I change the zoom level. Once the zoom level changes, the coordinates are accurate again.
Note that I do not perform any fancy math to adjust mouse position based on zoom or pan, because WPF handles all of that for me via ScaleTransform and ScrollViewer. I get the position relative to the scaled object, and 99% of the time, this is perfect.
But not when I maximize the screen. Not until I change the zoom.
Really bizarre. I may have to nudge the ScaleTransform whenever the user maximizes just to prevent this. It feels like a dirty hack, but I am not sure I have any good alternatives.
And just like that, I figured it out.
It works when not maximized because the control is not stretched. Indeed, it is scrollable. When I maximize the window, there is enough room to stretch the control, and while ScaleTransform ensure I get friendly coordinates back, WPF stretching will not. Zooming fixed it because it made the control larger, thus eliminating the need/ability for WPF to stretch the control to fit.
Yeesh!
Yes, I’m searching for how to control the mouse position in WPF at present and yours was the 5th hit on Google
Yes this seems like pretty basic material but most books focus on finding the mouse relative to a Window; not a screen. Hence people have to Google for an answer. I needed the info because I’m trying to move a transparent window up and down on my screen but I don’t want any horizontal movement in the process (hence I can’t use the much simpler this.DragMove()). You might want to blog about this.CaptureMouse() as it relates to that manual window dragging problem!
No the post ain’t good, it’s popular only because getting mouse position in WPF is a pain and it throws exceptions when the visual tree can’t be resolved.
For example I need position of the mouse relative to a control during drag and drop, but all I read is it can’t be done.
Nice one, I think I was trying to use the same original solution as you. There should be a law about incorrect postings on the internet.
Trying to fake a “pull down from maximized” functionality on a skinned WPF window with a hidden title bar and was having problems with multiple monitors and needed a way to track from a UC relative position to a screen relative position. Thanks!
I was searching for a solution to this in wpf:
Drag on a button, opens a window , the mouse should grab the window with the left button still pressed (by the title bar to activate AvalonDock), and then just DragMove() to reposition/docking wherever you want.
Having problems with all the steps so far… Couldn’t correlate the position of the opened window with the mouse position. I had to call click event to activate the current window for avalon etc…
Trying to simply drag a button to a new position. Works first time, then when I click on the button to drag it again it jumps back to its original position. I understand why this is but have not found the solution. I guess I need to tell its parent (the canvas) what the buttons new position is during the mouseup event. Sounds easy but proving difficult!!!!
@nev308, Yeah, you probably need to call Canvas.SetLeft and Canvas.SetTop
Thanks for the article, very helpful.
My code wound up like this:
Point dlgPoint = new Point();
dlgPoint = mySource.myCanvas.PointToScreen(Mouse.GetPosition(mySource.myCanvas));
dlg.Left = dlgPoint.X – (dlg.Width / 2);
dlg.Top = dlgPoint.Y – (dlg.Height / 2);
Tried MANY other approaches, no success under C# with XAML
it is now 2014 and this post still #2 in Google results when searching for ‘wpf translate mouse position to desktop’ 🙂
@Amer,
Yeah, six years later and it’s still one of my top posts. It reads a bit crazy when I go back and re-read it but hopefully I’ve helped a few people.
Brian
I need to find mouse position on DoumentViewer.DocumentPage.. Please help me out… wpf GURUs
@Amol,
What have you tried? The code in this post will get you the mouse position relative to the desktop. Is that of any help? What do you need the position to be relative to?
Brian