用鼠标移动绘制的线条

我试图通过用鼠标抓住它来移动绘制的线条。

该行已经使用Graphics.DrawLine(Pen P, Point A, Point B)绘制。

创建Line并在表单上绘制它绝对没有问题。

我试过了:

  • 将行添加到GraphicsPath – 这甚至不绘制OnPaint行。

  • 检查MouseEventArgs e.Location是否与一些基本代数一致(我现在扔掉的计算)

总结一下:我想抓住线并将其拖到某处,但我甚至无法检查e.Location是否在线上,我该怎么做?

编辑:这是我使用GraphicsPath时代码的外观。

当我不使用GraphicsPath我有:

 if (s.thisShape == ShapeType.Line) { g.DrawLine(pen, s.p1, s.p2); } else { ... }` 

在drawingShapes方法中。

来自drawStuff:Usercontrol类:

 private void drawStuff_MouseDown(object sender, MouseEventArgs e) { pointRegion = e.Location; for (int i = 0; i < Shapes.Count; i++) { if (Shapes[i].Region.IsVisible(pointRegion)) { isDragging = true; count = i; break; } } } private void drawStuff_MouseMove(object sender, MouseEventArgs e) { if (isDragging) { Shapes[count].moveWithDiff(pointRegion, e.Location); pointRegion = e.Location; Refresh(); } } private void drawStuff_MouseUp(object sender, MouseEventArgs e) { isDragging = false; Refresh(); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); drawShapes(e.Graphics); } private void drawShapes(Graphics g) { temporaryPen = pennaLeft; foreach (Shape s in Shapes) { g.FillRegion(temporaryPen, s.Region); } } 

从Shape:Usercontrol类:

 public void moveWithDiff(Point pr, Point mp) { Point p = new Point(); if (this.thisShape == ShapeType.Line) { pX = mp.X - pr.X; pY = mp.Y - pr.Y; this.p1.X += pX; this.p1.Y += pY; this.p2.X += pX; this.p2.Y += pY; } RefreshPath(); } private void RefreshPath() { gPath = new GraphicsPath(); switch (thisShape) { case ShapeType.Line: gPath.AddLine(this.p1, this.p2); break; } this.Region = new Region(gPath); } 

现在这甚至没有绘制线,但是在drawingShapes()中使用if语句它绘制得很完美,但我不能将它拖到其他地方。

让我们从基础开始,在屏幕上划一条线。 我创建了一个自定义类来处理我希望这个过程可以使用的一些函数:

 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 * pX + YIntercept); if (temp >= (pY-cushion) && temp <=(p.Y+cushion)) { return true; } else { return false; } } } 

这个类提供了一些辅助函数,可以让我们的生活更轻松。 我们有返回斜率和Y截距的属性,因此我们可以确定某个点是否在线上。 然后我们提供一个辅助函数IsPointOnLine(),它需要一个点和一个缓冲。 缓冲垫用于简单地允许用户点击足够靠近线以使其返回真实。

接下来,我将实例化该行并在Form的paint事件中绘制它:

 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个像素内单击并使用鼠标移动它。

注意,代码中有一些需要额外error handling的位置,尤其是处理除0错误。

我建议你创建一个矩形,它是线条的宽度和线条的长度,然后你可以使用

 if(rectangle.Contains(Point p)) { // do your move } 

您还可以对矩形进行充气,以便更轻松地抓取:

 rectangle.Inflate(1, 1);