1、InkCanvas类。
实现画板需要用到InkCanvas。一般情况下不需任何代码就可以在上面画线了。
如果需要设置画笔颜色、笔尖大小等就需要设置DefaultDrawingAttributes,例如:
DrawingAttributes attributes = new DrawingAttributes(); attributes.Color = Colors.Black; attributes.Height = 50; attributes.Width = 50; attributes.FitToCurve = true;
2、在InkCanvas上画直线
方法:在StrokeCollected事件中进行修正,StrokeCollected事件在单个笔画结束后触发。可以取出笔画的起始点(BeginPoint)和终点(EndPoint),然后使用该两点新建笔画即可。
代码如下:
private void InkCanvas_StrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e) { if (e.Stroke.StylusPoints.Count > 1) { UpdateLine(e.Stroke); } } private void UpdateLine(Stroke currentStroke) { StylusPoint beginPoint = currentStroke.StylusPoints[0];//起始点 StylusPoint endPoint = currentStroke.StylusPoints.Last();//终点 packageCanvas.Strokes.Remove(currentStroke);//移除原来的笔画 List<Point> pointList = new List<Point>(); pointList.Add(new Point(beginPoint.X, beginPoint.Y)); pointList.Add(new Point(endPoint.X, endPoint.Y)); StylusPointCollection point = new StylusPointCollection(pointList); Stroke stroke = new Stroke(point);//用两点实现笔画 stroke.DrawingAttributes = packageCanvas.DefaultDrawingAttributes.Clone(); InkCanvas.Strokes.Add(stroke); }
3、在InkCanvas上画直虚线
方法:还是跟上面一样取起始点和终点,不同点是:在两点间绘制许多点,然后将相邻的两点连接成一个笔画。这样一个直虚线变好了。
代码如下:
private void UpdateLine(Stroke currentStroke) { InkCanvas.Strokes.Remove(currentStroke);//移除原来笔画 int dotTime = 0;
int intervalLen=6;//步长 double lineLen = Math.Sqrt(Math.Pow(beginPoint.X - endPoint.X, 2) + Math.Pow(beginPoint.Y - endPoint.Y, 2));//线的长度 Point currentPoint = new Point(beginPoint.X, beginPoint.Y); double relativaRate = Math.Abs(endPoint.Y - beginPoint.Y) * 1.0 / Math.Abs(endPoint.X - beginPoint.X); double angle = Math.Atan(relativaRate) * 180 / Math.PI;//直线的角度大小,无需考虑正负 int xOrientation = endPoint.X > beginPoint.X ? 1 : -1;//判断新生成点的X轴方向 int yOrientation = endPoint.Y > beginPoint.Y ? 1 : -1; if (lineLen < intervalLen) { return; } while (dotTime * intervalLen < lineLen) { double x = currentPoint.X + dotTime * intervalLen * Math.Cos(angle * Math.PI / 180) * xOrientation; double y = currentPoint.Y + dotTime * intervalLen * Math.Sin(angle * Math.PI / 180) * yOrientation; List<Point> pL = new List<Point>(); pL.Add(new Point(x, y)); x += intervalLen * Math.Cos(angle * Math.PI / 180) * xOrientation; y += intervalLen * Math.Sin(angle * Math.PI / 180) * yOrientation; pL.Add(new Point(x, y)); StylusPointCollection spc = new StylusPointCollection(pL);//相邻两点作为一个笔画 Stroke stroke = new Stroke(spc); stroke.DrawingAttributes = packageCanvas.DefaultDrawingAttributes.Clone(); InkCanvas.Strokes.Add(stroke); dotTime+=2; } }
4、在InkCanvas上画弯虚线
方法:在InkCanvas_StrokeCollected方法的参数属性中可以获得线上的点的坐标。
2)生成StylusPointCollection collection=currentStroke.StylusPoints,用来存放当前笔画的所有点
2)生成一个List<Point> allPointList,用来存放最终生成的点
2) 将起始点=》allPointList,起始点-》currentPoint
3)遍历collection,IF currentPoint与找到点(item)的距离==步长 THEN item=>allPointList;item=>currentPoint,取下一个点
IF currentPoint与找到点(item)的距离>步长 THEN 在currentPoint与item线上找到一个点,使得与currentPoint的距离=步长,item=>allPointList;item=>currentPoint,继续当前点
IF currentPoint与找到点(item)的距离<步长 取下一个点
代码如下:
private void UpdateLine(Stroke currentStroke) { InkCanvas.Strokes.Remove(currentStroke); StylusPointCollection collection = currentStroke.StylusPoints; List<Point> allSelectedPoint = new List<Point>(); Point currentPoint = new Point(collection[0].X, collection[0].Y); allSelectedPoint.Add(currentPoint); for (int i = 0; i < collection.Count; i++) { var item = collection[i]; double length = Math.Sqrt(Math.Pow(item.X - currentPoint.X, 2) + Math.Pow(item.Y - currentPoint.Y, 2)); if ((int)(length + 0.5) == (int)intervalLen || length == intervalLen) { currentPoint = new Point(item.X, item.Y); allSelectedPoint.Add(currentPoint); } else if (length > intervalLen) { double relativaRate = Math.Abs(item.Y - currentPoint.Y) * 1.0 / Math.Abs(item.X - currentPoint.X); double angle = Math.Atan(relativaRate) * 180 / Math.PI; int xOrientation = item.X > currentPoint.X ? 1 : -1; int yOrientation = item.Y > currentPoint.Y ? 1 : -1; double x = currentPoint.X + intervalLen * Math.Cos(angle * Math.PI / 180) * xOrientation; double y = currentPoint.Y + intervalLen * Math.Sin(angle * Math.PI / 180) * yOrientation; currentPoint = new Point(x, y); allSelectedPoint.Add(currentPoint); i--;//很重要,继续当前点 } } for (int j = 0; j < allSelectedPoint.Count; j++) { List<Point> p = new List<Point>(); p.Add(allSelectedPoint[j]); if (j < allSelectedPoint.Count - 1) { j++; } p.Add(allSelectedPoint[j]); StylusPointCollection spc = new StylusPointCollection(p); Stroke stroke = new Stroke(spc); InkCanvas.Strokes.Add(stroke); } }
以上是测试过的代码,不足之处是:只能在当前笔画完成后在进行修正,因为代码写在InkCanvas_StrokeCollected中。