我正在尝试在我的应用程序中实现一种功能,将光标捕捉到场景中网格的边缘。目前我确实有框架来获取当前的 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 并且只是渲染我的(我还需要调查其他内容,因为我对该功能一无所知)。
答案 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 = Transparent
。private 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的建议......