如何知道鼠标在MouseMove之前的位置

时间:2013-03-07 03:17:31

标签: c# directx mousemove cursor-position snap-to-grid

我正在尝试在我的应用程序中实现一种功能,将光标捕捉到场景中网格的边缘。目前我确实有框架来获取当前的 MouseMove 提供的 e.Location 并转换为我的世界坐标并返回到屏幕 - 并且值匹配。请参阅以下基本代码概述。

public void Scene_MouseMove(object sender, MouseEventArgs e)
{
    Vector2 world = ScreenToWorld(e.Location);

    ---> Check here to make sure the world coordinates returned
         fall inside my grid scene edges.
    if (world.X < Grid.Left) world.x = Grid.Left;

    Point target = WorldToScreen(world);

    // set cursr desired position
    Cursor.Position = (sender as PictureBox).PointToScreen( target );
}

我遇到的问题是MouseMove被称为 AFTER 鼠标已经移动的事实,所以当我点击网格的边缘时,我看到鼠标过冲了一帧,并且然后纠正自己。当我移动鼠标时,这会导致光标抖过边缘。我想这样做,当我到达边缘时光标在其轨道上停止死亡,但我不知道如何在鼠标移动之前捕获数据!

也许我会说错了,所以任何建议都会非常感激。

仅供参考 - 这是我试图实施的SnapToGrid功能的第一部分。

编辑:一个更简单的例子:

您可以通过以下简单示例查看我的问题。注意当你移动光标时光标是如何闪烁的?

bool g_Set = false;
public void Scene_MouseMove(object sender, MouseEventArgs e)
{
    // stop MouseMove from flooding the control recursively
    if(g_Set) { g_Set = false; return; }
    g_Set = true;
    Cursor.Position = new Point(400,400);
}

C#是否支持API中的任何内容以在实际移动Cursor之前捕获 MouseMove ,或者我应该只是考虑实现我自己的Cursor类来隐藏 Form.Cursor 并且只是渲染我的(我还需要调查其他内容,因为我对该功能一无所知)。

4 个答案:

答案 0 :(得分:0)

要捕捉到边缘,为快照提供一点空间,例如2像素:

if (world.X - 2 < Grid.Left) world.x = Grid.Left;

将光标限制在控件的矩形内,例如:aButton

Cursor.Clip = aButton.RectangleToScreen(aButton.ClientRectangle);

释放光标:

Cursor.Clip = null;

答案 1 :(得分:0)

使用线性外推法计算进入帧之前的最后一个像素。你需要两个点P1和P2。输入前的点P0可以近似为

P0.X = P2.X - P1.X
P0.Y = P2.Y - P1.Y

答案 2 :(得分:0)

您可以创建一个UserControl,其上有一个场景。将场景放在中心,周围有已知大小的边距。 UserControl.BackColor = Transparentprivate void UserControl_MouseMove(Object sender,MouseEventArgs e) { // check if mouse is entering the Scene, you know the size of the margin } 。处理事件

{{1}}

从那里你可以想出让鼠标进入场景的逻辑。

答案 3 :(得分:0)

所以经过一整天的调查后,我最终崩溃并编写了一个Cursor类。这里重要的是我使用Managed DirectX在PictureBox中渲染,所以我有一条出路。

实际上,当它进入控件时我隐藏 System.Cursor 并通过在每个帧之间获取System.Cursor的偏移量来开始渲染我自己的光标,应用我的逻辑,并确定我在哪里想要渲染“我的”光标。请参阅下文我如何处理抵消:

public bool g_RecalcCursor = false;
public Point g_Reference = new Point(400,400);
public void SceneView_MouseMove(object sender, MouseEventArgs e)
{
    // this logic avoids recursive calls into MouseMove
    if (g_RecalcCursor)
    { 
        g_RecalcCursor = false;
        return;
    }

    Point ee = (sender as PictureBox).PointToScreen(e.Location);
    Point delta = new Point(g_Reference.X - ee.X, g_Reference.Y - ee.Y);

    //------------------------------------------//
    // I can use delta now to move my cursor    //
    // and apply logic "BEFORE" it renders      //
    //------------------------------------------//

    g_RecalcCursor = true;
    Cursor.Position = g_Reference;
}

我很惊讶鼠标移动时没有像 Form_Closing / Form_Closed 这样的调用( MouseMoving / MouseMove ) - 但是再一次, System.Cursor 可能并不意味着被应用程序操纵,以免恶化用户应该如何正常运行的体验,因此API中的操作功能有限。

我仍然愿意接受任何让我使用System.Cursor的建议......