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;
}
}
}