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