none
InkCanvas 画图,选中问题,求Bob Bao老大解答 RRS feed

  • 问题

  • 你好,版主

    我根据您给的思路和代码,在做一个画图工具

    其中碰到这样的问题

    http://t0.qpic.cn/mblogpic/7d28652492f1d7f8bcd4/2000

    这是一张图,不好意思,我不知道怎样在论坛中贴出图片.

    这张图片是一个六边形,用InkCanvas的Select模式去选中它的时候,却发现,选中的框框有错位,没有把整个六边形包住

     topLeft = new Point(StylusPoints[0].X, StylusPoints[0].Y);
          centerLeft = new Point(StylusPoints[2].X, StylusPoints[2].Y);
          bottomLeft = new Point(StylusPoints[4].X, StylusPoints[4].Y);
          bottomRight = new Point(StylusPoints[5].X, StylusPoints[5].Y);
          centerRight = new Point(StylusPoints[3].X, StylusPoints[3].Y);
          topRight = new Point(StylusPoints[1].X, StylusPoints[1].Y);
    
          pathGeomery = new PathGeometry();
    
          PathSegmentCollection pathCollection = new PathSegmentCollection();
    
          pathCollection.Add(new LineSegment(centerLeft, true));
          pathCollection.Add(new LineSegment(bottomLeft, true));
          pathCollection.Add(new LineSegment(bottomRight, true));
          pathCollection.Add(new LineSegment(centerRight, true));
          pathCollection.Add(new LineSegment(topRight, true));
    
    
          PathFigure pathFigure = new PathFigure();
          pathFigure.IsClosed = true;
          pathFigure.StartPoint = topLeft;
          pathFigure.Segments = pathCollection;
    
    
          PathFigureCollection pathFigureCollection = new PathFigureCollection();
          pathFigureCollection.Add(pathFigure);
    
          pathGeomery.Figures = pathFigureCollection;
    
    
    
          drawingContext.DrawGeometry(backgroundBrush(BgColorHelper), pen, pathGeomery);
    

    这是绘制六边形的坐标代码.不知道是否有问题


    Hero
    2011年7月18日 14:56

