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; } /// /// 当前点的类型 /// public enum PointControlType { None = -1, LeftTop, LeftMiddle, LeftBottom, MiddlBottom, RightBottom, RightMiddle, RightTop, MiddleTop, Rotate, Body } /// /// 当前点击命中的控制点 /// public PointControlType HitControlType { get; private set; } /// /// 矩形框周围可拖拽点的坐标集合 /// private List ControlPoints { get; set; } = new List(); /// /// 当前内部缓存的矩形 /// private Rect ClientRect { get; set; } = new Rect(0, 0, 0, 0); private Rect MaxRect { get; set; } = new Rect(0, 0, 0, 0); /// /// 按下时缓存的矩形 /// private Rect SnapClientRect { get; set; } /// /// 覆盖填充色 /// public SolidColorBrush FillBrush { get; set; } /// /// 边框线画刷 /// public SolidColorBrush BorderBrush { get; set; } /// /// 边框线画笔 /// public Pen LinePen { get; set; } /// /// 控制点画笔 /// public Pen PointPen { get; set; } /// /// 控制点大小 /// public int PointSize { get; set; } = 6; /// /// 绘制线段长度(点) /// public int ClipLine { get; set; } = 8; /// /// 鼠标按下时的坐标 /// public Point MouseDownPoint { get; set; } /// /// 移动偏移量 /// 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; } /// /// 开始绘制 /// public void OpenDraw() { if (DrawDC == null) { DrawDC = RenderOpen(); } } /// /// 关闭绘制 /// private void CloseDraw() { DrawDC?.Close(); DrawDC = null; } /// /// 清除绘制内容 /// public void ClearDraw() { OpenDraw(); CloseDraw(); } /// /// 绘制所需的内容 /// public void Draw() { Dispatcher.Invoke(() => { CalcControlPoint(); OpenDraw(); DrawDC?.DrawRectangle(FillBrush, LinePen, ClientRect); DrawClipMode(); CloseDraw(); }); } /// /// 鼠标按下时调用,存储鼠标状态 /// 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; } /// /// 鼠标松开时调用,存储鼠标状态 /// public bool MouseLeftButtonUp(Point clickPoint) { if (HitControlType != PointControlType.None) { Draw(); MoveOffset = new Point(0, 0); return true; } MoveOffset = new Point(0, 0); return false; } /// /// 鼠标移动时调用,根据按下时的状态,更新内部矩形 /// public bool MouseMove(Point clickPoint) { if (HitControlType != PointControlType.None) { if (CalcHitPointMove(clickPoint)) { Draw(); return true; } } return false; } /// /// 设置矩形用于绘制 /// public void SetRect(Rect newRect) { ClientRect = newRect; } /// /// 获取当前命中状态 /// 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; } /// /// 绘制框上的可选点 /// 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); } } /// /// 计算所有点的坐标 /// 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)); } /// /// 根据类型生成对应四个角的Path路径 /// 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; } /// /// 根据类型生成对应四条边的Path路径 /// 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; } /// /// 计算当前命中点是否需要绘制。为True则更新内部矩形 /// 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; } } }