如果 Cursor 被锁定,则检测鼠标移动
Detect mouse movement if Cursor is locked
我正在开发 Cad 应用程序并希望实现捕捉 - 当用户将鼠标移近某个对象时,我将 Cursor.Position 设置为该对象的中心点。如果用户在任何方向上移动鼠标说 7 个像素,那么 Cursor 设置 free.The 我这样做的方式是 - 我存储捕捉的 Cursor 位置,然后在 MouseMoveEvent 下我计算从存储位置到当前位置的距离。如果这个位置小于定义的阈值,那么我将当前光标位置设置回存储值。每次调用 MouseMoveEvent 时,两个光标位置之间的微小差异都会添加到先前计算的差异中,因此迟早会达到我的阈值并且光标会跳出对齐位置。代码示例:
var x = Cursor.Position.X - storedPosition.X;
pixelsX += x;
int threshold = 7;
if (pixelsX > threshold)
{
Cursor.Position = new System.Drawing.Point(storedPosition.X + 10, storedPosition.Y);
snapReleased = true;
}
这个问题是,在每个 MouseMoveEvent 中,鼠标移动的量非常小,如果没有达到阈值,它会设置回存储位置,这会使光标闪烁(这很烦人)所以我的问题是 - 有没有一种在 Cursor 锁定在一个位置时检测鼠标移动的方法?
我不会"snap"鼠标指针。你知道鼠标卡住时的感觉吗?根据您的年龄,您可能还记得滚轮老鼠,它们里面有一个橡皮球。太可怕了。
相反,我认为您即将 select 或当前正在移动的物体应该会迅速做出反应。例如,当您要 select 一个对象时,当鼠标指针比阈值更近时,该对象将突出显示。用户可以点击鼠标并抓取对象。
移动物体时,当物体与另一个物体、引导线等的距离小于阈值时,该物体可以吸附到位
以下是一个自定义面板控件,它演示了一个捕捉到网格的所有者绘制的光标 (snapPoints
)。系统光标在鼠标 entry/leave 上 hidden/shown。捕捉到点的距离由常量 snapLimit
控制。
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
namespace WindowsFormsApplication1
{
public class DrawingSurface : Panel
{
private const double snapLimit = 7.0D;
private List<Point> snapPoints = new List<Point>();
private Point cursorPos;
private Point lastDrawnPos;
private bool drawCursor;
public DrawingSurface() : base()
{
this.BorderStyle = BorderStyle.Fixed3D;
this.BackColor = Color.AliceBlue;
this.DoubleBuffered = true;
this.Cursor = Cursors.Cross;
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
System.Windows.Forms.Cursor.Hide();
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
System.Windows.Forms.Cursor.Show();
this.drawCursor = false;
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
foreach (Point dot in this.snapPoints)
{
e.Graphics.FillEllipse(Brushes.Red, dot.X - 1, dot.Y - 1, 2, 2);
}
if (drawCursor)
{
Cursor cur = System.Windows.Forms.Cursor.Current;
Point pt = this.cursorPos;
pt.Offset(-cur.HotSpot.X, -cur.HotSpot.Y);
Rectangle target = new Rectangle(pt, cur.Size);
cur.Draw(e.Graphics, target);
this.lastDrawnPos = this.cursorPos;
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
SetCursor(e.Location);
}
private void SetCursor(Point loc)
{
this.cursorPos = loc;
foreach (Point pt in this.snapPoints)
{
double deltaX = loc.X - pt.X;
double deltaY = loc.Y - pt.Y;
double radius = Math.Sqrt((deltaX * deltaX) + (deltaY * deltaY));
if (radius < snapLimit)
{
this.cursorPos = pt;
break;
}
}
if (lastDrawnPos != this.cursorPos)
{
this.drawCursor = true;
this.Invalidate();
}
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
this.snapPoints.Clear();
for (int y = 0; y <= this.ClientRectangle.Height; y += 50)
{
for (int x = 0; x <= this.ClientRectangle.Width; x += 50)
{
this.snapPoints.Add(new Point(x, y));
}
}
}
}
}
我正在开发 Cad 应用程序并希望实现捕捉 - 当用户将鼠标移近某个对象时,我将 Cursor.Position 设置为该对象的中心点。如果用户在任何方向上移动鼠标说 7 个像素,那么 Cursor 设置 free.The 我这样做的方式是 - 我存储捕捉的 Cursor 位置,然后在 MouseMoveEvent 下我计算从存储位置到当前位置的距离。如果这个位置小于定义的阈值,那么我将当前光标位置设置回存储值。每次调用 MouseMoveEvent 时,两个光标位置之间的微小差异都会添加到先前计算的差异中,因此迟早会达到我的阈值并且光标会跳出对齐位置。代码示例:
var x = Cursor.Position.X - storedPosition.X;
pixelsX += x;
int threshold = 7;
if (pixelsX > threshold)
{
Cursor.Position = new System.Drawing.Point(storedPosition.X + 10, storedPosition.Y);
snapReleased = true;
}
这个问题是,在每个 MouseMoveEvent 中,鼠标移动的量非常小,如果没有达到阈值,它会设置回存储位置,这会使光标闪烁(这很烦人)所以我的问题是 - 有没有一种在 Cursor 锁定在一个位置时检测鼠标移动的方法?
我不会"snap"鼠标指针。你知道鼠标卡住时的感觉吗?根据您的年龄,您可能还记得滚轮老鼠,它们里面有一个橡皮球。太可怕了。
相反,我认为您即将 select 或当前正在移动的物体应该会迅速做出反应。例如,当您要 select 一个对象时,当鼠标指针比阈值更近时,该对象将突出显示。用户可以点击鼠标并抓取对象。
移动物体时,当物体与另一个物体、引导线等的距离小于阈值时,该物体可以吸附到位
以下是一个自定义面板控件,它演示了一个捕捉到网格的所有者绘制的光标 (snapPoints
)。系统光标在鼠标 entry/leave 上 hidden/shown。捕捉到点的距离由常量 snapLimit
控制。
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
namespace WindowsFormsApplication1
{
public class DrawingSurface : Panel
{
private const double snapLimit = 7.0D;
private List<Point> snapPoints = new List<Point>();
private Point cursorPos;
private Point lastDrawnPos;
private bool drawCursor;
public DrawingSurface() : base()
{
this.BorderStyle = BorderStyle.Fixed3D;
this.BackColor = Color.AliceBlue;
this.DoubleBuffered = true;
this.Cursor = Cursors.Cross;
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
System.Windows.Forms.Cursor.Hide();
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
System.Windows.Forms.Cursor.Show();
this.drawCursor = false;
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
foreach (Point dot in this.snapPoints)
{
e.Graphics.FillEllipse(Brushes.Red, dot.X - 1, dot.Y - 1, 2, 2);
}
if (drawCursor)
{
Cursor cur = System.Windows.Forms.Cursor.Current;
Point pt = this.cursorPos;
pt.Offset(-cur.HotSpot.X, -cur.HotSpot.Y);
Rectangle target = new Rectangle(pt, cur.Size);
cur.Draw(e.Graphics, target);
this.lastDrawnPos = this.cursorPos;
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
SetCursor(e.Location);
}
private void SetCursor(Point loc)
{
this.cursorPos = loc;
foreach (Point pt in this.snapPoints)
{
double deltaX = loc.X - pt.X;
double deltaY = loc.Y - pt.Y;
double radius = Math.Sqrt((deltaX * deltaX) + (deltaY * deltaY));
if (radius < snapLimit)
{
this.cursorPos = pt;
break;
}
}
if (lastDrawnPos != this.cursorPos)
{
this.drawCursor = true;
this.Invalidate();
}
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
this.snapPoints.Clear();
for (int y = 0; y <= this.ClientRectangle.Height; y += 50)
{
for (int x = 0; x <= this.ClientRectangle.Width; x += 50)
{
this.snapPoints.Add(new Point(x, y));
}
}
}
}
}