using System.ComponentModel; using System.Drawing.Drawing2D; using System.Drawing.Text; using System.Windows.Forms; using XKRS.UI.Helper; using System.Text.Json; using System.Security.Cryptography.X509Certificates; using System.Xml.Serialization; using System.Drawing; using Sunny.UI; using Sunny.UI.Win32; using OpenCvSharp; using OpenCvSharp.Extensions; using Point = System.Drawing.Point; namespace XKRS.UI { public partial class Canvas : UserControl, INotifyPropertyChanged { #region 变量通知 public event PropertyChangedEventHandler? PropertyChanged; private void NotifyPropertyChanged(string name) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(name)); } } #endregion [DisplayName("方向键移动间距")] [Description("按下方向键时,选中的缺陷可以向对应的方向平移,该值设置按下一次方向键缺陷图片的移动距离,单位:像素")] public float MoveStep { get; set; } = 5f; [DisplayName("允许选中缺陷")] [Description("鼠标单击时,是否允许选中图上绘制的缺陷,允许选中时才可以对缺陷进行操作")] public bool AllowSelectDefect { get; set; } = true; private Keys _keyLastPressed = Keys.None; /// /// 顺序查找已选中的缺陷 /// private Defect? _selectedDefect; public Defect SelectedDefect { get { _selectedDefect = DefectList.FirstOrDefault(d => d.Selected); return _selectedDefect; } } /// /// 整体缩放比例 /// private float _wholeScale; public float WholeScale { get { return _wholeScale; } set { _wholeScale = value; WholeScaleChange(); } } /// /// 横向缩放比列 /// private float _xScale; public float XScale { get { return _xScale; } set { _xScale = value; XScaleChange(); } } /// /// 竖向缩放比例 /// private float _yScale; public float YScale { get { return _yScale; } set { _yScale = value; YScaleChange(); } } /// /// 缩放比例,该参数必须大于0 /// private double _scale = 1.0; public double Scale { get { return _scale; } set { if (value <= 0.000001) { return; } _scale = value; NotifyPropertyChanged("DScale"); } } /// /// 旋转角度 /// private double _route = 0.0; public double Route { get { return _route; } set { _route = value; DRouteChange(); NotifyPropertyChanged("DRoute"); } } /// /// 横向移动距离 /// private float _xMove; public float XMove { get { return _xMove; } set { _xMove = value; XMoveChange(); } } /// /// 竖向移动距离 /// private float _yMove; public float YMove { get { return _yMove; } set { _yMove = value; YMoveChange(); } } /// /// 边框颜色 /// private Brush _brushColor; public Brush BrushColor { get { return _brushColor; } set { _brushColor = value; ColorChange(); } } /// /// 变换矩阵 /// private Matrix _matrix = new Matrix(); public Matrix Matrix => _matrix.Clone(); /// /// 矩形框 /// private Rectangle _rcImg = new Rectangle(0, 0, 0, 0); public int _width { get; private set; } public int _height { get; private set; } /// /// 位图 /// private Bitmap? _bitmap = null; public Bitmap CanvasBitmap { get { return _bitmap; } } /// /// 预览缺陷图片的GraphicsPath /// private GraphicsPath? _path = null; public Bitmap ImgData { get { return _bitmap; } set { Init(); _bitmap = value; if (null == _bitmap) { _rcImg.Width = 0; _rcImg.Height = 0; } else { _rcImg.Width = _bitmap.Width; _rcImg.Height = _bitmap.Height; FitImage(); } //强制控件使其工作区无效并且重新绘制自己以及任何子控件 Refresh(); } } private string strImgPath = string.Empty; public string ImagePath { get { return strImgPath; } set { try { if (null != _bitmap) { _bitmap.Dispose(); } using (Stream s = File.Open(value, FileMode.Open)) { ImgData = (Bitmap)Image.FromStream(s); } } catch (Exception) { _bitmap = null; strImgPath = string.Empty; Refresh(); } } } private Mat strImgMat = new Mat(); public Mat ImaMAt { get { return strImgMat; } set { try { if (null != _bitmap) { _bitmap.Dispose(); } ImgData = value.ToBitmap(); } catch (Exception) { _bitmap = null; strImgPath = string.Empty; Refresh(); } } } private PointF _panBasePoint = PointF.Empty; private ClickArea _clickArea = ClickArea.AREA_UNKNOW; public List DefectList = new List(); public List GPathList = new List(); Action actionMove; Action actionUp; Action actionDown; //action1+= object osender; private Dictionary> _mouseEventDic = new Dictionary>() { }; public Canvas() { InitializeComponent(); DoubleBuffered = true; SetStyle(ControlStyles.AllPaintingInWmPaint//控件忽略窗口消息 WM_ERASEBKGND 以减少闪烁 | ControlStyles.UserPaint//由控件而不是由操作系统来绘制控件自身,即自定义绘制 | ControlStyles.OptimizedDoubleBuffer//控件将首先绘制到缓冲区而不是直接绘制到屏幕,这可以减少闪烁 | ControlStyles.ResizeRedraw, true);//控件会在调整大小时进行重绘 //添加鼠标滑轮事件 //MouseWheel += OnCanvasMouseWheel; //actionMove += ImageMoveFunc; // actionUp += ImageUPFunc; // actionDown += ImageDownFunc; _mouseEventDic.Add(MouseButtons.Left, actionMove); // _mouseEventDic.Add(MouseButtons.Left, actionMove); // _mouseEventDic.Add(MouseButtons.Left, actionMove); } /// /// 初始化 /// private void Init() { _clickArea = ClickArea.AREA_UNKNOW;//枚举 _rcImg = new Rectangle(0, 0, 0, 0); Scale = 1.0; Route = 0.0; _matrix.Reset();//重置为单位矩阵 strImgPath = string.Empty; _bitmap = null; } protected override void OnPaint(PaintEventArgs e) { //base.OnPaint(e); try { //获取表示控件的工作区的矩形 Rectangle rect = ClientRectangle; Graphics oriGraphics = e.Graphics; //设置平滑程度为高质量,减少抗锯齿的出现 oriGraphics.SmoothingMode = SmoothingMode.HighQuality; // 双缓冲绘图 //获取当前应用程序域的 BufferedGraphicsContext,此实例管理该应用程序的所有默认双缓冲 BufferedGraphicsContext currentContext = BufferedGraphicsManager.Current; //BufferedGraphics 对象管理与呈现图面(例如窗体或控件)关联的内存缓冲 BufferedGraphics myBuffer = currentContext.Allocate(oriGraphics, rect); //实例化一个直接表示内存缓冲的 Graphics 对象,可将图形呈现到内存缓冲,绘制到此对象中 Graphics bufferGraphics = myBuffer.Graphics; bufferGraphics.SmoothingMode = SmoothingMode.HighQuality; //高质量低速度呈现 bufferGraphics.PixelOffsetMode = PixelOffsetMode.HighQuality; //使用的插值算法 bufferGraphics.InterpolationMode = InterpolationMode.NearestNeighbor; //清除整个绘图面并以指定背景色填充,Console.BackColor指获取当前控件的背景色 bufferGraphics.Clear(BackColor); bufferGraphics.MultiplyTransform(_matrix); #region 画背景图 if (_bitmap != null) { try { bufferGraphics.DrawImage(_bitmap, 0, 0, _bitmap.Width, _bitmap.Height); if (_path != null) { bufferGraphics.DrawPath(new Pen(Brushes.Yellow, 1f), _path); } } catch { } } else { _bitmap = null; return; } #endregion #region 画矩形 GPathList.ForEach(path => { if (path != null) { bufferGraphics.DrawPath(new Pen(Brushes.Green, 2f), path); } }); #endregion #region 画缺陷 DefectList.ForEach(item => { // 缺陷图片 Bitmap bitmapDefect = item.OriBitMap; // 基准矩阵为背景图的矩阵 Matrix baseMatrix = _matrix.Clone(); baseMatrix.Multiply(item.PrivateMatrix); // 右乘每个缺陷自己的矩阵 bufferGraphics.Transform = baseMatrix; PointF upperLeftPoint = item.UpperLeftPoint; bufferGraphics.DrawImage(bitmapDefect, upperLeftPoint.X, upperLeftPoint.Y, bitmapDefect.Width, bitmapDefect.Height); if (item.Selected) { // bufferGraphics.DrawPath(new Pen(Brushes.Yellow, 1f), item.Path); item.DrawPath(bufferGraphics); } baseMatrix.Dispose(); }); #endregion myBuffer.Render(oriGraphics); //释放资源 bufferGraphics.Dispose(); myBuffer.Dispose(); currentContext.Dispose(); } catch { } } /// /// 鼠标滚轮事件 /// private void Canvas_MouseWheel(object? sender, MouseEventArgs e) { //绑定滚轮键 if (_clickArea == ClickArea.AREA_UNKNOW || _clickArea == ClickArea.AREA_IMG) { var delta = e.Delta; var p = e.Location.ToImageCoordinate(_matrix); var mat = new Matrix(); mat.Translate(p.X, p.Y); if (delta > 0) { mat.Scale(1.1f, 1.1f); } else { mat.Scale(0.9f, 0.9f); } mat.Translate(-p.X, -p.Y); _matrix.Multiply(mat); Refresh(); } else if (_clickArea == ClickArea.AREA_DEFECT) { var delta = e.Delta; var tmpMatrix = _matrix.Clone(); tmpMatrix.Multiply(SelectedDefect.PrivateMatrix); var point = e.Location.ToImageCoordinate(tmpMatrix); SelectedDefect.Move(point.X, point.Y); if (delta > 0) { SelectedDefect.Scale(1.1f, 1.1f); SelectedDefect.WholeDScale *= 1.1f; SelectedDefect.XDScale *= 1.1f; SelectedDefect.YDScale *= 1.1f; for (int i = 0; i < SelectedDefect.LastSetScale.Length; i++) { SelectedDefect.LastSetScale[i] *= 1.1f; } } else { SelectedDefect.Scale(0.9f, 0.9f); SelectedDefect.WholeDScale *= 0.9f; SelectedDefect.XDScale *= 0.9f; SelectedDefect.YDScale *= 0.9f; for (int i = 0; i < SelectedDefect.LastSetScale.Length; i++) { SelectedDefect.LastSetScale[i] *= 0.9f; } } SelectedDefect.Move(-point.X, -point.Y); Refresh(); } } /// /// 整体缩放比列改变时触发 /// private void WholeScaleChange() { if (SelectedDefect == null) { return; } float scaleWhole = WholeScale / SelectedDefect.LastSetScale[0]; SelectedDefect.LastSetScale[0] = WholeScale; SelectedDefect.WholeDScale = WholeScale; SelectedDefect.XDScale *= scaleWhole; SelectedDefect.YDScale *= scaleWhole; SelectedDefect.LastSetScale[1] *= scaleWhole; SelectedDefect.LastSetScale[2] *= scaleWhole; var point = SelectedDefect._defectCenterPoint; SelectedDefect.Move(point.X, point.Y); SelectedDefect.Scale(scaleWhole, scaleWhole); SelectedDefect.Move(-point.X, -point.Y); Refresh(); } /// /// 横向缩放比例改变时触发 /// private void XScaleChange() { if (SelectedDefect == null) { return; } float scaleX = XScale / SelectedDefect.LastSetScale[1]; SelectedDefect.LastSetScale[1] = XScale; SelectedDefect.XDScale = XScale; var point = SelectedDefect._defectCenterPoint; SelectedDefect.Move(point.X, point.Y); SelectedDefect.Scale(scaleX, 1f); SelectedDefect.Move(-point.X, -point.Y); Refresh(); } /// /// 竖向缩放比例改变时触发 /// private void YScaleChange() { if (SelectedDefect == null) { return; } float scaleY = YScale / SelectedDefect.LastSetScale[2]; SelectedDefect.LastSetScale[2] = YScale; SelectedDefect.YDScale = YScale; var point = SelectedDefect._defectCenterPoint; SelectedDefect.Move(point.X, point.Y); SelectedDefect.Scale(1f, scaleY); SelectedDefect.Move(-point.X, -point.Y); Refresh(); } /// /// 自适应图片,缩放到符合控件尺寸 /// private void FitImage() { if (null == _bitmap) { return; } _matrix = new Matrix(); try { // 先将图片缩放到适配控件尺寸 // 宽高比例中的较大值 float wRatio = 1f * _bitmap.Width / Width; float hRatio = 1f * _bitmap.Height / Height; float ratio = 1 / Math.Max(wRatio, hRatio); _matrix.Scale(ratio, ratio); _width = (int)(_bitmap.Width * ratio); _height = (int)(_bitmap.Height * ratio); // 再将图片平移到控件中心 // 将plMain的中心转换为图片坐标 PointF pControlCenter = new(Width / 2.0f, Height / 2.0f); PointF pImgCoordinate = pControlCenter.ToImageCoordinate(_matrix); //目标坐标减去当前坐标 _matrix.Translate(pImgCoordinate.X - _bitmap.Width / 2.0f, pImgCoordinate.Y - _bitmap.Height / 2.0f); } catch (Exception) { throw; } //强制控件使其工作区无效并立即重绘自己和任何子控件 Invalidate(); } private void Canvas_SizeChanged(object sender, EventArgs e) { Refresh(); } //{ // { MouseButtons.Left, ImageMoveFunc()}, // { MouseButtons.Right, ImageMoveFunc}, //}; // _mouseEventDic public enum ActionEnum { MOVE_ACTION, Move_Down, Move_Up, } public void Set(MouseButtons btn, ActionEnum action) { switch (action) { case ActionEnum.MOVE_ACTION: _mouseEventDic[btn] = ImageMoveFunc; break; case ActionEnum.Move_Up: _mouseEventDic[btn] = ImageUPFunc; break; case ActionEnum.Move_Down: _mouseEventDic[btn] = ImageDownFunc; break; } } private void ImageMoveFunc(object sender, MouseEventArgs e) { //鼠标左键移动触发移动事件 if (MouseButtons.Left == e.Button) { if (PointF.Empty == _panBasePoint) { return; } switch (_clickArea) { //case ClickArea.AREA_DEFECT: // 点击了缺陷区域 // { // // 选中的缺陷 // if (null == SelectedDefect) // { // break; // } // var tmpMatrix = _matrix.Clone(); // tmpMatrix.Multiply(SelectedDefect.PrivateMatrix); // //MouseEventArgs.Location包含相对于控件左上角的point坐标 // //得到点击的坐标在缺陷坐标系中的坐标值 // PointF p = e.Location.ToImageCoordinate(tmpMatrix); // float x = p.X - _panBasePoint.X; // float y = p.Y - _panBasePoint.Y; // Rectangle rectangle = new Rectangle((int)_panBasePoint.X, (int)_panBasePoint.Y,(int)x,(int)y); // // 位移矩阵左乘缺陷矩阵 // SelectedDefect.Move(x, y); // // 更新缺陷在控件坐标系中的位移 // PointF nowPoint = SelectedDefect._defectCenterPoint.ToControlCoordinate(tmpMatrix); // PointF initialPoint = SelectedDefect.InitialPosition.ToControlCoordinate(_matrix); // SelectedDefect.XDMove = nowPoint.X - initialPoint.X; // SelectedDefect.YDMove = nowPoint.Y - initialPoint.Y; // break; // } case ClickArea.AREA_IMG: // 点击了图像区域 { PointF p = e.Location.ToImageCoordinate(_matrix); float x = p.X - _panBasePoint.X; float y = p.Y - _panBasePoint.Y; _matrix.Translate(x, y); break; } } } } private void ImageUPFunc(object sender, MouseEventArgs e) { if (MouseButtons.Left == e.Button || MouseButtons.Right == e.Button) { _panBasePoint = Point.Empty; _clickArea = ClickArea.AREA_UNKNOW; } } private void ImageDownFunc(object sender, MouseEventArgs e) { Func funcContain = defect => { // 每个图片的最终矩阵,即背景图的矩阵 右乘 缺陷自身的矩阵 var tmpMatrix = _matrix.Clone(); tmpMatrix.Multiply(defect.PrivateMatrix); // 得到点击的坐标在每个缺陷的坐标系中的坐标值 PointF tmpP = e.Location.ToImageCoordinate(tmpMatrix); if (defect.ContainPoint(tmpP.ToPoint())) // 点击了缺陷区域 { _clickArea = ClickArea.AREA_DEFECT; _panBasePoint = tmpP; a = e.Location; // 此时基准点的坐标系为缺陷图片的坐标系 return true; } return false; }; if (AllowSelectDefect) { if (MouseButtons.Left == e.Button) { // 如果允许选中缺陷功能 // 检查是否在缺陷范围内,倒序查找 var ret = DefectList.LastOrDefault(d => funcContain(d)); if (null != ret) // 点击了缺陷 { if (ret.Selected) // 点击的是已经选择过的缺陷 { } else // 点击的是未选择的缺陷 { // 取消选择所有的,并选中当前点击的 DefectList.ForEach(d => d.UnSelect()); ret.Select(); } return; } else { DefectList.ForEach(d => d.UnSelect()); PointF clickPoint = e.Location.ToImageCoordinate(_matrix); if (_rcImg.Contains(clickPoint.ToPoint())) { _clickArea = ClickArea.AREA_IMG; _panBasePoint = clickPoint; } } } if (e.Button == MouseButtons.Right) { PointF clickPoint = e.Location.ToImageCoordinate(_matrix); if (_rcImg.Contains(clickPoint.ToPoint())) { if (null == SelectedDefect) { return; } _clickArea = ClickArea.AREA_IMG; _panBasePoint = clickPoint.ToImageCoordinate(SelectedDefect.PrivateMatrix); } } } } /// /// 图像移动与旋转 /// private void Canvas_MouseMove(object sender, MouseEventArgs e) { //鼠标左键移动触发移动事件 if (MouseButtons.Left == e.Button) { //_mouseEventDic[MouseButtons.Left].Invoke(sender, e); if (PointF.Empty == _panBasePoint) { return; } switch (_clickArea) { //case ClickArea.AREA_DEFECT: // 点击了缺陷区域 // { // // 选中的缺陷 // if (null == SelectedDefect) // { // break; // } // var tmpMatrix = _matrix.Clone(); // tmpMatrix.Multiply(SelectedDefect.PrivateMatrix); // //MouseEventArgs.Location包含相对于控件左上角的point坐标 // //得到点击的坐标在缺陷坐标系中的坐标值 // PointF p = e.Location.ToImageCoordinate(tmpMatrix); // float x = p.X - _panBasePoint.X; // float y = p.Y - _panBasePoint.Y; // // 位移矩阵左乘缺陷矩阵 // SelectedDefect.Move(x, y); // // 更新缺陷在控件坐标系中的位移 // PointF nowPoint = SelectedDefect._defectCenterPoint.ToControlCoordinate(tmpMatrix); // PointF initialPoint = SelectedDefect.InitialPosition.ToControlCoordinate(_matrix); // SelectedDefect.XDMove = nowPoint.X - initialPoint.X; // SelectedDefect.YDMove = nowPoint.Y - initialPoint.Y; // break; // } case ClickArea.AREA_IMG: // 点击了图像区域 { PointF p = e.Location.ToImageCoordinate(_matrix); string log = "x:" + p.X.ToString() + "Y:" + p.Y.ToString(); WriteLog(log); float x = p.X - _panBasePoint.X; float y = p.Y - _panBasePoint.Y; string log2 = "mmmx:" + x.ToString() + "mmmY:" + y.ToString(); WriteLog(log2); //Rectangle rectangle = new Rectangle((int)_panBasePoint.X, (int)_panBasePoint.Y, (int)x, (int)y); // _path = new GraphicsPath(); //_path.AddRectangle(rectangle); //_path.CloseAllFigures(); // Defect defect = new Defect(rectangle, _matrixcs); // DefectList.Add(defect); //PointF[] ps = new PointF[] { defect._defectCenterPoint }; // defect.PrivateMatrix.TransformPoints(ps); // defect.InitialPosition = ps[0]; // defect.Select(); break; } } } //鼠标右键移动触发旋转事件 if (e.Button == MouseButtons.Right) { if (_panBasePoint == PointF.Empty || _clickArea == ClickArea.AREA_UNKNOW) { return; } switch (_clickArea) { case ClickArea.AREA_UNKNOW: case ClickArea.AREA_DEFECT: { break; } case ClickArea.AREA_IMG: { if (SelectedDefect == null) { return; } Matrix tmpMatrix = _matrix.Clone(); tmpMatrix.Multiply(SelectedDefect.PrivateMatrix); PointF p = e.Location.ToImageCoordinate(tmpMatrix); float xBefore = _panBasePoint.X - SelectedDefect._defectCenterPoint.X; float yBefore = _panBasePoint.Y - SelectedDefect._defectCenterPoint.Y; float xAfter = p.X - SelectedDefect._defectCenterPoint.X; float yAfter = p.Y - SelectedDefect._defectCenterPoint.Y; double coorBefore = Math.Atan2(yBefore, xBefore); double coorAfter = Math.Atan2(yAfter, xAfter); SelectedDefect.DRoute = ((coorAfter - coorBefore) * 180 / Math.PI); Route = SelectedDefect.DRoute; break; } } } Refresh(); } /// /// 角度变化触发 /// private void DRouteChange() { if (SelectedDefect == null) { return; } SelectedDefect.RotateAt((float)Route, SelectedDefect._defectCenterPoint); SelectedDefect.TotalDRoute += Route; Refresh(); } private PointF a; /// /// 横向位移触发 /// private void XMoveChange() { if (null == SelectedDefect) { return; } Matrix tmpMatrix = _matrix.Clone(); tmpMatrix.Multiply(SelectedDefect.PrivateMatrix); SelectedDefect.LastSetPosition = SelectedDefect._defectCenterPoint.ToControlCoordinate(tmpMatrix); PointF nowPoint = new PointF(SelectedDefect.LastSetPosition.X + XMove, SelectedDefect.LastSetPosition.Y); nowPoint = nowPoint.ToImageCoordinate(tmpMatrix); float x = nowPoint.X - SelectedDefect._defectCenterPoint.X; float y = nowPoint.Y - SelectedDefect._defectCenterPoint.Y; SelectedDefect.Move(x, y); SelectedDefect.XDMove += XMove; Refresh(); } /// /// 竖向位移触发 /// private void YMoveChange() { if (null == SelectedDefect) { return; } Matrix tmpMatrix = _matrix.Clone(); tmpMatrix.Multiply(SelectedDefect.PrivateMatrix); SelectedDefect.LastSetPosition = SelectedDefect._defectCenterPoint.ToControlCoordinate(tmpMatrix); PointF nowPoint = new PointF(SelectedDefect.LastSetPosition.X, SelectedDefect.LastSetPosition.Y + YMove); nowPoint = nowPoint.ToImageCoordinate(tmpMatrix); int x = (int)(nowPoint.X - SelectedDefect._defectCenterPoint.X); int y = (int)(nowPoint.Y - SelectedDefect._defectCenterPoint.Y); SelectedDefect.Move(x, y); SelectedDefect.YDMove += YMove; Refresh(); } public void ColorChange() { Refresh(); } /// /// 鼠标按下事件 /// private void Canvas_MouseDown(object sender, MouseEventArgs e) { Func funcContain = defect => { // 每个图片的最终矩阵,即背景图的矩阵 右乘 缺陷自身的矩阵 var tmpMatrix = _matrix.Clone(); tmpMatrix.Multiply(defect.PrivateMatrix); // 得到点击的坐标在每个缺陷的坐标系中的坐标值 PointF tmpP = e.Location.ToImageCoordinate(tmpMatrix); if (defect.ContainPoint(tmpP.ToPoint())) // 点击了缺陷区域 { _clickArea = ClickArea.AREA_DEFECT; _panBasePoint = tmpP; a = e.Location; // 此时基准点的坐标系为缺陷图片的坐标系 return true; } return false; }; if (AllowSelectDefect) { if (MouseButtons.Left == e.Button) { // 如果允许选中缺陷功能 // 检查是否在缺陷范围内,倒序查找 var ret = DefectList.LastOrDefault(d => funcContain(d)); if (null != ret) // 点击了缺陷 { if (ret.Selected) // 点击的是已经选择过的缺陷 { } else // 点击的是未选择的缺陷 { // 取消选择所有的,并选中当前点击的 DefectList.ForEach(d => d.UnSelect()); ret.Select(); } return; } else { //Defect rectitem=new Defect(); // DefectList.Add() DefectList.ForEach(d => d.UnSelect()); PointF clickPoint = e.Location.ToImageCoordinate(_matrix); if (_rcImg.Contains(clickPoint.ToPoint())) { _clickArea = ClickArea.AREA_IMG; _panBasePoint = clickPoint; } } } if (e.Button == MouseButtons.Right) { PointF clickPoint = e.Location.ToImageCoordinate(_matrix); if (_rcImg.Contains(clickPoint.ToPoint())) { if (null == SelectedDefect) { return; } _clickArea = ClickArea.AREA_IMG; _panBasePoint = clickPoint.ToImageCoordinate(SelectedDefect.PrivateMatrix); } } } } /// /// 鼠标松开的事件 /// private void Canvas_MouseUp(object sender, MouseEventArgs e) { if (MouseButtons.Left == e.Button || MouseButtons.Right == e.Button) { PointF p = e.Location.ToImageCoordinate(_matrix); string log = "x:" + p.X.ToString() + "Y:" + p.Y.ToString(); WriteLog(log); float x = p.X - _panBasePoint.X; float y = p.Y - _panBasePoint.Y; string log2 = "mmmx:" + x.ToString() + "mmmY:" + y.ToString(); WriteLog(log2); //Rectangle rectangle = new Rectangle((int)_panBasePoint.X, (int)_panBasePoint.Y, (int)x, (int)y); //GraphicsPath path = new GraphicsPath(); //path.AddRectangle(rectangle); //path.CloseAllFigures(); //GPathList.Add(path); //Matrix _matrixcs = new Matrix(); //Defect defect = new Defect(rectangle, _matrixcs); //DefectList.Add(defect); //PointF[] ps = new PointF[] { defect._defectCenterPoint }; //defect.PrivateMatrix.TransformPoints(ps); //defect.InitialPosition = ps[0]; //defect.Select(); _panBasePoint = Point.Empty; _clickArea = ClickArea.AREA_UNKNOW; } } /// /// 载入缺陷预览图 /// public void LoadDefect(string file, Polygon p) { _path = null; PointF[] points = p.GetPoints().ToArray(); _path = new GraphicsPath(); _path.AddPolygon(points); _path.CloseAllFigures(); ImagePath = file; } public void LoadDefect(string file) { _path = null; ImagePath = file; } public void LoadPolygon(string file) { Matrix _matrix = new Matrix(); _path = null; Defect defect = new Defect(file, _matrix); DefectList.Add(defect); Refresh(); } public void LoadPolygon(string file, Polygon p) { Matrix _matrix = new Matrix(); PointF[] points = p.GetPoints().ToArray(); Defect defect = new Defect(file, points, _matrix); DefectList.Add(defect); PointF[] ps = new PointF[] { defect._defectCenterPoint }; defect.PrivateMatrix.TransformPoints(ps); defect.InitialPosition = ps[0]; Refresh(); } private void WriteLog(string log) { Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {log}"); } /// /// 删除新增缺陷 /// public void deleteDefect() { var defect = DefectList.FirstOrDefault(d => d.Selected); if (defect == null) { return; } DefectList.Remove(defect); } /// /// 按键按下 /// private void Canvas_KeyDown(object sender, KeyEventArgs e) { if (SelectedDefect == null) { return; } switch (e.KeyCode) { case Keys.Left: { SelectedDefect.Move(-MoveStep, 0, MatrixOrder.Append); } break; case Keys.Up: { SelectedDefect.Move(0, -MoveStep, MatrixOrder.Append); } break; case Keys.Right: { SelectedDefect.Move(MoveStep, 0, MatrixOrder.Append); } break; case Keys.Down: { SelectedDefect.Move(0, MoveStep, MatrixOrder.Append); } break; case Keys.Delete: { DefectList.Remove(SelectedDefect); break; } default: break; } Refresh(); } /// /// 按键抬起 /// private void Canvas_KeyUp(object sender, KeyEventArgs e) { _keyLastPressed = Keys.None; } /// /// 重写 ProcessDialogKey 使控件可以监听方向键与删除键 /// protected override bool ProcessDialogKey(Keys keyData) { if (keyData == Keys.Up || keyData == Keys.Down || keyData == Keys.Left || keyData == Keys.Right || keyData == Keys.Delete) { return false; } else { return base.ProcessDialogKey(keyData); } } } }