WPF and MousePosition

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

Comments (13)

  1. 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

  2. Yes, I’m searching for how to control the mouse position in WPF at present and yours was the 5th hit on Google

  3. Greg

    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!

  4. 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.

  5. 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.

  6. Mike

    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.

  7. Warren

    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!

  8. infel

    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…

  9. nev308

    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!!!!

  10. @nev308, Yeah, you probably need to call Canvas.SetLeft and Canvas.SetTop

  11. Bob

    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

  12. Amer

    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

Leave a Reply