答案

  • 选择框的范围是根据你鼠标点下的原始位置和抬起的最终位置决定的,所以这两点就确定了一个范围,这个范围就是选择框的范围。

    我想知道的是你是如何根据鼠标移动获得你的6个点的? 因为鼠标的点下拖动瞬间只能够产生两个实际点,根据计算我们还可以生成其他一些点,比如你的六边形,就可以这么生成:

     

     private void inkcanvas_MouseMove(object sender, MouseEventArgs e)
     {
      if (IsDrawing)
      {
      currentPoint = e.GetPosition((IInputElement)sender);
      StylusPointCollection pts = new StylusPointCollection();
    
      pts.Add(new StylusPoint(
       (currentPoint.X - mouseLeftDownPoint.X) / 3 + mouseLeftDownPoint.X,
       mouseLeftDownPoint.Y)); // LeftTopPoint
    
      pts.Add(new StylusPoint(
       (currentPoint.X - mouseLeftDownPoint.X) * 2 / 3 + mouseLeftDownPoint.X,
       mouseLeftDownPoint.Y)); // RightTopPoint
    
      pts.Add(new StylusPoint(
       mouseLeftDownPoint.X, 
       (currentPoint.Y - mouseLeftDownPoint.Y) / 2 + mouseLeftDownPoint.Y)); // LeftCenterPoint
    
      pts.Add(new StylusPoint(
       currentPoint.X,
       (currentPoint.Y - mouseLeftDownPoint.Y) / 2 + mouseLeftDownPoint.Y)); // RightCenterPoint
    
      pts.Add(new StylusPoint(
       (currentPoint.X - mouseLeftDownPoint.X) / 3 + mouseLeftDownPoint.X,
       currentPoint.Y)); // LeftBottomPoint
    
      pts.Add(new StylusPoint(
       (currentPoint.X - mouseLeftDownPoint.X) * 2 / 3 + mouseLeftDownPoint.X,
       currentPoint.Y)); // RightBottomPoint
    
      if (st != null)
       inkcanvas.Strokes.Remove(st);
      st = new customStroke(pts);
    
      st.DrawingAttributes.Color = Colors.Red;
      inkcanvas.Strokes.Add(st);
      }
    

    然后老规矩,你可以下载我的例子看下:https://skydrive.live.com/?cid=51b2fdd068799d15#!/?cid=51b2fdd068799d15&sc=documents&uc=1&id=51B2FDD068799D15%21762

     

     

    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年7月19日 11:13
    版主
  • Hi,

    我今天早上看到你的代码我就知道昨天我说错了, 选择框的范围是由鼠标点下的原始位置和抬起的最终位置决定的,不是由这个点集合中最左上和右下的位置决定。

    所以我昨天的写的那个例子是可以正常运行的,而你的代码,右中的点超出了鼠标最终抬起位置。因为我是基于鼠标滑过范围三等分得到的六边形四个顶点,而你是二等分,所以势必右侧的中点出了范围。

     

    你下载我的例子看下吧,应该有所启发。

     

    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年7月20日 2:38
    版主

全部回复

  • 选择框的范围是根据你鼠标点下的原始位置和抬起的最终位置决定的,所以这两点就确定了一个范围,这个范围就是选择框的范围。

    我想知道的是你是如何根据鼠标移动获得你的6个点的? 因为鼠标的点下拖动瞬间只能够产生两个实际点,根据计算我们还可以生成其他一些点,比如你的六边形,就可以这么生成:

     

     private void inkcanvas_MouseMove(object sender, MouseEventArgs e)
     {
      if (IsDrawing)
      {
      currentPoint = e.GetPosition((IInputElement)sender);
      StylusPointCollection pts = new StylusPointCollection();
    
      pts.Add(new StylusPoint(
       (currentPoint.X - mouseLeftDownPoint.X) / 3 + mouseLeftDownPoint.X,
       mouseLeftDownPoint.Y)); // LeftTopPoint
    
      pts.Add(new StylusPoint(
       (currentPoint.X - mouseLeftDownPoint.X) * 2 / 3 + mouseLeftDownPoint.X,
       mouseLeftDownPoint.Y)); // RightTopPoint
    
      pts.Add(new StylusPoint(
       mouseLeftDownPoint.X, 
       (currentPoint.Y - mouseLeftDownPoint.Y) / 2 + mouseLeftDownPoint.Y)); // LeftCenterPoint
    
      pts.Add(new StylusPoint(
       currentPoint.X,
       (currentPoint.Y - mouseLeftDownPoint.Y) / 2 + mouseLeftDownPoint.Y)); // RightCenterPoint
    
      pts.Add(new StylusPoint(
       (currentPoint.X - mouseLeftDownPoint.X) / 3 + mouseLeftDownPoint.X,
       currentPoint.Y)); // LeftBottomPoint
    
      pts.Add(new StylusPoint(
       (currentPoint.X - mouseLeftDownPoint.X) * 2 / 3 + mouseLeftDownPoint.X,
       currentPoint.Y)); // RightBottomPoint
    
      if (st != null)
       inkcanvas.Strokes.Remove(st);
      st = new customStroke(pts);
    
      st.DrawingAttributes.Color = Colors.Red;
      inkcanvas.Strokes.Add(st);
      }
    

    然后老规矩,你可以下载我的例子看下:https://skydrive.live.com/?cid=51b2fdd068799d15#!/?cid=51b2fdd068799d15&sc=documents&uc=1&id=51B2FDD068799D15%21762

     

     

    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年7月19日 11:13
    版主
  •  void GetHexagon(StylusPointCollection pts, Action<StylusPointCollection> exec)
      {
       centerLeftPoint.X = topLeftPoint.X - (movePoint.X - topLeftPoint.X) / 2;
       centerLeftPoint.Y = topLeftPoint.Y + (movePoint.Y - topLeftPoint.Y) / 2;
    
       bottomLeftPoint.X = movePoint.X - (movePoint.X - topLeftPoint.X);
       bottomLeftPoint.Y = movePoint.Y;
    
       bottomRightPoint = movePoint;
    
       centerRightPoint.X = movePoint.X + (movePoint.X - topLeftPoint.X) / 2;
       centerRightPoint.Y = topLeftPoint.Y + (movePoint.Y - topLeftPoint.Y) / 2;
    
       topRightPoint.X = movePoint.X;
       topRightPoint.Y = topLeftPoint.Y;
    
       pts.Add(new StylusPoint(topLeftPoint.X, topLeftPoint.Y));
       pts.Add(new StylusPoint(topRightPoint.X, topRightPoint.Y));
       pts.Add(new StylusPoint(centerLeftPoint.X, centerLeftPoint.Y));
       pts.Add(new StylusPoint(centerRightPoint.X, centerRightPoint.Y));
       pts.Add(new StylusPoint(bottomLeftPoint.X, bottomLeftPoint.Y));
       pts.Add(new StylusPoint(bottomRightPoint.X, bottomRightPoint.Y));
    
       exec(pts);
    
      }
    


    这个就是我根据两个点 获得其他点的方法,我们的画法 有什么区别么,想不通 啊....

     


    Hero
    2011年7月20日 1:11
  • Hi,

    我今天早上看到你的代码我就知道昨天我说错了, 选择框的范围是由鼠标点下的原始位置和抬起的最终位置决定的,不是由这个点集合中最左上和右下的位置决定。

    所以我昨天的写的那个例子是可以正常运行的,而你的代码,右中的点超出了鼠标最终抬起位置。因为我是基于鼠标滑过范围三等分得到的六边形四个顶点,而你是二等分,所以势必右侧的中点出了范围。

     

    你下载我的例子看下吧,应该有所启发。

     

    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年7月20日 2:38
    版主
  • 原来如此

    非常感谢

    知道原理了

    Bob bao


    Hero
    2011年7月21日 4:27
  • 你好,Bob Bao

    我直接复制了你的算法,放到了我的画法里,结果Select的时候,还是超出来了,我贴出来你看看

     

    //这是画的方法
    
     protected override void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes)
      {
       if (drawingContext == null)
       {
        throw new ArgumentNullException("drawingContext");
       }
       if (null == drawingAttributes)
       {
        throw new ArgumentNullException("drawingAttributes");
       }
    
       Pen pen = new Pen
       {
        StartLineCap = PenLineCap.Round,
        EndLineCap = PenLineCap.Round,
        Brush = new SolidColorBrush(ObjectColor),
        Thickness = LineWidth
       };
    
       topLeft = new Point(StylusPoints[0].X, StylusPoints[0].Y);
       centerLeft = new Point(StylusPoints[2].X, StylusPoints[2].Y);
       bottomLeft = new Point(StylusPoints[4].X, StylusPoints[4].Y);
       bottomRight = new Point(StylusPoints[5].X, StylusPoints[5].Y);
       centerRight = new Point(StylusPoints[3].X, StylusPoints[3].Y);
       topRight = new Point(StylusPoints[1].X, StylusPoints[1].Y);
    
       pathGeomery = new PathGeometry();
    
       PathSegmentCollection pathCollection = new PathSegmentCollection();
    
       pathCollection.Add(new LineSegment(centerLeft, true));
       pathCollection.Add(new LineSegment(bottomLeft, true));
       pathCollection.Add(new LineSegment(bottomRight, true));
       pathCollection.Add(new LineSegment(centerRight, true));
       pathCollection.Add(new LineSegment(topRight, true));
    
    
       PathFigure pathFigure = new PathFigure();
       pathFigure.IsClosed = true;
       pathFigure.StartPoint = topLeft;
       pathFigure.Segments = pathCollection;
    
    
       PathFigureCollection pathFigureCollection = new PathFigureCollection();
       pathFigureCollection.Add(pathFigure);
    
       pathGeomery.Figures = pathFigureCollection;
    
    
    
       drawingContext.DrawGeometry(backgroundBrush(BgColorHelper), pen, pathGeomery);
      }
    

     

     

     

    //这是获得图形坐标
    
     public override void OnMouseDown(DrawingInkCanvas drawingInkCanvas, System.Windows.Input.MouseButtonEventArgs e)
      {
       topLeftPoint = e.GetPosition((IInputElement)drawingInkCanvas);
      }
    
      public override void OnMouseMove(DrawingInkCanvas drawingInkCanvas, System.Windows.Input.MouseEventArgs e)
      {
       currentPoint = e.GetPosition((IInputElement)drawingInkCanvas);
       if (e.LeftButton == MouseButtonState.Pressed)
       {
        StylusPointCollection pts = new StylusPointCollection();
        GetHexagon(pts, (s) =>
        {
         if (drawHexagon != null)
          drawingInkCanvas.Strokes.Remove(drawHexagon);
    
         DrawingAttributes drawingAttributes = new DrawingAttributes
         {
          Color = Colors.Black,
          StylusTip = StylusTip.Ellipse,
          IgnorePressure = true,
          FitToCurve = true
         };
    
         drawHexagon = new DrawHexagon(s, drawingAttributes);
    
         drawHexagon.BgColorHelper = drawingInkCanvas.ObjectBackground;
         drawHexagon.ObjectColor = drawingInkCanvas.ObjectColor;
         drawHexagon.LineWidth = drawingInkCanvas.LineWidth;
         drawingInkCanvas.Strokes.Add(drawHexagon);
         drawingInkCanvas.HistoryStroke = drawHexagon;
    
        }
        );
       }
      }
    
    void GetHexagon(StylusPointCollection pts, Action<StylusPointCollection> exec)
      {
    
       pts.Add(new StylusPoint(
        (currentPoint.X - topLeftPoint.X) / 3 + topLeftPoint.X,
        topLeftPoint.Y)); // LeftTopPoint
    
       pts.Add(new StylusPoint(
        (currentPoint.X - topLeftPoint.X) * 2 / 3 + topLeftPoint.X,
        topLeftPoint.Y)); // RightTopPoint
    
       pts.Add(new StylusPoint(
        topLeftPoint.X,
        (currentPoint.Y - topLeftPoint.Y) / 2 + topLeftPoint.Y)); // LeftCenterPoint
    
       pts.Add(new StylusPoint(
        currentPoint.X,
        (currentPoint.Y - topLeftPoint.Y) / 2 + topLeftPoint.Y)); // RightCenterPoint
    
       pts.Add(new StylusPoint(
        (currentPoint.X - topLeftPoint.X) / 3 + topLeftPoint.X,
        currentPoint.Y)); // LeftBottomPoint
    
       pts.Add(new StylusPoint(
        (currentPoint.X - topLeftPoint.X) * 2 / 3 + topLeftPoint.X,
        currentPoint.Y)); // RightBottomPoint
    
       exec(pts);
    
      }
    

    我看了一下,没有区别啊...为什么Select的时候,就是有偏差呢

     


    Hero
    2011年7月23日 1:53
  • 我刚才又试了一下

    选中比如Triangle三角形的时候,拖动选中状态时出现的框

    比如我拖动的是右下角,使其变大,我发现它左上角的坐标点也会改变

    就是这个原因使我产生偏差,不知道这是怎么出现的.

    我画矩形的时候就不会有这个问题

     

    这个就是我的例子,ToolTriangle 里面是事件 和获得坐标的类

    DrawTriangle 是具体组成图形的画法

    我用了你的坐标组合方法,发现select的时候,还是不对

    您看一下三角形和六边形就可以了

     

    http://dl.dbank.com/c03jj072fm


    Hero

    2011年7月23日 7:51
  • OK, 我看到现象了,周末两天在家没上来看,今天花点时间给你看一下,我会在你新开的帖子里面给你回复的: http://social.microsoft.com/Forums/zh-CN/wpfzhchs/thread/901223da-72ef-4732-9939-94cfe4c1604e
    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年7月25日 2:10
    版主
  • 谢谢Bob Bao

    我找到原因了,折腾了我两天

     

    原来使用画自定义的Stroke 不能设置它的DrawingAttributes,否则会导致不规则形状的选中的偏差,

    具体是什么原理还不知道,至少肯定了是DrawingAttributes属性造成的.

     

    现在OK了


    Hero
    2011年7月25日 2:40