diff --git a/InkCanvasForClass/MainWindow_cs/MW_FloatingBarIcons.cs b/InkCanvasForClass/MainWindow_cs/MW_FloatingBarIcons.cs index f177619..6a2fd54 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_FloatingBarIcons.cs @@ -738,6 +738,7 @@ namespace Ink_Canvas { #region 主要的工具按鈕事件 private async void SymbolIconCursor_Click(object sender, RoutedEventArgs e) { + if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing(); if (currentMode != 0) { ImageBlackboard_MouseUp(null, null); } else { @@ -764,6 +765,8 @@ namespace Ink_Canvas { ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent); if (sender == Cursor_Icon && lastBorderMouseDownObject != Cursor_Icon) return; + if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing(); + // 切换前自动截图保存墨迹 if (inkCanvas.Strokes.Count > 0 && inkCanvas.Strokes.Count > Settings.Automation.MinimumAutomationStrokeNumber) @@ -854,6 +857,8 @@ namespace Ink_Canvas { ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent); if (sender == Pen_Icon && lastBorderMouseDownObject != Pen_Icon) return; + if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing(); + if (Pen_Icon.Background == null || StackPanelCanvasControls.Visibility == Visibility.Collapsed) { inkCanvas.EditingMode = InkCanvasEditingMode.Ink; @@ -947,6 +952,8 @@ namespace Ink_Canvas { ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent); if (sender == SymbolIconSelect && lastBorderMouseDownObject != SymbolIconSelect) return; + if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing(); + if (SelectedMode == ICCToolsEnum.LassoMode) { if (SelectionPopupV2.IsOpen == false) { var transform = SymbolIconSelect.TransformToVisual(Main_Grid); @@ -976,6 +983,8 @@ namespace Ink_Canvas { ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent); if (sender == Eraser_Icon && lastBorderMouseDownObject != Eraser_Icon) return; + if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing(); + forceEraser = true; forcePointEraser = true; @@ -1057,6 +1066,8 @@ namespace Ink_Canvas { ((Panel)lastBorderMouseDownObject).Background = new SolidColorBrush(Colors.Transparent); if (sender == EraserByStrokes_Icon && lastBorderMouseDownObject != EraserByStrokes_Icon) return; + if (ShapeDrawingV2Layer.IsInShapeDrawingMode) ShapeDrawingV2Layer.EndShapeDrawing(); + forceEraser = true; forcePointEraser = false; diff --git a/InkCanvasForClass/MainWindow_cs/MW_InkCanvas.cs b/InkCanvasForClass/MainWindow_cs/MW_InkCanvas.cs index f258213..23e7b4e 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_InkCanvas.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_InkCanvas.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics; using System.Reflection; using System.Windows; using System.Windows.Controls; @@ -19,6 +20,11 @@ namespace Ink_Canvas { public static Guid StrokeShapeTypeGuid = new Guid("6537b29c-557f-487f-800b-cb30a8f1de78"); public static Guid StrokeIsShapeGuid = new Guid("40eff5db-9346-4e42-bd46-7b0eb19d0018"); + public StylusPointCollection RawStylusPointCollection { get; set; } + + public MainWindow.ShapeDrawingHelper.ArrowLineConfig ArrowLineConfig { get; set; } = + new MainWindow.ShapeDrawingHelper.ArrowLineConfig(); + // 自定义的墨迹渲染 protected override void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes) { @@ -29,7 +35,14 @@ namespace Ink_Canvas { } if ((int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DashedLine || - (int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DottedLine) { + (int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.Line || + (int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DottedLine || + (int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.ArrowOneSide || + (int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.ArrowTwoSide) { + if (StylusPoints.Count < 2) { + base.DrawCore(drawingContext, drawingAttributes); + return; + } StreamGeometry geometry = new StreamGeometry(); var pts = new List(this.StylusPoints.ToPoints()); using (StreamGeometryContext ctx = geometry.Open()) { @@ -42,8 +55,37 @@ namespace Ink_Canvas { DashCap = PenLineCap.Round, StartLineCap = PenLineCap.Round, EndLineCap = PenLineCap.Round, - DashStyle = (int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DottedLine ? DashStyles.Dot : DashStyles.Dash }; + if ((int)this.GetPropertyData(StrokeShapeTypeGuid) != (int)MainWindow.ShapeDrawingType.Line && + (int)this.GetPropertyData(StrokeShapeTypeGuid) != (int)MainWindow.ShapeDrawingType.ArrowOneSide && + (int)this.GetPropertyData(StrokeShapeTypeGuid) != (int)MainWindow.ShapeDrawingType.ArrowTwoSide) + pen.DashStyle = (int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.DottedLine ? DashStyles.Dot : DashStyles.Dash; + + if ((int)this.GetPropertyData(StrokeShapeTypeGuid) == (int)MainWindow.ShapeDrawingType.ArrowOneSide) { + pts = new List(this.StylusPoints.ToPoints()); + RawStylusPointCollection = StylusPoints.Clone(); + double w = ArrowLineConfig.ArrowWidth, h = ArrowLineConfig.ArrowHeight; + var theta = Math.Atan2(pts[0].Y - pts[1].Y, pts[0].X - pts[1].X); + var sint = Math.Sin(theta); + var cost = Math.Cos(theta); + var pointList = new List { + new Point(pts[0].X, pts[0].Y), + new Point(pts[1].X, pts[1].Y), + new Point(pts[1].X + (w * cost - h * sint), pts[1].Y + (w * sint + h * cost)), + new Point(pts[1].X, pts[1].Y), + new Point(pts[1].X + (w * cost + h * sint), pts[1].Y - (h * cost - w * sint)), + }; + StylusPoints = new StylusPointCollection(pointList); + var _pts = new List(this.StylusPoints.ToPoints()); + using (StreamGeometryContext ctx = geometry.Open()) { + ctx.BeginFigure(_pts[0], false , false); + _pts.RemoveAt(0); + ctx.PolyLineTo(_pts,true, true); + } + drawingContext.DrawGeometry(new SolidColorBrush(DrawingAttributes.Color),pen, geometry); + return; + + } drawingContext.DrawGeometry(new SolidColorBrush(Colors.Transparent),pen, geometry); } diff --git a/InkCanvasForClass/MainWindow_cs/MW_SelectionGestures.cs b/InkCanvasForClass/MainWindow_cs/MW_SelectionGestures.cs index 384ff18..c6b0acb 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_SelectionGestures.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_SelectionGestures.cs @@ -538,7 +538,7 @@ namespace Ink_Canvas { } if (final_w >= 1 && final_h >= 1) { - // 此處還需要修改行為,讓其能夠縮放到1x1; + // TODO 此處還需要修改行為,讓其能夠縮放到1x1; StrokeSelectionBorder.Width = final_w >=1 ? final_w : 1; StrokeSelectionBorder.Height = final_h >=1 ? final_h : 1; diff --git a/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawing.cs b/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawing.cs index 3df5d4e..b92210a 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawing.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawing.cs @@ -1590,7 +1590,7 @@ namespace Ink_Canvas { ShapeDrawingPopupV2.IsOpen = false; }; ShapeDrawingV2.ShapeSelectedEvent += (sender, args) => { - ShapeDrawingV2Layer.StartShapeDrawing(args.Type); + ShapeDrawingV2Layer.StartShapeDrawing(args.Type, args.Name); }; } diff --git a/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawingCore.cs b/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawingCore.cs index 2d56f7b..b153e01 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawingCore.cs +++ b/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawingCore.cs @@ -12,7 +12,9 @@ namespace Ink_Canvas { // 线 if (type == MainWindow.ShapeDrawingType.Line || type == MainWindow.ShapeDrawingType.DashedLine || - type == MainWindow.ShapeDrawingType.DottedLine) { + type == MainWindow.ShapeDrawingType.DottedLine || + type == MainWindow.ShapeDrawingType.ArrowOneSide || + type == MainWindow.ShapeDrawingType.ArrowTwoSide) { if (pts.Count != 2) throw new Exception("传入的点个数不是2个"); var stk = new IccStroke(new StylusPointCollection() { new StylusPoint(pts[0].X, pts[0].Y), @@ -25,5 +27,35 @@ namespace Ink_Canvas { return new StrokeCollection(); } + + public static class ShapeDrawingHelper { + + /// + /// 根据给定的两个点计算角度 + /// + /// + /// + /// + public static double CaculateRotateAngleByGivenTwoPoints(Point firstPoint, Point lastPoint) { + var vec1 = new double[] { + lastPoint.X - firstPoint.X , + lastPoint.Y - firstPoint.Y + }; + var vec_base = new double[] { 0, firstPoint.Y }; + var cosine = (vec_base[0] * vec1[0] + vec_base[1] * vec1[1]) / + (Math.Sqrt(Math.Pow(vec_base[0],2) + Math.Pow(vec_base[1],2)) * + Math.Sqrt(Math.Pow(vec1[0],2) + Math.Pow(vec1[1],2))); + var angle = Math.Acos(cosine); + var isIn2And3Quadrant = lastPoint.X <= firstPoint.X; + var rotateAngle = Math.Round(180 + 180 * (angle / Math.PI) * (isIn2And3Quadrant ? 1 : -1), 0); + return rotateAngle; + } + + public class ArrowLineConfig { + public int ArrowWidth { get; set; } = 20; + public int ArrowHeight { get; set; } = 7; + } + + } } } diff --git a/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawingLayer.xaml b/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawingLayer.xaml index a97bb2d..a29ca2e 100644 --- a/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawingLayer.xaml +++ b/InkCanvasForClass/MainWindow_cs/MW_ShapeDrawingLayer.xaml @@ -8,7 +8,9 @@ xmlns:helpers="clr-namespace:Ink_Canvas.Helpers" mc:Ignorable="d" d:DesignWidth="1920" d:DesignHeight="1080"> - + + + @@ -24,7 +26,7 @@ -