在上下文菜单中单击移动时,将鼠标位置设置为无边框 window 中的标题中心

Set mouse position to center of title in borderless window when clicking move in context menu

我正在寻找以下问题的解决方案:为了美观,我使用了无边框 window,因此我为此 window 创建了一个标题区域(它是 Grid).

  <Grid x:Name="rootGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="{DynamicResource BackgroundColor}" >
    <Grid.ContextMenu>
        <ContextMenu>
            <MenuItem x:Name="cmiVerschieben" Header="Verschieben" Click="cmiVerschieben_Click"/>
        </ContextMenu>
    </Grid.ContextMenu>
    <!-- ... -->
</Grid>

现在我像大多数应用程序一样在标题栏中添加了一个上下文菜单 (关闭、最大化、最小化、移动...)。

简单的命令不是问题,但是对于“移动”条目,我必须将鼠标光标从当前位置移动到标题网格的中心。

我在 cmiVerschieben_Click 中用 rootGrid.Focus();rootGrid.CaptureMouse(); 尝试过,但两者都没有将我的光标设置到 rootGrid

我为什么要这样做?在许多其他应用程序中,当我单击“移动”上下文菜单项时,鼠标会移动到标题的中心 window。

我在这里从我的代码中删除了不必要的事件处理程序。

首先,您需要一些互操作代码来获取和设置当前鼠标在屏幕上的位置。看看这些相关问题作为参考:Get mouse position. Set mouse position.

[DllImport("User32.dll")]
private static extern bool SetCursorPos(int x, int y);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetCursorPos(ref Win32Point pt);

[StructLayout(LayoutKind.Sequential)]
internal struct Win32Point
{
   public int X;
   public int Y;
}

private static Point GetMousePosition()
{
   Win32Point w32Mouse = new Win32Point();
   GetCursorPos(ref w32Mouse);

   return new Point(w32Mouse.X, w32Mouse.Y);
}

然后您可以计算出与您的 rootGrid 的位置差异并设置新的鼠标位置,以及不同的鼠标光标图标。

private void CmiVerschieben_OnClick(object sender, RoutedEventArgs e)
{
   var positionOnRootGrid = Mouse.GetPosition(rootGrid);
   var xDifference = (int)(positionOnRootGrid.X - rootGrid.ActualWidth / 2);
   var yDifference = (int)(positionOnRootGrid.Y - rootGrid.ActualHeight / 2);
   var absoluteMousePosition = GetMousePosition();

   var absoluteXPosition = absoluteMousePosition.X - xDifference;
   var absoluteYPosition = absoluteMousePosition.Y - yDifference;

   // Set the position in the center of the root grid
   SetCursorPos(absoluteXPosition, absoluteYPosition);

   // Set the mouse cursor icon for roorGrid
   rootGrid.Cursor = Cursors.SizeAll;
}

当然,您必须处理拖动 window 并稍后重置光标。