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; private double RatioRate { get; set; } = 1; /// /// 鼠标按下时的坐标 /// 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; RatioRate = ClientRect.Width > 0 ? ClientRect.Height / ClientRect.Width : 1; return true; } return false; } public void test(double x) { ClientRect = new Rect(ClientRect.X , ClientRect.Y , ClientRect.Width * x, ClientRect.Height * x); } /// /// 鼠标松开时调用,存储鼠标状态 /// 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; } public Rect GetClientRect() { return ClientRect; } /// /// 获取当前命中状态 /// 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)moveVector.X; int yMove = -(int)moveVector.Y; switch (HitControlType) { case PointControlType.LeftTop: { double X = centerPoint.X - xMove; double Width = SnapClientRect.Width + SnapClientRect.X - centerPoint.X + xMove; if (Width < 10) { Width = 10; X = SnapClientRect.X + SnapClientRect.Width - 10; } double Y = centerPoint.Y - yMove; double Height = SnapClientRect.Height + SnapClientRect.Y - centerPoint.Y + yMove; if (Height < 10) { Height = 10; Y = SnapClientRect.Y + SnapClientRect.Height - 10; } ClientRect = new Rect(new Point(X, Y), new Size(Width, Height)); } break; case PointControlType.LeftMiddle: { double X = centerPoint.X - xMove; double Width = SnapClientRect.Width + SnapClientRect.X - centerPoint.X + xMove; if (Width < 10) { Width = 10; X = SnapClientRect.X + SnapClientRect.Width - 10; } double Y = SnapClientRect.Top; double Height = SnapClientRect.Height; ClientRect = new Rect(new Point(X, Y), new Size(Width, Height)); } break; case PointControlType.LeftBottom: { double X = centerPoint.X - xMove; double Width = SnapClientRect.Width + SnapClientRect.X - centerPoint.X + xMove; if (Width < 10) { Width = 10; X = SnapClientRect.X + SnapClientRect.Width - 10; } double Y = SnapClientRect.Y; double Height = SnapClientRect.Height + SnapClientRect.Y - centerPoint.Y - yMove; if (Height < 10) { Height = 10; Y = SnapClientRect.Y; } ClientRect = new Rect(new Point(X, Y), new Size(Width, Height)); } break; case PointControlType.MiddlBottom: { double X = SnapClientRect.Left; double Width = SnapClientRect.Width; double Y = SnapClientRect.Y; double Height = SnapClientRect.Height + SnapClientRect.Y - centerPoint.Y - yMove; if (Height < 10) { Height = 10; Y = SnapClientRect.Y; } ClientRect = new Rect(new Point(X, Y), new Size(Width, Height)); } break; case PointControlType.RightBottom: { double X = SnapClientRect.Left; double Width = SnapClientRect.Width + SnapClientRect.X - centerPoint.X - xMove; if (Width < 10) { Width = 10; } double Y = SnapClientRect.Y; double Height = SnapClientRect.Height + SnapClientRect.Y - centerPoint.Y - yMove; if (Height < 10) { Height = 10; } ClientRect = new Rect(new Point(X, Y), new Size(Width, Height)); } break; case PointControlType.RightMiddle: { double X = SnapClientRect.Left; double Width = SnapClientRect.Width + SnapClientRect.X - centerPoint.X - xMove; if (Width < 10) { Width = 10; } double Y = SnapClientRect.Top; double Height = SnapClientRect.Height; ClientRect = new Rect(new Point(X, Y), new Size(Width, Height)); } break; case PointControlType.RightTop: { double X = SnapClientRect.X; double Width = SnapClientRect.Width + SnapClientRect.X - centerPoint.X - xMove; if (Width < 10) { Width = 10; X = SnapClientRect.X; } double Y = centerPoint.Y - yMove; double Height = SnapClientRect.Height + SnapClientRect.Y - centerPoint.Y + yMove; if (Height < 10) { Height = 10; Y = SnapClientRect.Y + SnapClientRect.Height - 10; } ClientRect = new Rect(new Point(X, Y), new Size(Width, Height)); } break; case PointControlType.MiddleTop: { double X = SnapClientRect.X; double Width = SnapClientRect.Width; double Y = centerPoint.Y - yMove; double Height = SnapClientRect.Height + SnapClientRect.Y - centerPoint.Y + yMove; if (Height < 10) { Height = 10; Y = SnapClientRect.Y + SnapClientRect.Height - 10; } ClientRect = new Rect(new Point(X, Y), new Size(Width, Height)); } break; case PointControlType.Rotate: break; case PointControlType.Body: { moveVector = mousePoint - MouseDownPoint; ClientRect = new Rect(SnapClientRect.Left - xMove, SnapClientRect.Top - yMove, SnapClientRect.Width, SnapClientRect.Height); } break; default: return false; } if (ClientRect.X < MaxRect.X) { ClientRect = new Rect (MaxRect.X, ClientRect.Y, ClientRect.Width, ClientRect.Height); } if (ClientRect.Y < MaxRect.Y) { ClientRect = new Rect (ClientRect.X, MaxRect.Y, ClientRect.Width, ClientRect.Height); } if (ClientRect.Right > MaxRect.Right) { ClientRect = new Rect (MaxRect.Right - ClientRect.Width, ClientRect.Y, ClientRect.Width, ClientRect.Height); } if (ClientRect.Bottom > MaxRect.Bottom) { ClientRect = new Rect (ClientRect.X, MaxRect.Bottom - ClientRect.Height, ClientRect.Width, ClientRect.Height); } Console.WriteLine(ClientRect.ToString()); MoveOffset = new Point(ClientRect.X - SnapClientRect.X, ClientRect.Y - SnapClientRect.Y); return true; } } }