我试图在wpf中使用gdi实现撤消和重做。我对gdi不是很熟悉,我的尝试也没有成功。
在我的鼠标移动事件中,我画得像这样:
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
是Gdi位图
在我的鼠标注册事件中,我将tempBitmap推送到堆栈,在我的撤销事件中,我从堆栈弹出并执行以下操作:
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();
但是点击撤消什么都不做。我相信我正在推送并将错误的项目弹出到堆栈中。我想我应该做gdi图形,而不是tempbitmap,但我不确定如何。
编辑:--------------------------------------------- -------
我采取了不同的方法,但它似乎是一个死胡同。我为行动历史创建了一个堆栈。在每次击打后将动作推到堆叠中,并在撤消后弹出。然后在我的撤消事件中,我只是重绘所有内容减去最后一个动作。如果我只是用gdi绘制线条和简单的东西,这可以正常工作。但是,我也有一个绘制图像的工具,以及很多图像。这种方法太慢了。 上面只展示了三个级别的撤消,我绘制得越多,撤消越慢(显然有更多动作从堆栈中读取并重绘)。
Theres必须通过拍摄当前画布的快照来实现这项工作。任何想法的家伙?