Windows 8:如何使用内置的墨水function撤消和重做墨水?

基于microsoft的简化墨迹示例,我在我的应用程序中实现了墨迹代码: http : //code.msdn.microsoft.com/windowsapps/Input-simplified-ink-sample-11614bbf/view/SourceCode

首先,我创建了一个保存操作数据的类(draw / delete / clear),如下所示:

public enum eInkOperation { Draw, Delete, None } public class InkOperation { public InkStroke Stroke { get; set; } //requred for drawing from undo public eInkOperation Operation { get; set; } public InkOperation(InkStroke stroke, eInkOperation inkOperation) { Stroke = stroke.Clone(); //needs to be cloned for AddStroke to work Operation = inkOperation; } } 

然后我为撤消墨水操作创建了一个堆栈,为重做操作创建了一个堆栈

 //stack of normal operations Stack _undoStack = new Stack(); //Undo action will pop them off of the undo stack and push them onto the redo stack Stack _redoStack = new Stack(); 

当用户撤消笔划时,我将其推到重做堆栈上并使用以下方法从inkmanager中删除它:

 private void RedoStackPush(InkOperation inkOperation) { inkOperation.Stroke = inkOperation.Stroke.Clone(); _redoStack.Push(inkOperation); } private void DeleteStroke(InkStroke stroke) { stroke = inkManager.GetStrokes().Last(); stroke.Selected = true; inkManager.DeleteSelected(); } 

然后,当用户单击重做时,笔划将从重做堆栈弹出并使用此方法绘制:

 private void DrawStroke(InkStroke stroke) { if (stroke!=null) { inkManager.Mode = InkManipulationMode.Inking; inkManager.AddStroke(stroke); } renderer.Clear(); //this renderer object smooths the strokes //and adds them as Path objects to the desired control (Grid, etc) renderer.AddInk(inkManager.GetStrokes()); } 

这一切都有效,并且笔划显示在网格上。 但是,当我尝试擦除新重绘的笔划时,我得到以下exception:

 AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 

这发生在:

 public void PointerMoved(PointerRoutedEventArgs e) { try { var pointerPoint = e.GetCurrentPoint(_inkingArea); var pointerEventType = InkHelpers.GetPointerEventType(e); if (pointerId == (int)pointerPoint.PointerId) { switch (inkManager.Mode) { case InkManipulationMode.Inking: case InkManipulationMode.Selecting: //process intermediate points var intermediatePoints = e.GetIntermediatePoints(_inkingArea); for (int i = intermediatePoints.Count - 1; i >= 0; i--) { inkManager.ProcessPointerUpdate(intermediatePoints[i]); } //live rendering renderer.UpdateLiveRender(pointerPoint); break; case InkManipulationMode.Erasing: //check if something has been erased //in erase mode InkManager.ProcessPointerUpdate returns an invalidate rectangle: //if it is not degenerate, something has been erased //in erase mode don't bother processing intermediate points //If inkManager.ProcessPointerUpdate throws an exception, it crashes the app regardless of any catches Rect invalidateRect = (Rect)inkManager.ProcessPointerUpdate(e.GetCurrentPoint(_inkingArea)); if (invalidateRect.Height != 0 && invalidateRect.Width != 0) { //we don't know what has been erased so we clear the render //and add back all the ink saved in the ink manager renderer.Clear(); var remainingStrokes = inkManager.GetStrokes(); renderer.AddInk(remainingStrokes); } break; default: break; } } } catch (Exception) { } } 

在这一行:

 Rect invalidateRect = (Rect)inkManager.ProcessPointerUpdate(e.GetCurrentPoint(_inkingArea)); 

我认为问题在于向墨水管理器添加笔划的过程。 我尝试创建一个新笔划,甚至从InkStrokeinheritance以使其可自定义但InkStroke类是密封的,它没有构造函数。 唯一一个是我发现复制它是为了做inkStroke.Clone()。 但是,当尝试重绘已删除的墨迹时,甚至会出现问题(撤消已删除的笔划)。

我尝试使用最少量的代码尽可能清楚地解决这个问题以避免混淆,所以如果它不够,请告诉我。

同样在这个问题中,我专注于撤消绘制动作。 撤消删除操作(甚至“全部清除”操作)有其自身的一组问题,因为我无法复制InkStroke对象。

提前感谢您的时间和考虑。

从MSDN查看此主题,可能会有所帮助。