Como desenhar linha e selecione no painel

Meu programa pode desenhar linhas usando canvas.Drawline (). Como clicar na linha e alterar essa cor (selecione a linha)?

private List coordFirst = new List(); private List coordLast = new List(); public Graphics canvas; private void Form1_Load(object sender, EventArgs e) { canvas=panel1.CreateGraphics(); } 

Linha de coordenadas armazenada em coordFirs & coodLast.

Aqui está uma class Line adequada:

 class Line { public Color LineColor { get; set; } public float Linewidth { get; set; } public bool Selected { get; set; } public Point Start { get; set; } public Point End { get; set; } public Line(Color c, float w, Point s, Point e) { LineColor = c; Linewidth = w; Start = s; End = e; } public void Draw(Graphics G) { using (Pen pen = new Pen(LineColor, Linewidth)) G.DrawLine(pen, Start, End); } public bool HitTest(Point Pt) { // test if we fall outside of the bounding box: if ((Pt.X < Start.X && Pt.X < End.X) || (Pt.X > Start.X && Pt.X > End.X) || (Pt.Y < Start.Y && Pt.Y < End.Y) || (Pt.Y > Start.Y && Pt.Y > End.Y)) return false; // now we calculate the distance: float dy = End.Y - Start.Y; float dx = End.X - Start.X; float Z = dy * Pt.X - dx * Pt.Y + Start.Y * End.X - Start.X * End.Y; float N = dy * dy + dx * dx; float dist = (float)( Math.Abs(Z) / Math.Sqrt(N)); // done: return dist < Linewidth / 2f; } } 

Defina uma lista para as linhas, provavelmente em nível de class:

  List lines = new List(); 

Aqui está como você pode inicializá-lo com algumas linhas:

 for (int i = 0; i < 20; i++) lines.Add(new Line(Color.Black, 4f, new Point(R.Next(panel1.Width), R.Next(panel1.Height)), new Point(R.Next(panel1.Width), R.Next(panel1.Height)))); 

Aqui está o resultado de clicar em um cruzamento:

insira a descrição da imagem aqui

Sempre que você adicionar, alterar ou remover uma linha, você precisará fazer com que o Panel reflita as notícias, acionando o evento Paint :

 panel1.Invalidate(); 

Aqui está o evento Paint do Panel :

 private void panel1_Paint(object sender, PaintEventArgs e) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; foreach (Line L in lines) L.Draw(e.Graphics); } 

No evento do MouseClick você faz o teste:

 private void panel1_MouseClick(object sender, MouseEventArgs e) { foreach(Line L in lines) L.LineColor = L.HitTest(e.Location) ? Color.Red : Color.Black; panel1.Invalidate(); } 

Para evitar o flicker, não use a class básica do Panel pois ela não é doublebuffered . Em vez disso, use uma PictureBox ou uma subclass de doublebuffered Panel :

 class DrawPanel : Panel { public DrawPanel () { DoubleBuffered = true; } } 

Notas :

  • Não existe uma 'Line' no WinForms, apenas pixels de várias colors. Então, para selecionar uma linha, você precisa armazenar as duas coordenadas dos pontos de extremidade e, em seguida, descobrir se você a atingiu quando clicou.

  • O exemplo acima mostra como fazer isso em matemática.

  • Em vez disso, pode-se testar cada linha desenhando-a em um bitmap e testando o pixel que o mouse clicou. Mas desenhar esses bitmaps teria que fazer matemática nos bastidores e também alocar espaço para os bitmaps, então a matemática será mais eficiente.

  • Sim, a class Line parece um pouco longa para uma coisa tão simples como uma linha, mas veja como são curtos todos os códigos de evento! Isso é porque as responsabilidades são onde elas pertencem!

  • Observe também que a primeira regra de fazer qualquer desenho no WinForms é: Nunca armazenar em cache ou armazenar um object Grahics . Na verdade, você nunca deve usar o CreateGraphics em primeiro lugar, pois o object Graphics nunca ficará no escopo e os charts que ele produz não persistem (ou seja, sobrevivam a uma sequência Minimize-maximize).

  • Observe também como eu distribuo o object e.Graphics dos parâmetros do evento Paint para as instâncias Line para que eles possam desenhar com um object Graphics atual!

  • Para selecionar linhas mais finas, pode ajudar a modificar um pouco a distância.

  • A Matemática foi tirada diretamente da Wikipedia .

Você pode mudar a cor de tudo ao clicar. Usando o evento click de um object específico.

Eu dou um exemplo para o botão. Se você clicar no botão, a cor do panal será alterada. Você pode modificar o código conforme sua necessidade.

 private List coordFirst = new List(); private List coordLast = new List(); public Graphics canvas; private void Form1_Load(object sender, EventArgs e) { canvas = panel1.CreateGraphics(); } private void panel1_Click(object sender, EventArgs e) { panel1.BackColor = Color.Blue; } private void nonSelectableButton3_Click(object sender, EventArgs e) { panel1.BackColor = Color.BurlyWood; }