Итак, я подумал, а затем Visual Studio-ing, что, возможно, нам даже не нужен цикл foreach. Я все еще поддерживаю список, чтобы мы знали, где пользователь щелкнул, но нет необходимости перебирать его и каждый раз перерисовывать.
Я понимаю, что это не обрабатывает случай, когда базовый список изменен, но и исходный образец. Вот весь мой Form1 класс:
public partial class Form1 : Form
{
private const int CircleDiameter = 20;
private const int PenWidth = 2;
private readonly List<Point> _points = new List<Point>();
public Form1()
{
InitializeComponent();
pictureBox1.Paint += (sender, args) =>
{
_points.ForEach(p => DrawPoint(p, args.Graphics));
};
}
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
var cursorLocation = pictureBox1.PointToClient(Cursor.Position);
_points.Add(cursorLocation);
var circleArea = new Rectangle(
cursorLocation.X - CircleDiameter/2 - PenWidth,
cursorLocation.Y - CircleDiameter/2 - PenWidth,
CircleDiameter + PenWidth*2,
CircleDiameter + PenWidth*2);
pictureBox1.Invalidate(circleArea);
}
private static void DrawPoint(Point point, Graphics graphics)
{
point.X -= CircleDiameter/2;
point.Y -= CircleDiameter/2;
using (var pen = new Pen(Color.Tomato, PenWidth))
using (var brush = new SolidBrush(Color.White))
{
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.DrawEllipse(pen, point.X, point.Y, CircleDiameter, CircleDiameter);
graphics.FillEllipse(brush, point.X, point.Y, CircleDiameter, CircleDiameter);
}
}
}
Update 1: Я обновил код, чтобы использовать событие Paint, который имеет цикл по каждому элементу. Тем не менее, я не делаю Invalidate (и Paint) каждый раз, когда добавляется круг - в этом нет необходимости. Просто добавление круга путем рисования означает, что элемент управления только отменяет действие и повторно рисует область, в которую был добавлен новый круг.
Попробуйте установить точку останова по методу DrawAllPoints. Вы увидите, что это происходит только во время полных недействительных операций, таких как минимизация и восстановление.
Обновление 2: После дополнительного чата я согласен, что метод Invalidate является превосходным. Код обновлен, чтобы использовать Invalidate с прямоугольником, чтобы сделать недействительным.
И теперь он очень похож на OP :)
Затем нарисовать ~ до ~ круга также в событии рисования. – Ralf
'pictureBox1.Paint + = новый PaintEventHandler (pic_Paint);' должен находиться в вашей форме load или constructor. –
@ RezaAghaei, почему его следует использовать только в конструкторе? и объясните немного больше? –