首页 > 解决方案 > 如何在以编程方式移动鼠标后防止触发 MouseMove 事件

问题描述

我正在尝试使用 WPF 3D 制作第一人称游戏模板。每当鼠标移动时,相机也会移动。我想制作一个鼠标离开窗口时返回中心的情况。我了解到您可以使用System.Windows.Forms.Cursor.Position来更改光标的位置。正如预期的那样,当光标离开窗口时,它会回到中心。但是,相机也会切换回之前的位置。当光标位置重置时,我不希望相机移动。这是我的代码:

MainCamera是主摄像头

MainViewport是托管的视口。

Crosshair是一个表示十字准线的椭圆。

CrosshairX是十字准线的 X 位置。

CrosshairY是十字准线的 Y 位置。

MouseX是鼠标的 X 位置。

MouseY是鼠标的 Y 位置。

public void Rotate(double d)
{
    // Rotate to the side a certain number of degrees
    double u = 0.05;
    double angleD = u * d;

    var m = new Matrix3D();
    m.Rotate(new Quaternion(MainCamera.UpDirection, -angleD)); // Rotate about the camera's up direction to look left/right
    MainCamera.LookDirection = m.Transform(MainCamera.LookDirection);
}

public void RotateVertical(double d)
{
    // Rotate up a certain number of degrees
    double u = 0.05;
    double angleD = u * d;

    // Cross Product gets a vector that is perpendicular to the passed in vectors (order does matter, reverse the order and the vector will point in the reverse direction)
    var cp = Vector3D.CrossProduct(MainCamera.UpDirection, MainCamera.LookDirection);
    cp.Normalize();

    var m = new Matrix3D();
    m.Rotate(new Quaternion(cp, -angleD)); // Rotate about the vector from the cross product
    MainCamera.LookDirection = m.Transform(MainCamera.LookDirection);
}

public void Move(double d)
{
    // Move forwards a certain number of steps
    double u = 0.05;
    Vector3D lookDirection = MainCamera.LookDirection;

    lookDirection.Normalize();
    MainCamera.Position = MainCamera.Position + u * lookDirection * d;
}

public void MoveSideways(double d)
{
    // Move sideways a certain number of steps
    double u = 0.05;
    Vector3D SideDirection = Vector3D.CrossProduct(MainCamera.LookDirection, MainCamera.UpDirection);
    SideDirection.Normalize();
    MainCamera.Position = MainCamera.Position + u * SideDirection * d;
}

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    // Detect keypresses
    switch (e.Key)
    {
        case Key.W:
            Move(10);
            break;
        case Key.A:
            MoveSideways(-10);
            break;
        case Key.S:
            Move(-10);
            break;
        case Key.D:
            MoveSideways(10);
            break;
        }
}

private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
    // Change the position of the crosshair if the window size changes.
    Crosshair.Margin = new Thickness(MainViewport.ActualWidth / 2, MainViewport.ActualHeight / 2, 0, 0);
    CrosshairX = MainViewport.ActualWidth / 2;
    CrosshairY = MainViewport.ActualHeight / 2;
}

private void Window_MouseMove(object sender, MouseEventArgs e)
{
     // Detects when the mouse moves.
    Rotate(Mouse.GetPosition(Application.Current.MainWindow).X - MouseX);
    RotateVertical(MouseY - Mouse.GetPosition(Application.Current.MainWindow).Y);

    MouseX = Mouse.GetPosition(Application.Current.MainWindow).X;
    MouseY = Mouse.GetPosition(Application.Current.MainWindow).Y;
}

private void Window_MouseLeave(object sender, MouseEventArgs e)
{
    // Bring mouse back to center if it leaves
    System.Windows.Forms.Cursor.Position = new System.Drawing.Point((int)CrosshairX, (int)CrosshairY);
}

我注意到添加

if (Mouse.GetPosition(Application.Current.MainWindow).X != CrosshairX && Mouse.GetPosition(Application.Current.MainWindow).Y != CrosshairY) {...}

RotateRotateVertical解决了问题,但它只工作了一半的时间。我想要一个 100% 有效的方法。

重置光标位置时如何阻止相机移动?

标签: c#wpf3d

解决方案


经过多次试验,我自己解决了这个问题。事实证明,问题在于MouseXMouseY正在存储窗口边界的 X 和 Y 值,并导致相机旋转从十字准线坐标与窗口边界坐标之差测量的角度。这导致相机旋转回中心。

我通过将MouseXMouseY坐标设置为十字准线坐标解决了这个问题,这样相机就不会旋转回中心。

private void Window_MouseLeave(object sender, MouseEventArgs e)
{
    // Bring mouse back to center if it leaves
    MouseX = CrosshairX;
    MouseY = CrosshairY;
    System.Windows.Forms.Cursor.Position = new System.Drawing.Point((int)CrosshairX, (int)CrosshairY);
}

推荐阅读