先看效果图:
因为公司是做电子白板软件的所以,对InkCanvas的Stroke进行继承,这样既可省去橡皮擦等的开发.
核心是重写DrawCore函数.
DrawEnd 函数是实现笔尾的三角箭头
DrawHead 函数是实现笔头的三角箭头
其实原理也简单,就是使用 PathGeometry 然后设置Pen 的DashStyle
再使用LineSegment 绘制stylusPoint既可。
internal class PathStrokeK : Stroke { private static double[] dashs = new double[] { 5.0, 3.0 }; private static Brush EndBrush = Brushes.Red; private Geometry endGeometry; private static string EndGeometryString = "M 0,0 L {0},{1} L0,{0}z"; private Size endSize; private static Brush HeadBrush = Brushes.Green; private Geometry headGeometry; private static string HeadGeometryString = "M 0,{1} L {0},0 L{0},{0}z"; private Size headSize; private static double Ratio = 5.0; private static double Thickness = 3.0; public PathStrokeK(StylusPointCollection spc) : base(spc) { string source = string.Format(HeadGeometryString, Thickness * Ratio, (Thickness * Ratio) / 2.0); string str2 = string.Format(EndGeometryString, Thickness * Ratio, (Thickness * Ratio) / 2.0); this.headGeometry = Geometry.Parse(source); this.endGeometry = Geometry.Parse(str2); this.headSize = new Size(Thickness * Ratio, Thickness * Ratio); this.endSize = new Size(Thickness * Ratio, Thickness * Ratio); } public void AddPoints(IEnumerable<StylusPoint> stylusPoints) { foreach (StylusPoint point in stylusPoints) { base.StylusPoints.Add(point); } } protected override void DrawCore(DrawingContext dc, DrawingAttributes da) { Brush brush = new SolidColorBrush(da.Color); StylusPointCollection stylusPoints = base.StylusPoints; if ((dashs == null) || (dashs.Length == 0)) { base.DrawCore(dc, da); } else if (stylusPoints.Count > 0) { Pen pen = new Pen { Brush = brush, Thickness = Thickness, DashStyle = new DashStyle(dashs, 0.0), DashCap = PenLineCap.Round, LineJoin = PenLineJoin.Round, MiterLimit = 0.0 }; PathGeometry geometry = new PathGeometry(); PathFigure figure = new PathFigure { StartPoint = (Point)stylusPoints[0], IsClosed = false }; for (int i = 1; i < stylusPoints.Count; i++) { figure.Segments.Add(new LineSegment((Point)stylusPoints[i], true)); } geometry.Figures.Add(figure); dc.DrawGeometry(null, pen, geometry); dc.DrawGeometry(brush, null, new EllipseGeometry((Point)stylusPoints[0], Thickness / 2.0, Thickness / 2.0)); dc.DrawGeometry(brush, null, new EllipseGeometry((Point)stylusPoints[stylusPoints.Count - 1], Thickness / 2.0, Thickness / 2.0)); } if (stylusPoints.Count > 1) { if (this.headGeometry != null) { this.DrawHead(dc, (Point)stylusPoints[0], (Point)stylusPoints[1], HeadBrush); } if (this.endGeometry != null) { this.DrawEnd(dc, (Point)stylusPoints[stylusPoints.Count - 1], (Point)stylusPoints[stylusPoints.Count - 2], EndBrush); } } } private void DrawEnd(DrawingContext dc, Point p0, Point p1, Brush b) { Matrix matrix = new Matrix(); matrix.Translate(-this.endSize.Width / 2.0, -this.endSize.Height / 2.0); Vector vector = new Vector(1.0, 0.0); Vector vector2 = Point.Subtract(p0, p1); matrix.Rotate(Vector.AngleBetween(vector, vector2)); matrix.Translate(p0.X, p0.Y); Geometry geometry = Geometry.Combine(this.endGeometry, Geometry.Empty, GeometryCombineMode.Union, new MatrixTransform(matrix)); dc.DrawGeometry(b, null, geometry); } private void DrawHead(DrawingContext dc, Point p0, Point p1, Brush b) { Matrix matrix = new Matrix(); matrix.Translate(-this.headSize.Width / 2.0, -this.headSize.Height / 2.0); Vector vector = new Vector(1.0, 0.0); Vector vector2 = Point.Subtract(p1, p0); matrix.Rotate(Vector.AngleBetween(vector, vector2)); matrix.Translate(p0.X, p0.Y); Geometry geometry = Geometry.Combine(this.headGeometry, Geometry.Empty, GeometryCombineMode.Union, new MatrixTransform(matrix)); dc.DrawGeometry(b, null, geometry); } }