Im trying to implement undo and redo using gdi in wpf. I am not very familiar with gdi and my attempts have been unsuccessful.
On my mouse move event I draw like this:
using (var g = Gdi.Graphics.FromImage(tempBitmap))
{
g.SmoothingMode = Gdi.Drawing2D.SmoothingMode.AntiAlias;
g.CompositingQuality = Gdi.Drawing2D.CompositingQuality.HighQuality;
if (currentTool == "eraserBrush")
g.CompositingMode = Gdi.Drawing2D.CompositingMode.SourceCopy;
else
g.CompositingMode = Gdi.Drawing2D.CompositingMode.SourceOver;
g.DrawLine(pen,p0,p1);
}
// Copy GDI bitmap to WPF bitmap.
var hbmp = tempBitmap.GetHbitmap();
var options = BitmapSizeOptions.FromEmptyOptions();
this.writableBmp.Source = Imaging.CreateBitmapSourceFromHBitmap(hbmp,
IntPtr.Zero, Int32Rect.Empty, options);
// Redraw the WPF Image control.
this.writableBmp.InvalidateMeasure();
this.writableBmp.InvalidateVisual();
tempBitmap
is a Gdi bitmap
On my mouse up event I push tempBitmap to a stack, and on my undo event I pop from the stack and do the following:
if (paintStack.Count <= 1)
return;
paintStack.Pop();
tempBitmap = paintStack.Peek();
var hbmp = paintStack.Peek().GetHbitmap();
var options = BitmapSizeOptions.FromEmptyOptions();
this.writableBmp.Source = Imaging.CreateBitmapSourceFromHBitmap(hbmp,
IntPtr.Zero, Int32Rect.Empty, options);
// Redraw the WPF Image control.
this.writableBmp.InvalidateMeasure();
this.writableBmp.InvalidateVisual();
But hitting undo does nothing. I believe I am pushing and poping the wrong item to the stack. I think I should be doing the gdi graphics, and not the tempbitmap, but I am not sure how.
Edit:----------------------------------------------------
I took a different approach but it seems its a dead end. I created a stack for the history of actions. Pushed an action to the stack after every stroke, and pop'd after an undo. Then on my undo event I just redraw everything minus the last action. This works fine if I am just drawing lines and simple stuff with gdi. However, I also have a tool that draws images, and a lot of them. This approach is way too slow.
The above demonstrates only three levels of undo, the more I draw the slower the undo is (obviously has more actions to read from the stack and redraw).
Theres got to be a way to make this work by just taking a snapshot of the current canvas. Any ideas guys?