10
votes

I have found that this works PART of the time by inheriting the Windows Forms mouse point and subtracting out the height and width of my window to set the left and top (since my window's size is fixed):

MyWindowObjectThatInheritsWindow window = new MyWindowObjectThatInheritsWindow();
System.Windows.Point mouseLocation = GetMousePositionWindowsForms();
window.Left = mouseLocation.X - 300;
window.Top = mouseLocation.Y - 240;
window.Show();

Edit: Here is the code for getting the mouse position...

public System.Windows.Point GetMousePositionWindowsForms()
{
    System.Drawing.Point point = System.Windows.Forms.Control.MousePosition;
    return new System.Windows.Point(point.X, point.Y);
}

Note that this works by making the bottom right edge of the window touch the top left of your mouse cursor. But this breaks for different screen resolutions, or maybe multiple monitors with different resolutiosn? I haven't fully narrowed it down yet, but I just tried this same code on another PC, and it seems to spawn the window not to the top left of the mouse cursor, but to the bottom left of it, and a good distance past it...

I should probably add that my window sizes to content, width and height, so I can't just use the ActualWidth and ActualHeight properties since they're not available. Perhaps the issue is in getting that sizing right? Is there any way to do that? I know for sure the 300 and 240 is correct according to my main PC with two monitors running 1920x1080 resolutions, as I have calculated the widths and heights of all the objects in my window which I have explicitly sized. Edit: Just tried explicitly setting the height and width to 240/300, to ensure that the window is no longer sized to content, and I still have this issue when subtracting out the actual height and width!

Any ideas?

3
It is not clear what you want exactly, not even what your code does (what is exactly returning GetMousePositionWindowsForms?). Can you please be a bit clearer?varocarbas
No problem. In a nutshell: I want to set a WPF window's bottom right edge to the top left of the mouse cursor. I have added in the function you requested.Alexandru
The problem is more or less clear; but your code not too much: it seems to be a mixture of C# winforms and WPF. In any case, I guess that you can continue this discussion with the answerer you got.varocarbas
@varocarbas Yes, it uses WinForms to get the mouse point on screen, but unfortunately that answer I got does not seem to work in my case since my MainWindow is hidden since my application consists of just a system tray icon.Alexandru
I am not familiar with this kind of mixtures (usually, you get directly anything you want in WPF or create a winforms application). Might not this be provoking the problems (wrongly coordinating two different frameworks)? In any case, just explain the exact conditions to Sheridan such that he can come up with a solution working for you.varocarbas

3 Answers

16
votes

In the end, this did the trick:

        protected override void OnContentRendered(EventArgs e)
        {
            base.OnContentRendered(e);
            MoveBottomRightEdgeOfWindowToMousePosition();
        }

        private void MoveBottomRightEdgeOfWindowToMousePosition()
        {
            var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
            var mouse = transform.Transform(GetMousePosition());
            Left = mouse.X - ActualWidth;
            Top = mouse.Y - ActualHeight;
        }

        public System.Windows.Point GetMousePosition()
        {
            System.Drawing.Point point = System.Windows.Forms.Control.MousePosition;
            return new System.Windows.Point(point.X, point.Y);
        }
4
votes

Can you not use something like this?:

Point mousePositionInApp = Mouse.GetPosition(Application.Current.MainWindow);
Point mousePositionInScreenCoordinates = 
    Application.Current.MainWindow.PointToScreen(mousePositionInApp);

I haven't been able to test it, but I think it should work.


UPDATE >>>

You don't have to use the Application.Current.MainWindow as the parameter in these methods... it should still work if you have access to a Button or another UIElement in a handler:

Point mousePositionInApp = Mouse.GetPosition(openButton);
Point mousePositionInScreenCoordinates = openButton.PointToScreen(mousePositionInApp);

Again, I haven't been able to test this, but if that fails as well, then you can find one more method in the How do I get the current mouse screen coordinates in WPF? post.

2
votes

You can also do this by slightly modifying your initial example and positioning the window before showing it.

MyWindowObjectThatInheritsWindow window = new MyWindowObjectThatInheritsWindow();

var helper = new WindowInteropHelper(window);
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
var transformFromDevice = hwndSource.CompositionTarget.TransformFromDevice;

System.Windows.Point wpfMouseLocation = transformFromDevice.Transform(GetMousePositionWindowsForms());
window.Left = wpfMouseLocation.X - 300;
window.Top = wpfMouseLocation.Y - 240;
window.Show();