c#如何在使用winforms时检测是否已点击一条线(在表格上绘制/绘制)?

我有一个winforms应用程序

这是我的代码

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication12 { public partial class Form1 : Form { Graphics gr; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { gr = this.CreateGraphics(); MyLine myline = new MyLine(); myline.P1 = new Point(100, 0); myline.P2 = new Point(200, 80); gr.DrawLine(new Pen(Color.Red), myline.P1,myline.P2); Rectangle r = new Rectangle(0, 0, 50, 50); gr.DrawRectangle(new Pen(Color.Teal, 5), r); if (r.Contains(0,25)) MessageBox.Show("within"); } private void btnClear_Click(object sender, EventArgs e) { gr.Clear(this.BackColor); } } } class MyLine { public Point P1 {get; set;} public Point P2 { get; set; } } 

我的问题是这个……

我可以绘制一个矩形,我可以看到一个点是否在其中。

因此,当表单上的单击位于矩形内时,我可以将程序扩展为“是”。 Rectangle有一个很好的Contains函数。

但我想为Line做同样的事情。

问题是,winforms没有Line类。 我可以编写自己的Line类,但问题仍然存在..如何查找点击是否落在它上面?

我注意到WPF有这样一个类如何识别线上的鼠标点击?

但我正在使用winforms。

使用GraphicsPath.IsOutlineVisible方法,可以确定使用指定的Pen绘制时指定的点是否在路径轮廓下。 您可以设置笔的宽度。

因此,您可以创建一个GraphicsPath ,然后使用GraphicsPath.AddLine将一行添加到路径中,并检查路径是否包含该点。

例:

下面的方法使用指定的宽度检查p是否在带有端点p1p2的行上。

您可以使用更宽的宽度来增加公差,或者如果线宽大于1:

 bool IsOnLine(Point p1, Point p2, Point p, int width = 1) { var isOnLine= false; using (var path = new GraphicsPath()) { using (var pen = new Pen(Brushes.Black, width)) { path.AddLine(p1,p2); isOnLine = path.IsOutlineVisible(p, pen); } } return isOnLine; } 

注意由barlop添加

语句path.AddLine(p1,p1); 在这个答案是错误的,并纠正为path.AddLine(p1,p2); 现在答案有效并且效果很好。

我实现了一个简单的Line类来检查一个点是否落在了线上。
您可以从Form_Click事件中捕获鼠标位置

这是片段

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication { public partial class Form1 : Form { Line myLine; int x1 = 10; int x2 = 40; int y1 = 0; int y2 = 30; public Form1() { InitializeComponent(); myLine = new Line() { Start = new Point(x1, y1), Stop = new Point(x2, y2), Epsilon = 10 }; } private void Form1_Paint(object sender, PaintEventArgs e) { Pen pen = new Pen(Color.FromArgb(255, 0, 0, 0)); e.Graphics.DrawLine(pen, x1, y1, x2, y2); pen.Dispose(); } private void Form1_Click(object sender, EventArgs e) { MouseEventArgs me = (MouseEventArgs)e; bool contain = myLine.contain(new Point(me.X,me.Y)); } } public class Line { public Point Start { get; set; } public Point Stop { get; set; } public float Epsilon { get; set; } public bool contain(Point p) { // y = mx + c float m = (Stop.Y - Start.Y) / (Stop.X - Start.X); float c = Stop.Y - (m * Stop.X); return pX >= Math.Min(Start.X, Stop.X) && pX <= Math.Max(Start.X, Stop.X) && pY >= Math.Min(Start.Y, Stop.Y) && pY <= Math.Max(Start.Y, Stop.Y) && Math.Abs(Math.Abs(pY) - Math.Abs((m * pX) + c)) < epsilon; //with relax rules //&& (pY == (m*pX)+c); // strict version } } 

UPDATE
小心X1 == X2的情况。 它会抛出exception。