让我们从基础知识开始,在屏幕上画一条线。我创建了一个自定义类来处理我希望在此过程中可用的一些功能:
public class MyLine
{
public Pen pen { get; set; }
public Point Start { get; set; }
public Point End { get; set; }
public MyLine(Pen p, Point p1, Point p2)
{
pen = p;
Start = p1;
End = p2;
}
public float slope
{
get
{
return (((float)End.Y - (float)Start.Y) / ((float)End.X - (float)Start.X));
}
}
public float YIntercept
{
get
{
return Start.Y - slope*Start.X;
}
}
public bool IsPointOnLine(Point p, int cushion)
{
float temp = (slope * p.X + YIntercept);
if (temp >= (p.Y-cushion) && temp <=(p.Y+cushion))
{
return true;
}
else
{
return false;
}
}
}
这个类提供了一些帮助函数,可以让我们的生活更轻松。我们有返回斜率和 Y 截距的属性,因此我们可以确定某个点是否在线上。然后,我们提供一个辅助函数 IsPointOnLine(),它接受一个点和一个缓冲。缓冲垫用于简单地允许用户在距离线足够近的地方单击以使其返回 true。
接下来我将实例化这条线并在窗体的绘制事件中绘制它:
MyLine m;
private void Form1_Load(object sender, EventArgs e)
{
m= new MyLine(Pens.Black, new Point(20, 20), new Point(40, 40));
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(m.pen, m.Start, m.End);
}
现在您应该能够运行您的应用程序并在屏幕上看到一条从 20,20 到 40,40 的行。
现在我想处理鼠标与线的交互,因此在 MouseDown 上,我们将查看单击点是否与线相交,以及是否设置了标志并保持与端点的增量。在 MouseMove 事件中,我们将查看该线是否已被单击但未释放,并相应地重置坐标。在 MouseUp 事件中,我们简单地重置我们的标志:
Point deltaStart;
Point deltaEnd;
bool dragging = false;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left && m.IsPointOnLine(e.Location, 5))
{
dragging = true;
deltaStart = new Point(m.Start.X - e.Location.X, m.Start.Y - e.Location.Y);
deltaEnd = new Point(m.End.X - e.Location.X, m.End.Y - e.Location.Y);
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (dragging && deltaStart != null && deltaEnd != null )
{
m.Start = new Point(deltaStart.X + e.Location.X, deltaStart.Y + e.Location.Y);
m.End = new Point(deltaEnd.X + e.Location.X, deltaEnd.Y + e.Location.Y);
this.Refresh();
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
dragging = false;
}
现在您应该能够在该线的 5 个像素范围内单击并使其随鼠标移动。
请注意,代码中的某些位置需要额外的错误处理,尤其是处理除 0 错误。