none
调用stroke.GetEraseResult方法以后怎么才能将Stroke对象删除干净? RRS feed

  • 问题

  • 我的实现方法是首先在可以在FrameworkElement上面自由书写,书写完成的笔迹保存在FrameworkElement中的stroke对象中,然后我调用stroke的GetEraseResult方法擦除笔迹,将擦除以后的笔迹再转化到新FrameworkElement对象的stroke中,并在界面上显示出来。但是为什么删除不干净?尤其是沿着一条线的轨迹擦除时,会留下一个一个的点,这是为什么?

    例子地址:https://skydrive.live.com/redir.aspx?cid=8f125a6da8d15aee&resid=8F125A6DA8D15AEE!114

    擦除的基本代码:

     

        /// <summary>
        /// 板擦对象
        /// </summary>
        public class EraserItem : FrameworkElement 
        {
            /// <summary>
            /// 
            /// </summary>
            public Canvas Owner
            {
                get { return _owner; }
            }
            #region 内部EraserItemVisual对象
            /// <summary>
            /// 内部Visual
            /// </summary>
            protected class EraserItemVisual : DrawingVisual
            {
                /// <summary>
                /// 
                /// </summary>
                public EraserItemVisual()
                {
    
                }
                /// <summary>
                /// 
                /// </summary>
                /// <param name="point"></param>
                public void AddPoint(Point point)
                {
                    DrawingContext dc = this.RenderOpen();
                    Pen pen = new Pen(Brushes.Black, 1);
                    dc.DrawEllipse(null, pen, point, 40, 40);
                    dc.Close();
                }
            }
            #endregion
            private VisualCollection _collection;
            private EraserItemVisual _visual;
            private Canvas _owner;
            /// <summary>
            /// 
            /// </summary>
            /// <param name="point"></param>
            /// <param name="owner"></param>
            public EraserItem( Point point, Canvas owner)
            { 
                _collection = new VisualCollection(this);
                _visual = new EraserItemVisual();
                _collection.Add(_visual);
                _owner = owner;
                _owner.Children.Add(this);
                _visual.AddPoint(point); 
            }
            /// <summary>
            /// 
            /// </summary>
            /// <param name="point"></param>
            /// <param name="owner"></param>
            public EraserItem(StylusPoint point, Canvas owner)
                : this(point.ToPoint(), owner)
            {
            }
            /// <summary>
            /// 
            /// </summary>
            /// <param name="point"></param>
            public void AddPoint(Point point)
            {
                _visual.AddPoint(point);
                EllipseStylusShape shape = new EllipseStylusShape(80, 80);
                this.EraserStroke(point, shape);
            }
            /// <summary>
            /// 绘制完成
            /// </summary>
            public void EraserStrokeComplete()
            {
                _visual = null; 
                this._collection.Clear();
                this._owner.Children.Remove(this);   
            }
            /// <summary>
            /// 擦除笔画
            /// </summary>
            /// <param name="point"></param>
            /// <param name="shape"></param>
            private void EraserStroke(Point point,StylusShape shape)
            {
                 for (int i = 0; i < _owner.Children.Count; i++)
                {
                    NormalPenItem line = _owner.Children[i] as NormalPenItem;
                    if (line == null) { continue; }
                    double left = Canvas.GetLeft(line);
                    double top = Canvas.GetTop(line);
                    TranslateTransform py = new TranslateTransform();
                    py.X = -left;
                    py.Y = -top;
                    Point pt = py.Transform(point);
                    StrokeCollection sc = line.GetEraseResult(new Point[] { pt }, shape);---->这里就是调用了Stroke对象的GetEraseResult方法
                    if (sc.Count == 1) { continue; }
                    _owner.Children.Remove(line);
                    foreach (Stroke stroke in sc)
                    {
                        line.SplitByStroke(stroke.Clone(),left,top);----->将拆分以后的对象重新加入到Canvas 中
                    }
                }
            }
    
            protected override Visual GetVisualChild(int index)
            {
                return _collection[index];
            }
    
            protected override int VisualChildrenCount
            {
                get
                {
                    return _collection.Count;
                }
            }
        }
    


     

     


    2011年10月24日 6:28

答案

  • 我的测试结果是,擦除动作缓慢时,几乎就不能擦除了。

    还有就是擦除内容的实际区域有偏差。

    我看了你的代码,现在只能说问题范围有所缩小,主要集中在 line.GetEraseResult(new Point[] { pt }, shape); 的第一个参数。

    根据文档: http://msdn.microsoft.com/zh-cn/library/ms590560.aspx eraserPath是分割 Stroke 的路径。光传入一个点是无法决定你的分割路径和方向的,所以擦除就会有随机的现象。

    我觉得你的设计应该是要根据用户擦除动作的一系列点来组成一个分割路径,然后去分割已有图形。

    Sincerely,

     


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 张柱敏 2011年10月27日 1:31
    2011年10月25日 7:51
    版主
  • 非常感谢!其实是我的代码写错了。

     

                    StrokeCollection sc = line.GetEraseResult(new Point[] { pt }, shape);---->这里就是调用了Stroke对象的GetEraseResult方法
                    if (sc.Count == 1) { continue; }----》这里应该先判断擦除的范围是否和笔画相交,然后再调用.GetEraseResult方法,去掉这一句
    
                    _owner.Children.Remove(line);

     

    2011年10月27日 1:31

全部回复

  • 我的测试结果是,擦除动作缓慢时,几乎就不能擦除了。

    还有就是擦除内容的实际区域有偏差。

    我看了你的代码,现在只能说问题范围有所缩小,主要集中在 line.GetEraseResult(new Point[] { pt }, shape); 的第一个参数。

    根据文档: http://msdn.microsoft.com/zh-cn/library/ms590560.aspx eraserPath是分割 Stroke 的路径。光传入一个点是无法决定你的分割路径和方向的,所以擦除就会有随机的现象。

    我觉得你的设计应该是要根据用户擦除动作的一系列点来组成一个分割路径,然后去分割已有图形。

    Sincerely,

     


    Bob Bao [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • 已标记为答案 张柱敏 2011年10月27日 1:31
    2011年10月25日 7:51
    版主
  • 非常感谢!其实是我的代码写错了。

     

                    StrokeCollection sc = line.GetEraseResult(new Point[] { pt }, shape);---->这里就是调用了Stroke对象的GetEraseResult方法
                    if (sc.Count == 1) { continue; }----》这里应该先判断擦除的范围是否和笔画相交,然后再调用.GetEraseResult方法,去掉这一句
    
                    _owner.Children.Remove(line);

     

    2011年10月27日 1:31