Вот подходящий класс Line
:
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;
}
}
Определите список строк, возможно, на уровне класса:
List lines = new List();
Вот как вы можете инициализировать это несколько строк:
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))));
Вот результат нажатия на переход:
Всякий раз, когда вы добавляете , измените или удалите строку, необходимую для того, чтобы Panel
отразили новости, вызвав событие Paint
:
panel1.Invalidate();
. Здесь Paint
событие Panel
:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
foreach (Line L in lines) L.Draw(e.Graphics);
}
В событии MouseClick
вы выполните тест:
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();
}
Чтобы избежать мерцания, не используйте базовый класс Panel
, поскольку он не doublebuffered
, Вместо этого используйте либо подкласс PictureBox
, либо doublebuffered Panel
:
class DrawPanel : Panel
{ public DrawPanel () { DoubleBuffered = true; } }
Примечания:
Line
выглядит немного длиннее для таких простая вещь asa line, но посмотрите, насколько короткими все коды событий теперь! Это потому, что ответственность - это место, где они принадлежат! Grahics
. Фактически, вы никогда не должны использовать CreateGraphics
в первую очередь, так как объект Graphics
никогда не останется в области видимости, и создаваемая графика не будет сохраняться (т. Е. Выдержать последовательность с минимальным увеличением). e.Graphics
объект параметров события Paint
в экземпляры Line
, чтобы они могли нарисовать себя с помощью текущего объекта Graphics
!