todos - c#¿Cómo puedo detectar si se ha hecho clic en una línea(pintada/dibujada en un formulario) cuando se usan las formas de ganar?
saber si un formulario esta abierto vb (2)
Con el método GraphicsPath.IsOutlineVisible
puede determinar si el punto especificado está debajo del contorno de la ruta cuando se dibuja con el Pen
especificado. Puede establecer el ancho del bolígrafo.
Entonces puede crear un GraphicsPath
y luego agregar una línea usando GraphicsPath.AddLine
a la ruta y verificar si la ruta contiene el punto.
Ejemplo:
El siguiente método verifica si p
está en línea con los puntos finales p1
y p2
usando el ancho especificado.
Puede usar un ancho más ancho para aumentar la tolerancia o si la línea es más ancha que 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;
}
Nota agregada por barlop
La instrucción path.AddLine(p1,p1);
en esta respuesta se equivocó y se corrigió en path.AddLine(p1,p2);
Ahora la respuesta funciona y funciona bien.
Tengo una aplicación de winforms
Aquí está mi código
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; }
}
Mi problema es esto ..
Puedo dibujar un rectángulo y puedo ver si hay un punto dentro de él.
Así que podría extender el programa para decir "sí" cuando un clic en el formulario esté dentro del rectángulo. El Rectángulo tiene una función Contiene que es genial.
Pero quiero hacer lo mismo con Line.
El problema es que winforms no tiene clase de línea. Podría escribir mi propia clase de línea, pero el problema sigue siendo ... ¿cómo saber si un clic aterrizó en él?
Noté que WPF tiene una clase así. ¿Cómo reconozco que un clic de mouse en una línea?
Pero estoy usando winforms.
Implementé una clase de Line
simple para verificar si un punto cae en la línea.
Puede capturar una posición de mouse fuera del evento Form_Click
Aquí está el fragmento
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 p.X >= Math.Min(Start.X, Stop.X)
&& p.X <= Math.Max(Start.X, Stop.X)
&& p.Y >= Math.Min(Start.Y, Stop.Y)
&& p.Y <= Math.Max(Start.Y, Stop.Y)
&& Math.Abs(Math.Abs(p.Y) - Math.Abs((m * p.X) + c)) < epsilon; //with relax rules
//&& (p.Y == (m*p.X)+c); // strict version
}
}
ACTUALIZAR
cuidado de un caso donde X1 == X2. Lanzará excepción.