There are various ways to achieve this, I would go for a solution where you store a list of
Line
objects and render them after the base render pass of the
PictureBox
.
This would make it easy to move and change the style of all lines.
To save a image is fairly simple, there's a
Save
method on
Image
.
You could try extending
PictureBox
like this, this is a working example;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace LinesTest
{
public class LinedPictureBox : PictureBox
{
private IList<Line> lines = new List<Line>();
private Line currentLine = null;
private bool holdsA = false;
public LinedPictureBox()
{
DoubleBuffered = true;
MouseDown += HandleMouseDown;
MouseMove += HandleMouseMove;
MouseUp += (s, e) => currentLine = null;
}
private static int GetDistance(Point a, Point b)
{
int dx = a.X - b.X;
int dy = a.Y - b.Y;
return (int)Math.Sqrt(dx * dx + dy * dy);
}
private void HandleMouseMove(object sender, MouseEventArgs e)
{
if (currentLine != null)
{
if (holdsA)
currentLine.A = e.Location;
else
currentLine.B = e.Location;
Invalidate();
}
}
private void HandleMouseDown(object sender, MouseEventArgs e)
{
Line aLine = (from line in lines orderby GetDistance(line.A, e.Location) select line).FirstOrDefault();
Line bLine = (from line in lines orderby GetDistance(line.B, e.Location) select line).FirstOrDefault();
if (aLine != null && bLine != null)
{
int aDistance = GetDistance(aLine.A, e.Location);
int bDistance = GetDistance(bLine.B, e.Location);
if (Math.Min(aDistance, bDistance) < 8)
{
if (aDistance < bDistance)
{
currentLine = aLine;
holdsA = true;
}
else
{
currentLine = bLine;
holdsA = false;
}
return;
}
}
currentLine = new Line { A = e.Location, B = e.Location, Pen = Pens.Red };
holdsA = false;
lines.Add(currentLine);
Invalidate();
}
private void PaintLines(Graphics graphics)
{
foreach (Line line in lines)
graphics.DrawLine(line.Pen, line.A, line.B);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
PaintLines(e.Graphics);
}
public void Save(string filename)
{
Image image = new Bitmap(Width, Height);
Graphics graphics = Graphics.FromImage(image);
switch (SizeMode)
{
case PictureBoxSizeMode.AutoSize:
case PictureBoxSizeMode.Normal:
graphics.DrawImage(Image, new Point());
break;
case PictureBoxSizeMode.StretchImage:
graphics.DrawImage(Image, new Rectangle(0, 0, Width, Height), new Rectangle(0, 0, Image.Width, Image.Height), GraphicsUnit.Pixel);
break;
case PictureBoxSizeMode.CenterImage:
{
int x = Math.Max(0, (Image.Width - Width) / 2);
int y = Math.Max(0, (Image.Height - Height) / 2);
graphics.DrawImage(Image, new Rectangle(0, 0, Width, Height), new Rectangle(x, y, Width, Height), GraphicsUnit.Pixel);
}
break;
}
PaintLines(graphics);
image.Save(filename);
}
}
public class Line
{
public Point A { get; set; }
public Point B { get; set; }
public Pen Pen { get; set; }
}
}
Hope this helps,
Fredrik