在鼠标位置(鼠标左上角)显示 WPF 窗口的最佳方式是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19768952/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 10:00:27  来源:igfitidea点击:

What is the best way to show a WPF window at the mouse location (to the top left of the mouse)?

c#wpfwindowlocationmouse

提问by Alexandru

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):

我发现通过继承 Windows 窗体鼠标点并减去我的窗口的高度和宽度来设置左侧和顶部(因为我的窗口的大小是固定的),这在部分时间有效:

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

请注意,这是通过使窗口的右下角接触鼠标光标的左上角来实现的。但这会因不同的屏幕分辨率或具有不同分辨率的多台显示器而中断?我还没有完全缩小范围,但我只是在另一台 PC 上尝试了相同的代码,它似乎不是在鼠标光标的左上角生成窗口,而是在它的左下角生成窗口,并且距离很远过去了...

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!

我可能应该将我的窗口大小添加到内容、宽度和高度,所以我不能只使用 ActualWidth 和 ActualHeight 属性,因为它们不可用。也许问题在于正确调整尺寸?有没有办法做到这一点?我确信 300 和 240 根据我的主 PC 是正确的,我有两台运行 1920x1080 分辨率的显示器,因为我已经计算了我已明确调整大小的窗口中所有对象的宽度和高度。编辑:刚刚尝试将高度和宽度明确设置为 240/300,以确保窗口不再根据内容调整大小,并且在减去实际高度和宽度时我仍然遇到这个问题!

Any ideas?

有任何想法吗?

回答by Alexandru

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);
        }

回答by Sheridan

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.MainWindowas the parameter in these methods... it shouldstill work if you have access to a Buttonor another UIElementin a handler:

您不必Application.Current.MainWindow在这些方法中使用 the作为参数...如果您可以访问处理程序中的a或另一个,它应该仍然有效:ButtonUIElement

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.

同样,我无法对此进行测试,但如果它也失败了,那么您可以在如何在 WPF 中获取当前鼠标屏幕坐标?邮政。

回答by Jan Gassen

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();