Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You can declare a private Image field and save image state to it for use in undo, using <a href="http://www.devlake.com/design-patterns/memento" rel="nofollow">Memento Design Pattern</a> to save and load object "image" state is the best practice, take a loot at it.</p> <p>However instead of one undo/redo operation a better solution is to implement <strong>multi-undo/redo</strong> strategy as the following:</p> <ul> <li>Declare two stacks one for undo and the other for redo:</li> <li>When <strong>undo</strong> pop the action "image" or "image state" from undo stack and push it to the redo stack.</li> <li>When <strong>redo</strong> pop the action "image" or "image state" from redo stack and push it to the undo stack.</li> </ul> <p>Example:</p> <pre><code>private Stack&lt;Image&gt; _undoStack = new Stack&lt;Image&gt;(); private Stack&lt;Image&gt; _redoStack = new Stack&lt;Image&gt;(); private readonly object _undoRedoLocker = new object(); private void Undo() { lock (_undoRedoLocker) { if (_undoStack.Count &gt; 0) { _redoStack.Push(_undoStack.Pop()); //OnUndo(); pictureBox1.Image = _redoStack.Peek(); pictureBox1.Refresh(); } } } private void Redo() { lock (_undoRedoLocker) { if (_redoStack.Count &gt; 0) { _undoStack.Push(_redoStack.Pop()); //OnRedo(); pictureBox1.Image = _undoStack.Peek(); pictureBox1.Refresh(); } } } //And whenever image need to be modified, add it to the undo stack first and then modify it private void UpdateImageData(Action updateImage) { lock (_undoRedoLocker) { _undoStack.Push(pictureBox1.Image);//image); try { //manipulate the image here. updateImage(); } catch { _undoStack.Pop();//because of exception remove the last added frame from stack throw; } } } private void pictureBox1_MouseClick(object sender, EventArgs e) { UpdateImageData(delegate() { rect.Width = 0; rect.Height = 0; pictureBox1.Invalidate(); int radius = 10; //Set the number of pixel you want to use here //Calculate the numbers based on radius int x0 = Math.Max(e.X - (radius / 2), 0), y0 = Math.Max(e.Y - (radius / 2), 0), x1 = Math.Min(e.X + (radius / 2), pictureBox1.Width), y1 = Math.Min(e.Y + (radius / 2), pictureBox1.Height); Bitmap bm = pictureBox1.Image as Bitmap; //Get the bitmap (assuming it is stored that way) for (int ix = x0; ix &lt; x1; ix++) { for (int iy = y0; iy &lt; y1; iy++) { bm.SetPixel(ix, iy, Color.Black); //Change the pixel color, maybe should be relative to bitmap } } pictureBox1.Refresh(); //Force refresh } } </code></pre> <ul> <li>Whenever user want to undo "for instance presses Ctrl+Z" on the form just call Undo();</li> <li>Whenever user want to redo on the form just call Redo();</li> </ul> <p>Note: I didn't test the above code but it should be working probably, if you find any issue leave a comment</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload