如何检测 Windows 窗体中一行的点击

bar*_*lop 3 .net c# graphics gdi+ 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; }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是这个..

我可以画一个矩形,并且可以查看其中是否有一个点。

因此,我可以扩展程序,当在矩形内单击表单时说“是”。矩形有一个很棒的包含函数。

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

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

我注意到 WPF 有这样一个类 如何识别鼠标单击一行?

但我用的是winform。

Rez*_*aei 6

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

因此,您可以创建一个GraphicsPath,然后向路径添加一条线GraphicsPath.AddLine,并检查路径是否包含该点。

例子:

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

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

//using System.Drawing;
//using System.Drawing.Drawing2D;
bool IsOnLine(Point p1, Point p2, Point p, int width = 1)
{
    using (var path = new GraphicsPath())
    {
        using (var pen = new Pen(Brushes.Black, width))
        {
            path.AddLine(p1, p2);
            return path.IsOutlineVisible(p, pen);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)