944 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			944 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| 
 | ||
| using DH.Commons.Enums;
 | ||
| using System;
 | ||
| using System.Collections.Generic;
 | ||
| using System.Collections.ObjectModel;
 | ||
| using System.Diagnostics;
 | ||
| using System.Drawing;
 | ||
| using System.Drawing.Drawing2D;
 | ||
| using System.Drawing.Imaging;
 | ||
| using System.Linq;
 | ||
| using System.Threading;
 | ||
| using System.Windows.Forms;
 | ||
| 
 | ||
| using static DH.Commons.Enums.EnumHelper;
 | ||
| 
 | ||
| 
 | ||
| namespace DH.UI.Model.Winform
 | ||
| {
 | ||
|     public partial class CanvasImage : UserControl
 | ||
|     {
 | ||
|         public CanvasImage()
 | ||
|         {
 | ||
|             InitializeComponent();
 | ||
| 
 | ||
|             DoubleBuffered = true;
 | ||
|             SetStyle(ControlStyles.OptimizedDoubleBuffer |
 | ||
|                             ControlStyles.ResizeRedraw |
 | ||
|                             ControlStyles.AllPaintingInWmPaint, true);
 | ||
| 
 | ||
|             MouseWheel += Canvas_MouseWheel;
 | ||
|             KeyDown += OnCanvasKeyDown;
 | ||
|             KeyPress += OnCanvasKeyPressed;
 | ||
|             MouseDoubleClick += Canvas_MouseDoubleClick;
 | ||
|             MouseDown += Canvas_MouseDown;
 | ||
|             MouseMove += Canvas_MouseMove;
 | ||
|             MouseUp += Canvas_MouseUp;
 | ||
| 
 | ||
|            // EventRouter.ChangeElementsMouseState -= OnElementChangeMouseState;
 | ||
|            // EventRouter.ChangeElementsMouseState += OnElementChangeMouseState;
 | ||
| 
 | ||
|             //Elements.CollectionChanged += Elements_CollectionChanged;
 | ||
|         }
 | ||
| 
 | ||
|         private void Elements_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
 | ||
|         {
 | ||
|             //this.Invoke(new Action(() =>
 | ||
|             //{
 | ||
|             //    this.Invalidate();
 | ||
|             //}));
 | ||
|         }
 | ||
| 
 | ||
|         #region Event
 | ||
|         public Action<MouseState> OnMouseStateChanged;
 | ||
|         public Action<IShapeElement> DrawTemplateChanged = null;
 | ||
|         public Action<Point, PointF, string> OnMouseLocationUpdated;
 | ||
|         #endregion
 | ||
| 
 | ||
|         private MouseState mouseState = MouseState.Normal;
 | ||
|         public MouseState MouseState
 | ||
|         {
 | ||
|             get
 | ||
|             {
 | ||
|                 return mouseState;
 | ||
|             }
 | ||
|             set
 | ||
|             {
 | ||
|                 if (mouseState != value)
 | ||
|                 {
 | ||
|                     mouseState = value;
 | ||
| 
 | ||
|                     // OnMouseStateChanged?.BeginInvoke(value, null, null);
 | ||
|                     Task.Run(() => OnMouseStateChanged.Invoke(value));
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         #region 属性和字段
 | ||
| 
 | ||
|         //private Bitmap map = new Bitmap(10, 10);
 | ||
|         //public Bitmap MAP
 | ||
|         //{
 | ||
|         //    get
 | ||
|         //    {
 | ||
|         //        _mapLoadHandler.WaitOne();
 | ||
|         //        return map;
 | ||
|         //    }
 | ||
|         //    set
 | ||
|         //    {
 | ||
|         //        map = value;
 | ||
|         //    }
 | ||
|         //}
 | ||
| 
 | ||
|         public Bitmap MAP { get; set; } = new Bitmap(10, 10);
 | ||
| 
 | ||
|         public Matrix Matrix { get; set; } = new Matrix();
 | ||
|         public ObservableCollection<IShapeElement> Elements { get; set; } = new ObservableCollection<IShapeElement>();
 | ||
| 
 | ||
|         RectangleF _selectionRect = new RectangleF();
 | ||
|         #endregion
 | ||
| 
 | ||
|         #region 重绘
 | ||
|         protected override void OnPaint(PaintEventArgs e)
 | ||
|         {
 | ||
|             try
 | ||
|             {
 | ||
|                 //lock (_mapLoadLock)
 | ||
|                 //{ }
 | ||
| 
 | ||
|                 Rectangle rect = ClientRectangle;
 | ||
|                 Graphics originG = e.Graphics;
 | ||
|                 BufferedGraphicsContext currentContext = BufferedGraphicsManager.Current;
 | ||
|                 BufferedGraphics myBuffer = currentContext.Allocate(originG, rect);
 | ||
|                 Graphics g = myBuffer.Graphics;
 | ||
|                 g.SmoothingMode = SmoothingMode.HighSpeed;
 | ||
|                 g.PixelOffsetMode = PixelOffsetMode.HighSpeed;
 | ||
|                 g.InterpolationMode = InterpolationMode.NearestNeighbor;
 | ||
|                 g.Clear(BackColor);
 | ||
| 
 | ||
|                 g.MultiplyTransform(Matrix);
 | ||
| 
 | ||
|                 if (MAP != null)
 | ||
|                 {
 | ||
|                     try
 | ||
|                     {
 | ||
|                         g.DrawImage(MAP, 0, 0, MAP.Width, MAP.Height);
 | ||
|                     }
 | ||
|                     catch (Exception ex)
 | ||
|                     {
 | ||
|                     }
 | ||
|                 }
 | ||
|                 else
 | ||
|                 {
 | ||
|                     g.Clear(BackColor);
 | ||
|                 }
 | ||
| 
 | ||
|                 DrawTemplate?.Draw(g);
 | ||
|                 foreach (IShapeElement ele in Elements)
 | ||
|                 {
 | ||
|                     if (ele.IsEnabled && ele.IsShowing)
 | ||
|                     {
 | ||
|                         ele.Draw(g);
 | ||
|                     }
 | ||
|                 }
 | ||
| 
 | ||
|                 #region Grid
 | ||
|                 if (MAP != null)
 | ||
|                 {
 | ||
|                     if (ShowGrid)
 | ||
|                     {
 | ||
|                         int baseX = MAP.Width / 2;
 | ||
|                         int baseY = MAP.Height / 2;
 | ||
| 
 | ||
|                         Point[] xPoint = new Point[] { new Point(0, baseY), new Point(MAP.Width, baseY) };
 | ||
|                         Point[] yPoint = new Point[] { new Point(baseX, 0), new Point(baseX, MAP.Height) };
 | ||
| 
 | ||
|                         g.DrawLine(new Pen(Pen_Grid.Color, 5.0f), xPoint[0], xPoint[1]);
 | ||
|                         g.DrawLine(new Pen(Pen_Grid.Color, 5.0f), yPoint[0], yPoint[1]);
 | ||
| 
 | ||
|                         if (GridValue > 0)
 | ||
|                         {
 | ||
|                             int stepX = MAP.Width / 2 / (GridValue * MAP.Width / 2 / _minGridStep / 10);
 | ||
|                             int stepY = MAP.Height / 2 / (GridValue * MAP.Height / 2 / _minGridStep / 10);
 | ||
| 
 | ||
|                             //int stepX = _minGridStep + (10 - GridValue) * (MAP.Width / 2 - _minGridStep) / 10;
 | ||
|                             //int stepY = _minGridStep + (10 - GridValue) * (MAP.Height / 2 - _minGridStep) / 10;
 | ||
| 
 | ||
|                             int yPositive = baseY;
 | ||
|                             do
 | ||
|                             {
 | ||
|                                 xPoint = new Point[] { new Point(0, yPositive), new Point(MAP.Width, yPositive) };
 | ||
|                                 g.DrawLine(Pen_Grid, xPoint[0], xPoint[1]);
 | ||
|                                 yPositive -= stepY;
 | ||
|                             } while (yPositive > 0);
 | ||
| 
 | ||
|                             int yNegative = baseY;
 | ||
|                             do
 | ||
|                             {
 | ||
|                                 xPoint = new Point[] { new Point(0, yNegative), new Point(MAP.Width, yNegative) };
 | ||
|                                 g.DrawLine(Pen_Grid, xPoint[0], xPoint[1]);
 | ||
|                                 yNegative += stepY;
 | ||
|                             } while (yNegative < MAP.Height);
 | ||
| 
 | ||
|                             int xPositive = baseX;
 | ||
|                             do
 | ||
|                             {
 | ||
|                                 yPoint = new Point[] { new Point(xPositive, 0), new Point(xPositive, MAP.Height) };
 | ||
|                                 g.DrawLine(Pen_Grid, yPoint[0], yPoint[1]);
 | ||
|                                 xPositive -= stepX;
 | ||
|                             } while (xPositive > 0);
 | ||
| 
 | ||
|                             int xNegative = baseX;
 | ||
|                             do
 | ||
|                             {
 | ||
|                                 yPoint = new Point[] { new Point(xNegative, 0), new Point(xNegative, MAP.Height) };
 | ||
|                                 g.DrawLine(Pen_Grid, yPoint[0], yPoint[1]);
 | ||
|                                 xNegative += stepX;
 | ||
|                             } while (xNegative < MAP.Width);
 | ||
|                         }
 | ||
|                     }
 | ||
|                 }
 | ||
|                 #endregion
 | ||
| 
 | ||
|                 if (MouseState == MouseState.SelectionZoneDoing)
 | ||
|                 {
 | ||
|                     g.DrawRectangle(Pens.AliceBlue, _selectionRect.X, _selectionRect.Y, _selectionRect.Width, _selectionRect.Height);
 | ||
|                     g.FillRectangle(new SolidBrush(Color.FromArgb(40, 0, 0, 255)), _selectionRect);
 | ||
|                 }
 | ||
| 
 | ||
|                 myBuffer.Render(originG);
 | ||
|                 g.Dispose();
 | ||
|                 myBuffer.Dispose();//释放资源
 | ||
|             }
 | ||
|             catch (Exception)
 | ||
|             {
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         private void halfTransparent()
 | ||
|         {
 | ||
|         }
 | ||
|         #endregion
 | ||
| 
 | ||
|         #region 绘制类型
 | ||
|         private IShapeElement drawTemplate = null;
 | ||
|         public IShapeElement DrawTemplate
 | ||
|         {
 | ||
|             get
 | ||
|             {
 | ||
|                 return drawTemplate;
 | ||
|             }
 | ||
|             set
 | ||
|             {
 | ||
|                 if (drawTemplate != value)
 | ||
|                 {
 | ||
| 
 | ||
|                     drawTemplate = value;
 | ||
| 
 | ||
|                     //DrawTemplateChanged?.BeginInvoke(value, null, null);
 | ||
|                     Task.Run(() => DrawTemplateChanged.Invoke(value));
 | ||
| 
 | ||
|                     if (value == null)
 | ||
|                     {
 | ||
|                         MouseState = MouseState.Normal;
 | ||
|                         return;
 | ||
|                     }
 | ||
| 
 | ||
|                     MouseState = MouseState.New;
 | ||
| 
 | ||
|                     var existed = Elements.FirstOrDefault(e => e.ID == value.ID);
 | ||
|                     if (existed != null)
 | ||
|                     {
 | ||
|                         Elements.Remove(existed);
 | ||
|                     }
 | ||
| 
 | ||
|                     //if (DrawTemplate != null)
 | ||
|                     //{
 | ||
|                     //    DrawTemplate.OnDrawDone += OnElementDrawDone;
 | ||
|                     //}
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         string currentElementId = "";
 | ||
|         string CurrentElementId
 | ||
|         {
 | ||
|             get
 | ||
|             {
 | ||
|                 return currentElementId;
 | ||
|             }
 | ||
|             set
 | ||
|             {
 | ||
|                 if (currentElementId != value)
 | ||
|                 {
 | ||
|                     currentElementId = value;
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         private void OnElementDrawDone(IShapeElement ele)
 | ||
|         {
 | ||
|             //int maxIndex = 1;
 | ||
|             //if (Elements.Count > 0)
 | ||
|             //{
 | ||
|             //    maxIndex = Elements.Max(u => u.Index) + 1;
 | ||
|             //}
 | ||
|             //ele.Index = maxIndex;
 | ||
|             //ele.Name = maxIndex.ToString();
 | ||
| 
 | ||
|             //#region 获取基元的设备属性,目前包括运动坐标和相机参数
 | ||
|             //SetElementDevicePara?.Invoke(ele);
 | ||
|             //#endregion
 | ||
| 
 | ||
|             //Elements.Add(ele);
 | ||
|             //DrawTemplate = DrawTemplate?.Clone() as IShapeElement;
 | ||
|         }
 | ||
|         #endregion
 | ||
| 
 | ||
|         #region 状态变换
 | ||
|         private void OnElementChangeMouseState(IShapeElement ele, ElementState preState, ElementState curState)
 | ||
|         {
 | ||
|             if (curState != ElementState.Normal)
 | ||
|             {
 | ||
|                 switch (curState)
 | ||
|                 {
 | ||
|                     case ElementState.New:
 | ||
|                         MouseState = MouseState.New;
 | ||
|                         break;
 | ||
|                     case ElementState.Selected:
 | ||
|                         CurrentElementId = ele.ID;
 | ||
|                         Cursor = Cursors.Default;
 | ||
|                         break;
 | ||
|                     case ElementState.Moving:
 | ||
|                         MouseState = MouseState.MoveElement;
 | ||
|                         Cursor = Cursors.NoMove2D;
 | ||
|                         break;
 | ||
|                     case ElementState.Editing:
 | ||
|                         MouseState = MouseState.Editing;
 | ||
|                         Cursor = Cursors.Hand;
 | ||
|                         break;
 | ||
|                     case ElementState.MouseInSide:
 | ||
|                         MouseState = MouseState.InSideElement;
 | ||
|                         break;
 | ||
|                     case ElementState.MouseHover:
 | ||
|                         MouseState = MouseState.HoverElement;
 | ||
|                         break;
 | ||
|                     case ElementState.CanStretchLeft:
 | ||
|                         Cursor = Cursors.SizeWE;
 | ||
|                         break;
 | ||
|                     case ElementState.StretchingLeft:
 | ||
|                         MouseState = MouseState.StretchingLeft;
 | ||
|                         Cursor = Cursors.SizeWE;
 | ||
|                         break;
 | ||
|                     case ElementState.CanStretchBottom:
 | ||
|                         Cursor = Cursors.SizeNS;
 | ||
|                         break;
 | ||
|                     case ElementState.StretchingBottom:
 | ||
|                         MouseState = MouseState.StretchingBottom;
 | ||
|                         Cursor = Cursors.SizeNS;
 | ||
|                         break;
 | ||
|                     case ElementState.CanStretchRight:
 | ||
|                         Cursor = Cursors.SizeWE;
 | ||
|                         break;
 | ||
|                     case ElementState.StretchingRight:
 | ||
|                         MouseState = MouseState.StretchingRight;
 | ||
|                         Cursor = Cursors.SizeWE;
 | ||
|                         break;
 | ||
|                     case ElementState.CanStretchTop:
 | ||
|                         Cursor = Cursors.SizeNS;
 | ||
|                         break;
 | ||
|                     case ElementState.StretchingTop:
 | ||
|                         MouseState = MouseState.StretchingTop;
 | ||
|                         Cursor = Cursors.SizeNS;
 | ||
|                         break;
 | ||
| 
 | ||
|                     case ElementState.CanStretchLeftLowerCorner:
 | ||
|                         Cursor = Cursors.SizeNESW;
 | ||
|                         break;
 | ||
|                     case ElementState.StretchingLeftLowerCorner:
 | ||
|                         MouseState = MouseState.StretchingLeftLowerCorner;
 | ||
|                         Cursor = Cursors.SizeNESW;
 | ||
|                         break;
 | ||
|                     case ElementState.CanStretchLeftUpperCorner:
 | ||
|                         Cursor = Cursors.SizeNWSE;
 | ||
|                         break;
 | ||
|                     case ElementState.StretchingLeftUpperCorner:
 | ||
|                         MouseState = MouseState.StretchingLeftUpperCorner;
 | ||
|                         Cursor = Cursors.SizeNWSE;
 | ||
|                         break;
 | ||
|                     case ElementState.CanStretchRightLowerCorner:
 | ||
|                         Cursor = Cursors.SizeNWSE;
 | ||
|                         break;
 | ||
|                     case ElementState.StretchingRightLowerCorner:
 | ||
|                         MouseState = MouseState.StretchingRightLowerCorner;
 | ||
|                         Cursor = Cursors.SizeNWSE;
 | ||
|                         break;
 | ||
|                     case ElementState.CanStretchRightUpperCorner:
 | ||
|                         Cursor = Cursors.SizeNESW;
 | ||
|                         break;
 | ||
|                     case ElementState.StretchingRightUpperCorner:
 | ||
|                         MouseState = MouseState.StretchingRightUpperCorner;
 | ||
|                         Cursor = Cursors.SizeNESW;
 | ||
|                         break;
 | ||
|                     default:
 | ||
|                         //MouseState = MouseState.Normal;
 | ||
|                         break;
 | ||
|                 }
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 if (Elements.All(e => e.State == ElementState.Normal))
 | ||
|                 {
 | ||
|                     CurrentElementId = null;
 | ||
| 
 | ||
|                     if (preState == ElementState.Selected)
 | ||
|                     {
 | ||
|                         DrawTemplate = null;
 | ||
|                     }
 | ||
|                     else if (DrawTemplate != null)
 | ||
|                     {
 | ||
|                         MouseState = MouseState.New;
 | ||
|                         return;
 | ||
|                     }
 | ||
| 
 | ||
|                     //MouseState = MouseState.Normal;
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|             this.Invalidate();
 | ||
|         }
 | ||
|         #endregion
 | ||
| 
 | ||
|         #region 鼠标动作
 | ||
|         private void Canvas_MouseWheel(object sender, MouseEventArgs e)
 | ||
|         {
 | ||
|             PointF prePoint = ToMapPoint(e.Location);
 | ||
| 
 | ||
|             //先缩放
 | ||
|             if (e.Delta > 0)
 | ||
|             {
 | ||
|                 Matrix.Scale((float)1.1, (float)1.1);
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 Matrix.Scale((float)0.9, (float)0.9);
 | ||
|             }
 | ||
| 
 | ||
|             PointF afterPoint = ToMapPoint(e.Location);
 | ||
| 
 | ||
|             //后平移
 | ||
|             Matrix.Translate(afterPoint.X - prePoint.X, afterPoint.Y - prePoint.Y);
 | ||
| 
 | ||
|             Invalidate();
 | ||
|         }
 | ||
| 
 | ||
|         PointF startPoint, currentPoint;
 | ||
|         bool _isMouseBtnPressing = false;
 | ||
| 
 | ||
|         private void Canvas_MouseDown(object sender, MouseEventArgs e)
 | ||
|         {
 | ||
|             PointF p = ToMapPoint(e.Location);
 | ||
| 
 | ||
|             if (e.Button == MouseButtons.Left)
 | ||
|             {
 | ||
|                 _isMouseBtnPressing = true;
 | ||
| 
 | ||
|                 switch (MouseState)
 | ||
|                 {
 | ||
|                     case MouseState.Normal:
 | ||
|                         startPoint = e.Location;
 | ||
|                         break;
 | ||
|                     case MouseState.StretchingLeft:
 | ||
|                         break;
 | ||
|                     case MouseState.StretchingRight:
 | ||
|                         break;
 | ||
|                     case MouseState.StretchingTop:
 | ||
|                         break;
 | ||
|                     case MouseState.StretchingBottom:
 | ||
|                         break;
 | ||
|                     case MouseState.MoveElement:
 | ||
|                         break;
 | ||
|                     case MouseState.HoverElement:
 | ||
|                     case MouseState.InSideElement:
 | ||
|                     case MouseState.New:
 | ||
|                         DrawTemplate?.OnMouseDown(p);
 | ||
|                         break;
 | ||
|                     case MouseState.Editing:
 | ||
|                         break;
 | ||
|                     case MouseState.SelectionZone:
 | ||
|                         MouseState = MouseState.SelectionZoneDoing;
 | ||
|                         startPoint = p;
 | ||
|                         break;
 | ||
|                 }
 | ||
| 
 | ||
|                 foreach (IShapeElement ele in Elements)
 | ||
|                 {
 | ||
|                     ele.OnMouseDown(p);
 | ||
|                 }
 | ||
|             }
 | ||
|             else if (e.Button == MouseButtons.Right)
 | ||
|             {
 | ||
|                 if (DrawTemplate != null && DrawTemplate.State == ElementState.New && DrawTemplate.IsCreatedDone())
 | ||
|                 {
 | ||
|                     IShapeElement ele = DrawTemplate.Clone() as IShapeElement;
 | ||
|                     ele.State = ElementState.Normal;
 | ||
|                     Elements.Add(ele);
 | ||
| 
 | ||
|                    // (DrawTemplate as ElementBase).Initial();
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         private void Canvas_MouseUp(object sender, MouseEventArgs e)
 | ||
|         {
 | ||
|             if (e.Button != MouseButtons.Left)
 | ||
|                 return;
 | ||
| 
 | ||
|             _isMouseBtnPressing = false;
 | ||
|             switch (MouseState)
 | ||
|             {
 | ||
|                 case MouseState.Normal:
 | ||
|                     break;
 | ||
|                 case MouseState.HoverElement:
 | ||
|                     break;
 | ||
|                 case MouseState.InSideElement:
 | ||
|                     break;
 | ||
|                 case MouseState.StretchingLeft:
 | ||
|                     break;
 | ||
|                 case MouseState.StretchingRight:
 | ||
|                     break;
 | ||
|                 case MouseState.StretchingTop:
 | ||
|                     break;
 | ||
|                 case MouseState.StretchingBottom:
 | ||
|                     break;
 | ||
|                 case MouseState.MoveElement:
 | ||
|                     //MouseState = MouseState.SelectedElement;
 | ||
|                     break;
 | ||
|                 case MouseState.New:
 | ||
|                     break;
 | ||
|                 case MouseState.Editing:
 | ||
|                     break;
 | ||
|                 case MouseState.MovingAll:
 | ||
|                     MouseState = MouseState.Normal;
 | ||
|                     break;
 | ||
|                 case MouseState.SelectionZone:
 | ||
|                     break;
 | ||
|                 case MouseState.SelectionZoneDoing:
 | ||
|                     MouseState = MouseState.SelectionZone;
 | ||
| 
 | ||
|                     foreach (IShapeElement ele in Elements)
 | ||
|                     {
 | ||
|                         ele.State = ElementState.Normal;
 | ||
|                         if (ele.IsIntersect(_selectionRect))
 | ||
|                         {
 | ||
|                             ele.State = ElementState.Selected;
 | ||
|                         }
 | ||
|                     }
 | ||
| 
 | ||
|                     break;
 | ||
|             }
 | ||
| 
 | ||
|             Cursor = Cursors.Default;
 | ||
| 
 | ||
|             if (MouseState != MouseState.SelectionZone)
 | ||
|             {
 | ||
|                 PointF p = ToMapPoint(e.Location);
 | ||
|                 DrawTemplate?.OnMouseUp(p);
 | ||
|                 foreach (IShapeElement ele in Elements)
 | ||
|                 {
 | ||
|                     ele.OnMouseUp(p);
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         private void Canvas_MouseMove(object sender, MouseEventArgs e)
 | ||
|         {
 | ||
|             PointF p = ToMapPoint(e.Location);
 | ||
| 
 | ||
|             switch (MouseState)
 | ||
|             {
 | ||
|                 case MouseState.Normal:
 | ||
|                     {
 | ||
|                         if (_isMouseBtnPressing)
 | ||
|                         {
 | ||
|                             currentPoint = e.Location;
 | ||
|                             PointF p1 = ToMapPoint(startPoint);
 | ||
|                             PointF p2 = ToMapPoint(currentPoint);
 | ||
|                             Matrix.Translate(p2.X - p1.X, p2.Y - p1.Y);
 | ||
|                             startPoint = e.Location;
 | ||
|                         }
 | ||
|                     }
 | ||
|                     break;
 | ||
|                 case MouseState.StretchingLeft:
 | ||
|                     break;
 | ||
|                 case MouseState.StretchingRight:
 | ||
|                     break;
 | ||
|                 case MouseState.StretchingTop:
 | ||
|                     break;
 | ||
|                 case MouseState.StretchingBottom:
 | ||
|                     break;
 | ||
|                 case MouseState.MoveElement:
 | ||
|                     break;
 | ||
|                 case MouseState.HoverElement:
 | ||
|                 case MouseState.InSideElement:
 | ||
|                 case MouseState.New:
 | ||
|                     DrawTemplate?.OnMouseMove(p);
 | ||
|                     break;
 | ||
|                 case MouseState.Editing:
 | ||
|                     break;
 | ||
|                 case MouseState.MovingAll:
 | ||
|                     break;
 | ||
|                 case MouseState.SelectionZoneDoing:
 | ||
|                     {
 | ||
|                         currentPoint = p;
 | ||
| 
 | ||
|                         float[] x2 = new float[2] { startPoint.X, currentPoint.X };
 | ||
|                         float[] y2 = new float[2] { startPoint.Y, currentPoint.Y };
 | ||
| 
 | ||
|                         float xMin = x2.Min();
 | ||
|                         float xMax = x2.Max();
 | ||
|                         float yMin = y2.Min();
 | ||
|                         float yMax = y2.Max();
 | ||
| 
 | ||
|                         _selectionRect = new RectangleF(xMin, yMin, xMax - xMin, yMax - yMin);
 | ||
|                     }
 | ||
|                     break;
 | ||
|             }
 | ||
| 
 | ||
|             PointF mapPoint = ToMapPoint(e.Location);
 | ||
|             Color color = Color.Transparent;
 | ||
|             if (MAP != null && mapPoint.X > 0 && mapPoint.X < MAP.Width && mapPoint.Y > 0 && mapPoint.Y < MAP.Height)
 | ||
|             {
 | ||
|                 color = MAP.GetPixel((int)mapPoint.X, (int)mapPoint.Y);
 | ||
|             }
 | ||
| 
 | ||
|             // OnMouseLocationUpdated?.BeginInvoke(e.Location, mapPoint, color.Name, null, null); 
 | ||
|             Task.Run(() => OnMouseLocationUpdated?.Invoke(e.Location, mapPoint, color.Name));
 | ||
| 
 | ||
|             if (MouseState != MouseState.SelectionZoneDoing)
 | ||
|             {
 | ||
|                 Elements.ToList().ForEach(ele => ele?.OnMouseMove(p));
 | ||
|             }
 | ||
| 
 | ||
|             Invalidate();
 | ||
|         }
 | ||
| 
 | ||
|         private void Canvas_MouseDoubleClick(object sender, MouseEventArgs e)
 | ||
|         {
 | ||
|             PointF p = ToMapPoint(e.Location);
 | ||
| 
 | ||
|             if (e.Button == MouseButtons.Left)
 | ||
|             {
 | ||
|                 switch (MouseState)
 | ||
|                 {
 | ||
|                     //case MouseState.SelectedElement:
 | ||
|                     case MouseState.HoverElement:
 | ||
|                     case MouseState.InSideElement:
 | ||
|                     case MouseState.MoveElement:
 | ||
|                     case MouseState.Normal:
 | ||
|                         //Elements.ForEach(ele =>
 | ||
|                         foreach (IShapeElement ele in Elements)
 | ||
|                         {
 | ||
|                             ele.OnMouseDoubleClick(p);
 | ||
|                         }
 | ||
|                         //);
 | ||
|                         break;
 | ||
|                     default:
 | ||
|                         break;
 | ||
|                 }
 | ||
|             }
 | ||
|             else
 | ||
|             {
 | ||
|                 //if (MouseState == MouseState.SelectedElement)
 | ||
|                 {
 | ||
|                     MouseState = MouseState.Normal;
 | ||
| 
 | ||
|                     //Elements.ForEach(ele =>
 | ||
|                     foreach (IShapeElement ele in Elements)
 | ||
|                     {
 | ||
|                         ele.State = ElementState.Normal;
 | ||
|                     }
 | ||
|                     //);
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         #endregion
 | ||
| 
 | ||
|         #region 图片操作
 | ||
|         bool _firstLoad = true;
 | ||
|         object _mapLoadLock = new object();
 | ||
|         ManualResetEvent _mapLoadHandler = new ManualResetEvent(true);
 | ||
|         ManualResetEvent _mapUsingHandler = new ManualResetEvent(false);
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 载入图片
 | ||
|         /// </summary>
 | ||
|         /// <param name="bitmap"></param>
 | ||
|         public void LoadImage(Bitmap bitmap)
 | ||
|         {
 | ||
|             if (bitmap == null)
 | ||
|                 return;
 | ||
| 
 | ||
|             ////lock (_mapLoadLock)
 | ||
|             ////_mapUsingHandler.WaitOne();
 | ||
|             //_mapLoadHandler.Reset();
 | ||
|             //{
 | ||
|             //    map?.Dispose();
 | ||
|             //    map = null;
 | ||
|             //    map = bitmap;
 | ||
|             //}
 | ||
|             //_mapLoadHandler.Set();
 | ||
| 
 | ||
|             MAP = bitmap;
 | ||
| 
 | ||
|             if (_firstLoad)
 | ||
|             {
 | ||
|                 SetScreenSize();
 | ||
|                 _firstLoad = false;
 | ||
|             }
 | ||
|             Invalidate();
 | ||
|         }
 | ||
| 
 | ||
|         public void Clear()
 | ||
|         {
 | ||
|             MAP = null;
 | ||
|             Elements.Clear();
 | ||
| 
 | ||
|             Invalidate();
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 设置图片为原始尺寸
 | ||
|         /// </summary>
 | ||
|         public void SetMapSize()
 | ||
|         {
 | ||
|             Matrix = new Matrix();
 | ||
|             Invalidate();
 | ||
|         }
 | ||
| 
 | ||
|         /// <summary>
 | ||
|         /// 设置图片为适配尺寸
 | ||
|         /// </summary>
 | ||
|         public void SetScreenSize()
 | ||
|         {
 | ||
|             try
 | ||
|             {
 | ||
|                 if (MAP == null)
 | ||
|                     return;
 | ||
| 
 | ||
|                 Matrix = new Matrix();
 | ||
| 
 | ||
|                 //先缩放
 | ||
|                 List<float> ratios = new List<float>() { MAP.Width / (float)Width, MAP.Height / (float)Height };
 | ||
|                 float ratio = 1 / ratios.Max();
 | ||
|                 Matrix.Scale(ratio, ratio);
 | ||
| 
 | ||
|                 //再平移
 | ||
|                 //将plMain的中心转换为图片坐标
 | ||
|                 PointF screenCenter = new PointF(Width / 2.0f, Height / 2.0f);
 | ||
|                 PointF mapPoint = ToMapPoint(screenCenter);
 | ||
| 
 | ||
|                 //目标坐标减去当前坐标
 | ||
|                 Matrix.Translate(-MAP.Width / 2.0f + mapPoint.X, -MAP.Height / 2.0f + mapPoint.Y);
 | ||
| 
 | ||
|                 Invalidate();
 | ||
|             }
 | ||
|             catch (Exception ex)
 | ||
|             {
 | ||
|                 //Trace.TraceError(ex.GetExceptionMessage());
 | ||
|             }
 | ||
|         }
 | ||
|         #endregion
 | ||
| 
 | ||
|         #region 私有方法
 | ||
|         //private void DisplayMouseLocation(Point location)
 | ||
|         //{
 | ||
|         //    string screenPoint = string.Format("屏幕坐标X:{0};Y:{1}", location.X, location.Y);
 | ||
| 
 | ||
|         //    Point mapPoint = ToMapPoint(location);
 | ||
|         //    string mapPointStr = string.Format("图片坐标X:{0};Y:{1}", mapPoint.X, mapPoint.Y);
 | ||
| 
 | ||
|         //    tsslLocation.Text = screenPoint + "       " + mapPointStr;
 | ||
|         //}
 | ||
| 
 | ||
|         private PointF ToMapPoint(PointF p)
 | ||
|         {
 | ||
|             PointF[] ps = new PointF[] { p };
 | ||
|             Matrix invertMatrix = Matrix.Clone();
 | ||
|             invertMatrix.Invert();
 | ||
|             invertMatrix.TransformPoints(ps);
 | ||
| 
 | ||
|             return ps[0];
 | ||
|         }
 | ||
| 
 | ||
|         private Point ToScreenPoint(Point p)
 | ||
|         {
 | ||
|             Point[] ps = new Point[] { p };
 | ||
|             Matrix.TransformPoints(ps);
 | ||
| 
 | ||
|             return ps[0];
 | ||
|         }
 | ||
| 
 | ||
|         #endregion
 | ||
| 
 | ||
|         #region 按键操作
 | ||
|         public void OnCanvasKeyPressed(object sender, KeyPressEventArgs e)
 | ||
|         {
 | ||
|             //if (e.KeyChar == 27)  //Esc
 | ||
|             //{
 | ||
|             //    //if (MouseState == MouseState.SelectedElement)
 | ||
|             //    {
 | ||
|             //        MouseState = MouseState.Normal;
 | ||
| 
 | ||
|             //        //Elements.ForEach(ele =>
 | ||
|             //        foreach (IShapeElement ele in Elements)
 | ||
|             //        {
 | ||
|             //            ele.State = ElementState.Normal;
 | ||
|             //        }
 | ||
|             //        //);
 | ||
|             //    }
 | ||
|             //}
 | ||
| 
 | ||
|             //Invalidate();
 | ||
|         }
 | ||
| 
 | ||
|         public void OnCanvasKeyDown(object sender, KeyEventArgs e)
 | ||
|         {
 | ||
|             if (e.KeyCode == Keys.Delete) //delete键
 | ||
|             {
 | ||
|                 Elements.Remove(Elements.FirstOrDefault(u => u.ID == CurrentElementId));
 | ||
|             }
 | ||
| 
 | ||
|             if (e.KeyData == Keys.Escape)  //Esc
 | ||
|             {
 | ||
|                 if (DrawTemplate != null /*&& (DrawTemplate as ElementBase).CreatePoints.Count > 0*/)
 | ||
|                 {
 | ||
|                     DrawTemplate.Initial();
 | ||
|                 }
 | ||
|                 else
 | ||
|                 {
 | ||
|                     DrawTemplate = null;
 | ||
| 
 | ||
|                     if (MouseState != MouseState.Normal)
 | ||
|                     {
 | ||
|                         MouseState = MouseState.Normal;
 | ||
|                     }
 | ||
|                     else
 | ||
|                     {
 | ||
|                         Elements.ToList().ForEach(u => u.State = ElementState.Normal);
 | ||
|                     }
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|             //if (e.KeyData == Keys.Up)
 | ||
|             //{
 | ||
|             //    Elements.ToList().ForEach(u =>
 | ||
|             //    {
 | ||
|             //        if (u.State == ElementState.Selected)
 | ||
|             //        {
 | ||
|             //            u.Translate(0, -1);
 | ||
|             //        }
 | ||
|             //    });
 | ||
|             //}
 | ||
| 
 | ||
|             //if (e.KeyData == Keys.Down)
 | ||
|             //{
 | ||
|             //    Elements.ToList().ForEach(u =>
 | ||
|             //    {
 | ||
|             //        if (u.State == ElementState.Selected)
 | ||
|             //        {
 | ||
|             //            u.Translate(0, 1);
 | ||
|             //        }
 | ||
|             //    });
 | ||
|             //}
 | ||
| 
 | ||
|             //if (e.KeyData == Keys.Left)
 | ||
|             //{
 | ||
|             //    Elements.ToList().ForEach(u =>
 | ||
|             //    {
 | ||
|             //        if (u.State == ElementState.Selected)
 | ||
|             //        {
 | ||
|             //            u.Translate(-1, 0);
 | ||
|             //        }
 | ||
|             //    });
 | ||
|             //}
 | ||
| 
 | ||
|             //if (e.KeyData == Keys.Right)
 | ||
|             //{
 | ||
|             //    Elements.ToList().ForEach(u =>
 | ||
|             //    {
 | ||
|             //        if (u.State == ElementState.Selected)
 | ||
|             //        {
 | ||
|             //            u.Translate(1, 0);
 | ||
|             //        }
 | ||
|             //    });
 | ||
|             //}
 | ||
| 
 | ||
|             Invalidate();
 | ||
|         }
 | ||
|         #endregion
 | ||
| 
 | ||
|         #region 基元的设备属性 运动设置和相机设置
 | ||
|         public Action<IShapeElement> SetElementDevicePara;
 | ||
| 
 | ||
|         public Action<IShapeElement> SetDeviceByElement;
 | ||
|         #endregion
 | ||
| 
 | ||
|         #region Grid
 | ||
|         private bool showGrid = false;
 | ||
|         public bool ShowGrid
 | ||
|         {
 | ||
|             get => showGrid;
 | ||
|             set
 | ||
|             {
 | ||
|                 showGrid = value;
 | ||
|                 Invalidate();
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         private int gridValue = 0;
 | ||
|         public int GridValue
 | ||
|         {
 | ||
|             get => gridValue;
 | ||
|             set
 | ||
|             {
 | ||
|                 gridValue = value;
 | ||
|                 Invalidate();
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         private Pen penGrid = new Pen(Color.FromArgb(120, Color.Red), 1.0f);
 | ||
|         public Pen Pen_Grid
 | ||
|         {
 | ||
|             get => penGrid;
 | ||
|             set
 | ||
|             {
 | ||
|                 penGrid = value;
 | ||
|                 Invalidate();
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         readonly int _minGridStep = 10;
 | ||
|         #endregion
 | ||
| 
 | ||
|         #region Dispose
 | ||
|         /// <summary> 
 | ||
|         /// 清理所有正在使用的资源。
 | ||
|         /// </summary>
 | ||
|         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
 | ||
|         protected override void Dispose(bool disposing)
 | ||
|         {
 | ||
|             MAP?.Dispose();
 | ||
|             Matrix?.Dispose();
 | ||
|             penGrid?.Dispose();
 | ||
| 
 | ||
|             if (disposing && (components != null))
 | ||
|             {
 | ||
|                 components.Dispose();
 | ||
|             }
 | ||
|             base.Dispose(disposing);
 | ||
|         }
 | ||
|         #endregion
 | ||
|     }
 | ||
| }
 |