我正在开发Cad应用程序并希望实现快照 - 当用户将鼠标移动到某个对象附近时,我将Cursor.Position设置为该对象的中心点。如果用户在任何方向上移动鼠标说7个像素,则Cursor被释放。我的方法是 - 我存储snaped Cursor位置然后在MouseMoveEvent下我计算从存储位置到当前位置的距离。如果此位置小于定义的阈值,则将当前光标位置设置回存储值。每次调用MouseMoveEvent时,两个光标位置之间的微小差异都会添加到先前已计算的差异中,所以迟早会达到我的阈值并且Cursor跳出snaped位置。代码示例:
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闪烁(这很烦人)所以我的问题是 - 有没有办法如果光标锁定在一个位置,检测鼠标移动?
答案 0 :(得分:3)
我不会" snap"鼠标指针。你知道鼠标卡住的感觉吗?根据您的年龄,您可能会记得滚轮老鼠,里面有橡皮球的老鼠。太可怕了。
相反,我认为您要选择或正在移动的对象应该快速响应。例如,当您要选择一个对象时,当鼠标指针比阈值更接近时,对象将突出显示。用户可以单击鼠标并抓取对象。
当移动一个物体时,物体可以在比阈值更接近另一个物体,引导线等时捕捉到位。
答案 1 :(得分:1)
以下是一个自定义面板控件,用于演示捕捉到网格(snapPoints
)的所有者绘制光标。鼠标进入/离开时隐藏/显示系统光标。对齐点距离由常量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));
}
}
}
}
}