Disegna più polilinea o curva a mano libera – Aggiunta di funzionalità di annullamento

Sto cercando di creare un’applicazione di disegno semplice con funzionalità di annullamento e ripetizione. Presumo che tu possa aggiungere ciò che stai disegnando in una lista e invocando la lista per disegnare tutto. Quindi annullare deve solo rimuovere l’ultimo elemento aggiunto e ridisegnare tutto di nuovo. Il problema è, come posso aggiungere quello che ho disegnato in una lista e usare quella lista per annullare?

Sto usando il metodo di ridisegno bitmap. Ecco come disegno:

Point start, end; bool painting; private List myPoints = new List(); private void pnlMain_MouseDown(object sender, MouseEventArgs e) { start = e.Location; painting = true; } private void pnlMain_MouseUp(object sender, MouseEventArgs e) { painting = false; } private void pnlMain_MouseMove(object sender, MouseEventArgs e) { if (painting == true) { end = e.Location; g.DrawLine(p, start, end); myPoints.Add(e.Location); pnlMain.Refresh(); start = end; } } private void btnUndo_Click(object sender, EventArgs e) { g.Clear(cldFill.Color); if (myPoints.Count > 2) { myPoints.RemoveAt(myPoints.Count - 1); g.DrawCurve(p, myPoints.ToArray()); } pnlMain.Refresh(); //This works but you have to spam it to get rid of //a line and does some weird connections. } 

È necessario memorizzare le righe in un List> . Ogni elemento della lista contiene i punti di un disegno che si disegna usando un movimento verso il basso, spostato verso l’alto. La prossima linea che disegni, verrà memorizzata nel prossimo elemento della lista. Ogni annullamento rimuoverà l’ultimo disegno.

Inserisci un’istanza di questo controllo nel modulo e gestirà il disegno per te. Anche per eseguire l’annullamento, chiama il suo metodo Undo .

 using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; 
 public class DrawingSurface : Control { public DrawingSurface() { this.DoubleBuffered = true; } List> Lines = new List>(); bool drawing = false; protected override void OnMouseDown(MouseEventArgs e) { Lines.Add(new List()); Lines.Last().Add(e.Location); drawing = true; base.OnMouseDown(e); } protected override void OnMouseMove(MouseEventArgs e) { if (drawing) { Lines.Last().Add(e.Location); this.Invalidate(); } base.OnMouseMove(e); } protected override void OnMouseUp(MouseEventArgs e) { if (drawing) { this.drawing = false; Lines.Last().Add(e.Location); this.Invalidate(); } base.OnMouseUp(e); } protected override void OnPaint(PaintEventArgs e) { e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; foreach (var item in Lines) e.Graphics.DrawLines(Pens.Black, item.ToArray()); /*or DrawCurve*/ } public void Undo() { if (Lines.Count > 0) { this.Lines.RemoveAt(Lines.Count - 1); this.Invalidate(); } } } 

Nota

  • Usando questa logica, puoi semplicemente implementare la ripetizione usando un altro List> . È sufficiente copiare l’ultimo elemento prima di annullare l’elenco di ripetizioni usando RedoBuffer.Add(Lines.Last()); . Quindi, per ogni comando di ripetizione, è sufficiente aggiungere l’ultimo elemento del buffer di ripristino a Lines e rimuoverlo dal buffer di ripristino. È inoltre necessario cancellare il buffer di ripristino dopo ogni puntatore del mouse verso il basso.
  • Puoi utilizzare DrawLines o DrawCurve base alle tue esigenze. DrawLines disegna una DrawLines , mentre DrawCurve disegna una curva più liscia.

  • Preferisco incapsulare Lines.Count > 0 in una proprietà come bool CanUndo e renderla accessibile da fuori controllo.

  • È solo un esempio e puoi semplicemente estendere la soluzione. Ad esempio, anziché List> puoi creare una class Shape contenente List , LineWidth , LineColor , ecc. LineColor eseguire attività usando List .