|
@@ -0,0 +1,487 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using System.Windows;
|
|
|
+using System.Windows.Media;
|
|
|
+
|
|
|
+namespace PDF_Office.CustomControl.ScanViewControl
|
|
|
+{
|
|
|
+
|
|
|
+ public class DrawRect : DrawingVisual
|
|
|
+ {
|
|
|
+ private DrawingContext DrawDC { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 当前点的类型
|
|
|
+ /// </summary>
|
|
|
+ public enum PointControlType
|
|
|
+ {
|
|
|
+ None = -1,
|
|
|
+ LeftTop,
|
|
|
+ LeftMiddle,
|
|
|
+ LeftBottom,
|
|
|
+ MiddlBottom,
|
|
|
+ RightBottom,
|
|
|
+ RightMiddle,
|
|
|
+ RightTop,
|
|
|
+ MiddleTop,
|
|
|
+ Rotate,
|
|
|
+ Body
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 当前点击命中的控制点
|
|
|
+ /// </summary>
|
|
|
+ public PointControlType HitControlType { get; private set; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 矩形框周围可拖拽点的坐标集合
|
|
|
+ /// </summary>
|
|
|
+ private List<Point> ControlPoints { get; set; } = new List<Point>();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 当前内部缓存的矩形
|
|
|
+ /// </summary>
|
|
|
+ private Rect ClientRect { get; set; } = new Rect(0, 0, 0, 0);
|
|
|
+ private Rect MaxRect { get; set; } = new Rect(0, 0, 0, 0);
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 按下时缓存的矩形
|
|
|
+ /// </summary>
|
|
|
+ private Rect SnapClientRect { get; set; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 覆盖填充色
|
|
|
+ /// </summary>
|
|
|
+ public SolidColorBrush FillBrush { get; set; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 边框线画刷
|
|
|
+ /// </summary>
|
|
|
+ public SolidColorBrush BorderBrush { get; set; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 边框线画笔
|
|
|
+ /// </summary>
|
|
|
+ public Pen LinePen { get; set; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 控制点画笔
|
|
|
+ /// </summary>
|
|
|
+ public Pen PointPen { get; set; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 控制点大小
|
|
|
+ /// </summary>
|
|
|
+ public int PointSize { get; set; } = 6;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 绘制线段长度(点)
|
|
|
+ /// </summary>
|
|
|
+ public int ClipLine { get; set; } = 8;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 鼠标按下时的坐标
|
|
|
+ /// </summary>
|
|
|
+ public Point MouseDownPoint { get; set; }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 移动偏移量
|
|
|
+ /// </summary>
|
|
|
+ private Point MoveOffset { get; set; } = new Point(0, 0);
|
|
|
+
|
|
|
+ public DrawRect()
|
|
|
+ {
|
|
|
+ FillBrush = new SolidColorBrush(Color.FromArgb(0x01, 0x00, 0x00, 0x00));
|
|
|
+ PointPen = new Pen(new SolidColorBrush(Color.FromRgb(0xC0, 0x4C, 0xF8)), 4);
|
|
|
+ LinePen = new Pen(Brushes.White, 2);
|
|
|
+ LinePen.DashStyle = DashStyles.Dash;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void SetMaxRect(Rect rect)
|
|
|
+ {
|
|
|
+ MaxRect = rect;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 开始绘制
|
|
|
+ /// </summary>
|
|
|
+ public void OpenDraw()
|
|
|
+ {
|
|
|
+ if (DrawDC == null)
|
|
|
+ {
|
|
|
+ DrawDC = RenderOpen();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 关闭绘制
|
|
|
+ /// </summary>
|
|
|
+ private void CloseDraw()
|
|
|
+ {
|
|
|
+ DrawDC?.Close();
|
|
|
+ DrawDC = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 清除绘制内容
|
|
|
+ /// </summary>
|
|
|
+ public void ClearDraw()
|
|
|
+ {
|
|
|
+ OpenDraw();
|
|
|
+ CloseDraw();
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 绘制所需的内容
|
|
|
+ /// </summary>
|
|
|
+ public void Draw()
|
|
|
+ {
|
|
|
+ Dispatcher.Invoke(() =>
|
|
|
+ {
|
|
|
+ CalcControlPoint();
|
|
|
+ OpenDraw();
|
|
|
+ DrawDC?.DrawRectangle(FillBrush, LinePen, ClientRect);
|
|
|
+ DrawClipMode();
|
|
|
+ CloseDraw();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 鼠标按下时调用,存储鼠标状态
|
|
|
+ /// </summary>
|
|
|
+ public bool MouseLeftButtonDown(Point clickPoint, CustomPanel custom)
|
|
|
+ {
|
|
|
+ HitControlType = PointControlType.None;
|
|
|
+ HitTestResult hitResult = VisualTreeHelper.HitTest(custom, clickPoint);
|
|
|
+ if (hitResult != null)
|
|
|
+ {
|
|
|
+ MouseDownPoint = clickPoint;
|
|
|
+ MoveOffset = new Point(0, 0);
|
|
|
+ HitControlType = GetHitControlIndex(clickPoint);
|
|
|
+ if (HitControlType == PointControlType.None)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ SnapClientRect = ClientRect;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 鼠标松开时调用,存储鼠标状态
|
|
|
+ /// </summary>
|
|
|
+ public bool MouseLeftButtonUp(Point clickPoint)
|
|
|
+ {
|
|
|
+ if (HitControlType != PointControlType.None)
|
|
|
+ {
|
|
|
+ Draw();
|
|
|
+ MoveOffset = new Point(0, 0);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ MoveOffset = new Point(0, 0);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 鼠标移动时调用,根据按下时的状态,更新内部矩形
|
|
|
+ /// </summary>
|
|
|
+ public bool MouseMove(Point clickPoint)
|
|
|
+ {
|
|
|
+ if (HitControlType != PointControlType.None)
|
|
|
+ {
|
|
|
+ if (CalcHitPointMove(clickPoint))
|
|
|
+ {
|
|
|
+ Draw();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 设置矩形用于绘制
|
|
|
+ /// </summary>
|
|
|
+ public void SetRect(Rect newRect)
|
|
|
+ {
|
|
|
+ ClientRect = newRect;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 获取当前命中状态
|
|
|
+ /// </summary>
|
|
|
+ private PointControlType GetHitControlIndex(Point clickPoint)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < ControlPoints.Count; i++)
|
|
|
+ {
|
|
|
+ Point checkPoint = ControlPoints[i];
|
|
|
+ Rect checkRect = new Rect(checkPoint.X - PointSize, checkPoint.Y - PointSize, PointSize * 2, PointSize * 2);
|
|
|
+ if (checkRect.Contains(clickPoint))
|
|
|
+ {
|
|
|
+ return (PointControlType)i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (ClientRect.Contains(clickPoint))
|
|
|
+ {
|
|
|
+ return PointControlType.Body;
|
|
|
+ }
|
|
|
+
|
|
|
+ return PointControlType.None;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 绘制框上的可选点
|
|
|
+ /// </summary>
|
|
|
+ private void DrawClipMode()
|
|
|
+ {
|
|
|
+ GeometryGroup geometryGroup = new GeometryGroup();
|
|
|
+
|
|
|
+ //四个角的可选点样式绘制
|
|
|
+ for (int i = 0; i <= 6; i += 2)
|
|
|
+ {
|
|
|
+ PathGeometry pathGeometry = GetCornerGeometry(ControlPoints[i], (PointControlType)i);
|
|
|
+ if (pathGeometry != null)
|
|
|
+ {
|
|
|
+ geometryGroup.Children.Add(pathGeometry);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //四条边的可选点样式绘制
|
|
|
+ for (int i = 1; i <= 7; i += 2)
|
|
|
+ {
|
|
|
+ LineGeometry lineGeometry = GetMiddleGeometry(ControlPoints[i], (PointControlType)i);
|
|
|
+ if (lineGeometry != null)
|
|
|
+ {
|
|
|
+ geometryGroup.Children.Add(lineGeometry);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (geometryGroup.Children.Count > 0)
|
|
|
+ {
|
|
|
+ DrawDC?.DrawGeometry(null, PointPen, geometryGroup);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 计算所有点的坐标
|
|
|
+ /// </summary>
|
|
|
+ private void CalcControlPoint()
|
|
|
+ {
|
|
|
+ ControlPoints.Clear();
|
|
|
+ int centerX = (int)(ClientRect.Left + ClientRect.Right) / 2;
|
|
|
+ int centerY = (int)(ClientRect.Top + ClientRect.Bottom) / 2;
|
|
|
+
|
|
|
+ ControlPoints.Add(new Point(ClientRect.Left, ClientRect.Top));
|
|
|
+ ControlPoints.Add(new Point(ClientRect.Left, centerY));
|
|
|
+ ControlPoints.Add(new Point(ClientRect.Left, ClientRect.Bottom));
|
|
|
+ ControlPoints.Add(new Point(centerX, ClientRect.Bottom));
|
|
|
+ ControlPoints.Add(new Point(ClientRect.Right, ClientRect.Bottom));
|
|
|
+ ControlPoints.Add(new Point(ClientRect.Right, centerY));
|
|
|
+ ControlPoints.Add(new Point(ClientRect.Right, ClientRect.Top));
|
|
|
+ ControlPoints.Add(new Point(centerX, ClientRect.Top));
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 根据类型生成对应四个角的Path路径
|
|
|
+ /// </summary>
|
|
|
+ private PathGeometry GetCornerGeometry(Point cornerPoint, PointControlType pointType)
|
|
|
+ {
|
|
|
+ PathGeometry pathGeometry = new PathGeometry();
|
|
|
+ PathFigure figure = new PathFigure();
|
|
|
+ PolyLineSegment polyLine = new PolyLineSegment();
|
|
|
+ figure.Segments.Add(polyLine);
|
|
|
+ pathGeometry.Figures.Add(figure);
|
|
|
+
|
|
|
+ Point startPoint = new Point(0, 0), middlePoint = new Point(0, 0), endPoint = new Point(0, 0);
|
|
|
+ int MinLine = (int)Math.Min(Math.Min(ClipLine, ClientRect.Width), ClientRect.Height);
|
|
|
+
|
|
|
+ switch (pointType)
|
|
|
+ {
|
|
|
+ case PointControlType.LeftTop:
|
|
|
+ {
|
|
|
+ startPoint = new Point(cornerPoint.X, cornerPoint.Y + MinLine);
|
|
|
+ middlePoint = cornerPoint;
|
|
|
+ endPoint = new Point(cornerPoint.X + MinLine, cornerPoint.Y);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.LeftBottom:
|
|
|
+ {
|
|
|
+ startPoint = new Point(cornerPoint.X, cornerPoint.Y - MinLine);
|
|
|
+ middlePoint = cornerPoint;
|
|
|
+ endPoint = new Point(cornerPoint.X + MinLine, cornerPoint.Y);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.RightBottom:
|
|
|
+ {
|
|
|
+ startPoint = new Point(cornerPoint.X - MinLine, cornerPoint.Y);
|
|
|
+ middlePoint = cornerPoint;
|
|
|
+ endPoint = new Point(cornerPoint.X, cornerPoint.Y - MinLine);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.RightTop:
|
|
|
+ {
|
|
|
+ startPoint = new Point(cornerPoint.X - MinLine, cornerPoint.Y);
|
|
|
+ middlePoint = cornerPoint;
|
|
|
+ endPoint = new Point(cornerPoint.X, cornerPoint.Y + MinLine);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ figure.StartPoint = startPoint;
|
|
|
+ polyLine.Points.Add(middlePoint);
|
|
|
+ polyLine.Points.Add(endPoint);
|
|
|
+
|
|
|
+ return pathGeometry;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 根据类型生成对应四条边的Path路径
|
|
|
+ /// </summary>
|
|
|
+ private LineGeometry GetMiddleGeometry(Point middlePoint, PointControlType pointType)
|
|
|
+ {
|
|
|
+ LineGeometry lineGeometry = new LineGeometry();
|
|
|
+ Point startPoint = new Point(0, 0), endPoint = new Point(0, 0);
|
|
|
+ int MinLine = (int)Math.Min(Math.Min(ClipLine * 2, ClientRect.Width), ClientRect.Height) / 2;
|
|
|
+
|
|
|
+ switch (pointType)
|
|
|
+ {
|
|
|
+ case PointControlType.LeftMiddle:
|
|
|
+ case PointControlType.RightMiddle:
|
|
|
+ {
|
|
|
+ startPoint.X = middlePoint.X;
|
|
|
+ startPoint.Y = middlePoint.Y - MinLine;
|
|
|
+ endPoint.X = middlePoint.X;
|
|
|
+ endPoint.Y = middlePoint.Y + MinLine;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.MiddleTop:
|
|
|
+ case PointControlType.MiddlBottom:
|
|
|
+ {
|
|
|
+ startPoint.X = middlePoint.X - MinLine;
|
|
|
+ startPoint.Y = middlePoint.Y;
|
|
|
+ endPoint.X = middlePoint.X + MinLine;
|
|
|
+ endPoint.Y = middlePoint.Y;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ lineGeometry.StartPoint = startPoint;
|
|
|
+ lineGeometry.EndPoint = endPoint;
|
|
|
+
|
|
|
+ return lineGeometry;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 计算当前命中点是否需要绘制。为True则更新内部矩形
|
|
|
+ /// </summary>
|
|
|
+ private bool CalcHitPointMove(Point mousePoint)
|
|
|
+ {
|
|
|
+ if (HitControlType == PointControlType.None)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ Point centerPoint = new Point((SnapClientRect.Right + SnapClientRect.Left) / 2, (SnapClientRect.Bottom + SnapClientRect.Top) / 2);
|
|
|
+ Vector moveVector = mousePoint - centerPoint;
|
|
|
+
|
|
|
+ int xMove = (int)Math.Abs(moveVector.X);
|
|
|
+ int yMove = xMove;
|
|
|
+
|
|
|
+ switch (HitControlType)
|
|
|
+ {
|
|
|
+ case PointControlType.LeftTop:
|
|
|
+ {
|
|
|
+ ClientRect = new Rect(new Point(centerPoint.X - xMove, centerPoint.Y - yMove), new Size(xMove * 2, yMove * 2));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.LeftMiddle:
|
|
|
+ {
|
|
|
+ ClientRect = new Rect(new Point(centerPoint.X - xMove, SnapClientRect.Top), new Size(xMove * 2, SnapClientRect.Height));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.LeftBottom:
|
|
|
+ {
|
|
|
+ ClientRect = new Rect(new Point(centerPoint.X - xMove, centerPoint.Y - yMove), new Size(xMove * 2, yMove * 2));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.MiddlBottom:
|
|
|
+ {
|
|
|
+ yMove = (int)Math.Abs(moveVector.Y);
|
|
|
+ ClientRect = new Rect(SnapClientRect.Left, centerPoint.Y - yMove, SnapClientRect.Width, yMove * 2);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.RightBottom:
|
|
|
+ {
|
|
|
+ ClientRect = new Rect(new Point(centerPoint.X - xMove, centerPoint.Y - yMove), new Size(xMove * 2, yMove * 2));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.RightMiddle:
|
|
|
+ {
|
|
|
+ ClientRect = new Rect(new Point(centerPoint.X - xMove, SnapClientRect.Top), new Size(xMove * 2, SnapClientRect.Height));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.RightTop:
|
|
|
+ {
|
|
|
+ ClientRect = new Rect(new Point(centerPoint.X - xMove, centerPoint.Y - yMove), new Size(xMove * 2, yMove * 2));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.MiddleTop:
|
|
|
+ {
|
|
|
+ yMove = (int)Math.Abs(moveVector.Y);
|
|
|
+ ClientRect = new Rect(SnapClientRect.Left, centerPoint.Y - yMove, SnapClientRect.Width, yMove * 2);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case PointControlType.Rotate:
|
|
|
+ break;
|
|
|
+ case PointControlType.Body:
|
|
|
+ {
|
|
|
+ moveVector = mousePoint - MouseDownPoint;
|
|
|
+ ClientRect = new Rect(SnapClientRect.Left + moveVector.X, SnapClientRect.Y + moveVector.Y, SnapClientRect.Width, SnapClientRect.Height);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ //if (ClientRect.X < MaxRect.X)
|
|
|
+ //{
|
|
|
+ // ClientRect = new Rect
|
|
|
+ // (MaxRect.X,
|
|
|
+ // ClientRect.Y,
|
|
|
+ // (ClientRect.Width - ClientRect.X) + MaxRect.X,
|
|
|
+ // ClientRect.Height);
|
|
|
+ //}
|
|
|
+ //if (ClientRect.Y < MaxRect.Y)
|
|
|
+ //{
|
|
|
+ // ClientRect = new Rect
|
|
|
+ // (ClientRect.X,
|
|
|
+ // MaxRect.Y,
|
|
|
+ // ClientRect.Width,
|
|
|
+ // (ClientRect.Height - ClientRect.Y) + MaxRect.Y);
|
|
|
+ //}
|
|
|
+ //if (ClientRect.Width> MaxRect.Width)
|
|
|
+ //{
|
|
|
+ // ClientRect = new Rect
|
|
|
+ // (MaxRect.Width - (ClientRect.Width - ClientRect.X),
|
|
|
+ // ClientRect.Y,
|
|
|
+ // MaxRect.Width,
|
|
|
+ // ClientRect.Height);
|
|
|
+ //}
|
|
|
+ //if (ClientRect.Height>MaxRect.Height)
|
|
|
+ //{
|
|
|
+ // ClientRect = new Rect
|
|
|
+ // (ClientRect.X,
|
|
|
+ // MaxRect.Height-(ClientRect.Height- ClientRect.Y),
|
|
|
+ // ClientRect.Width,
|
|
|
+ // MaxRect.Height);
|
|
|
+ //}
|
|
|
+
|
|
|
+ MoveOffset = new Point(ClientRect.X - SnapClientRect.X, ClientRect.Y - SnapClientRect.Y);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|