using CoreUnit.ScannerCanvasCoreUnit; using GUI.Properties; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms; namespace CoreUnit.Control.UserControl.Canvas { public class CanvasWrapper : ICanvas { CanvasCtrl m_canvas; Graphics m_graphics; Rectangle m_rect; public CanvasWrapper(CanvasCtrl canvas) { m_canvas = canvas; m_graphics = null; m_rect = new Rectangle(); } public CanvasWrapper(CanvasCtrl canvas, Graphics graphics, Rectangle clientrect) { m_canvas = canvas; m_graphics = graphics; m_rect = clientrect; } public IModel Model { get { return m_canvas.Model; } } public CanvasCtrl CanvasCtrl { get { return m_canvas; } } public void Dispose() { m_graphics = null; } #region ICanvas Members public IModel DataModel { get { return m_canvas.Model; } } public UnitPoint ScreenTopLeftToUnitPoint() { return m_canvas.ScreenTopLeftToUnitPoint(); } public UnitPoint ScreenBottomRightToUnitPoint() { return m_canvas.ScreenBottomRightToUnitPoint(); } public PointF ToScreen(UnitPoint unitpoint) { return m_canvas.ToScreen(unitpoint); } public float ToScreen(double unitvalue) { return m_canvas.ToScreen(unitvalue); } public double ToUnit(float screenvalue) { return m_canvas.ToUnit(screenvalue); } public UnitPoint ToUnit(PointF screenpoint) { return m_canvas.ToUnit(screenpoint); } public Graphics Graphics { get { return m_graphics; } } public Rectangle ClientRectangle { get { return m_rect; } set { m_rect = value; } } public Pen CreatePen(Color color, float unitWidth) { return m_canvas.CreatePen(color, unitWidth); } public void DrawLine(ICanvas canvas, Pen pen, UnitPoint p1, UnitPoint p2) { m_canvas.DrawLine(canvas, pen, p1, p2); } public void DrawArc(ICanvas canvas, Pen pen, UnitPoint center, float radius, float beginangle, float angle) { m_canvas.DrawArc(canvas, pen, center, radius, beginangle, angle); } public void DrawArc(ICanvas canvas, Pen pen, UnitPoint center, UnitPoint start, UnitPoint end, bool clockwise) { float radius = (float)HitUtil.Distance(center, start); float startAngle = (float)HitUtil.RadiansToDegrees(HitUtil.LineAngleR(center, start, 0)); float endAngle = (float)HitUtil.RadiansToDegrees(HitUtil.LineAngleR(center, end, 0)); float sweepAngle = 0; if (clockwise) { sweepAngle = (-1) * Math.Abs(startAngle - endAngle); if (sweepAngle < -180) { sweepAngle = (360 + sweepAngle) * (-1); } m_canvas.DrawArc(canvas, pen, center, radius, startAngle, sweepAngle); } else { sweepAngle = Math.Abs(startAngle - endAngle); if (sweepAngle > 180) { sweepAngle = (360 - sweepAngle); } m_canvas.DrawArc(canvas, pen, center, radius, startAngle, sweepAngle); } } public void DrawEllipse(ICanvas canvas, Pen pen, UnitPoint center, List points, float startangle, float endangle, float angle) { // 주어진 points 를 center 중심으로 angle 이 적용되지 않은 상태로 만든다 var unRotatePoints = points.Select(pt => HitUtil.RotatePoint(-angle, pt, center)); // angle 이 적용되지 않은 상태의 rect 영역을 구한다 double minX = unRotatePoints.Min(pt => pt.X); double minY = unRotatePoints.Min(pt => pt.Y); double maxX = unRotatePoints.Max(pt => pt.X); double maxY = unRotatePoints.Max(pt => pt.Y); double w = Math.Abs(maxX - minX); double h = Math.Abs(maxY - minY); w = w == 0 ? 1 : w; h = h == 0 ? 1 : h; RectangleF rect = ScreenUtils.GetRect(minX, minY + h, w, h); m_canvas.DrawEllipse(canvas, pen, center, rect, startangle, endangle, angle); } public void DrawLines(ICanvas canvas, Pen pen, List points) //연속된 라인을 그림 { for (int i = 0; i < points.Count; i++) { DrawLine(canvas, pen, points[i], points[i + 1 - (i / (points.Count - 1)) * points.Count]); } } public void Invalidate(bool dostatic) { m_canvas.DoInvalidate(dostatic); } public IDrawObject CurrentObject { get { return m_canvas.NewObject; } } public float BackgroundSize { get { return m_canvas.BackgroundSize; } } #endregion //스캐너 param값을 변경할 경우에 색상값을 변경함. public void UpdateObjectsColor(Color color) { foreach (ICanvasLayer layer in Model.Layers) { if (layer.Visible == false) continue; LoopUpdateObjectColor(layer.Objects, color); } Invalidate(true); } /// /// 안오산-160824-스캐너 패러미터에서 color 변경시 선택된 번호만 변경되도록 수정 /// /// /// public void UpdateObjectsColor(Color color, int index) { foreach (ICanvasLayer layer in Model.Layers) { if (layer.Visible == false) continue; LoopUpdateObjectColor(layer.Objects, color, index); } Invalidate(true); m_canvas.DoInvalidate(true); } private void LoopUpdateObjectColor(List objects, Color color) { foreach (IDrawObject obj in objects) { if (obj is Line) { //ScannerParam param = Canvas.DataModel.ScannerParams[((Line)obj).ScannerParamNo]; //obj.Color = param.Color; obj.Color = color; } else if (obj is Dot) { obj.Color = color; } else if (obj is Spline) { obj.Color = color; } else if (obj is SnowMan) { obj.Color = color; } else if (obj is Arc) { obj.Color = color; } else if (obj is Group) { LoopUpdateObjectColor(((Group)obj).SubObjects, color); } } } private void LoopUpdateObjectColor(List objects, Color color, int index) { foreach (IDrawObject obj in objects) { if (obj is Line) { if (obj.ScannerParamID == index + 1) { obj.Color = color; } } else if (obj is Dot) { if (obj.ScannerParamID == index + 1) { obj.Color = color; } } else if (obj is Spline) { if (obj.ScannerParamID == index + 1) { obj.Color = color; } } else if (obj is SnowMan) { if (obj.ScannerParamID == index + 1) { obj.Color = color; } } else if (obj is Arc) { obj.Color = color; } else if (obj is Group) { LoopUpdateObjectColor(((Group)obj).SubObjects, color, index); } } } } public partial class CanvasCtrl : System.Windows.Forms.UserControl { public List scannerParamColorList = new List(); // 더블버퍼 테스트 private BufferedGraphicsContext context; private BufferedGraphics grafx; public void UpdateScannerParamColorList() { } public enum eCommandType { select, pan, move, copy, draw, edit, editNode, } ICanvasOwner m_owner; CursorCollection m_cursors = new CursorCollection(); IModel m_model; MoveHelper m_moveHelper = null; NodeMoveHelper m_nodeMoveHelper = null; public CanvasWrapper m_canvaswrapper = null; public eCommandType m_commandType = eCommandType.select; bool m_runningSnaps = true; Type[] m_runningSnapTypes = null; PointF m_mousedownPoint; IDrawObject m_newObject = null; float m_backgroundSize = 120.0f; IEditTool m_editTool = null; SelectionRectangle m_selection = null; string m_drawObjectType = string.Empty; string m_editToolId = string.Empty; Bitmap m_staticImage = null; bool m_staticDirty = true; ISnapPoint m_snappoint = null; bool m_locked = false; //동적 작업 금지 기능(Pan, Zoom, Node등) public enum eCanvasType { Teach, Monitor, Preview, } public eCanvasType m_canvasType = eCanvasType.Teach; //사용자 정의 motion/rotation offset값 이벤트 public delegate float EventHandlerGetOffsetValue(); public EventHandlerGetOffsetValue evtGetOffsetValue = null; public delegate float EventHandlerGetAngleOffsetValue(); public EventHandlerGetAngleOffsetValue evtGetAngleOffsetValue = null; public delegate List EventHandlerGetMarkingSimulationPositionList(); public EventHandlerGetMarkingSimulationPositionList evtGetMarkingSimulationPositionList = null; public delegate void EventHandlerChangeSnapMode(bool snapMode); public EventHandlerChangeSnapMode evtSnapModeChanged = null; public Bitmap StaticImage { get { lock (this) { return m_staticImage; } } set { lock (this) { m_staticImage = value; } } } public CanvasWrapper CanvasWrapper { get { return m_canvaswrapper; } set { m_canvaswrapper = value; } } public Type[] RunningSnaps { get { return m_runningSnapTypes; } set { m_runningSnapTypes = value; } } public bool RunningSnapsEnabled { get { return m_runningSnaps; } set { m_runningSnaps = value; if (!value) m_snappoint = null; evtSnapModeChanged?.Invoke(value); } } System.Drawing.Drawing2D.SmoothingMode m_smoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; //System.Drawing.Drawing2D.SmoothingMode.HighSpeed; public System.Drawing.Drawing2D.SmoothingMode SmoothingMode { get { return m_smoothingMode; } set { m_smoothingMode = value; } } public IModel Model { get { return m_model; } set { m_model = value; } } public CanvasCtrl(ICanvasOwner owner, IModel datamodel, eCanvasType canvasType, bool locked = false) { m_canvaswrapper = new CanvasWrapper(this); m_owner = owner; m_model = datamodel; m_locked = locked; m_canvasType = canvasType; InitializeComponent(); this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); m_commandType = eCommandType.select; m_cursors.AddCursor(eCommandType.select, Cursors.Arrow); m_cursors.AddCursor(eCommandType.draw, Cursors.Cross); m_cursors.AddCursor(eCommandType.pan, Cursors.Hand); m_cursors.AddCursor(eCommandType.move, Cursors.SizeAll); m_cursors.AddCursor(eCommandType.copy, Cursors.SizeAll); m_cursors.AddCursor(eCommandType.edit, Cursors.Cross); UpdateCursor(); m_moveHelper = new MoveHelper(this); m_nodeMoveHelper = new NodeMoveHelper(m_canvaswrapper); //// 더블버퍼 설정 this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true); // Retrieves the BufferedGraphicsContext for the // current application domain. context = BufferedGraphicsManager.Current; // Sets the maximum size for the primary graphics buffer // of the buffered graphics context for the application // domain. Any allocation requests for a buffer larger // than this will create a temporary buffered graphics // context to host the graphics buffer. context.MaximumBuffer = new Size(this.ClientRectangle.Width + 1, this.ClientRectangle.Height + 1); // Allocates a graphics buffer the size of this form // using the pixel format of the Graphics created by // the Form.CreateGraphics() method, which returns a // Graphics object that matches the pixel format of the form. grafx = context.Allocate(this.CreateGraphics(), new Rectangle(0, 0, this.ClientRectangle.Width + 1, this.ClientRectangle.Height + 1)); // Draw the first frame to the buffer. //DrawToBuffer(grafx.Graphics, null); } private CanvasWrapper dc_buffer; private void DrawToBuffer(Graphics g, IDrawObject obj) { if (obj == null) return; //obj.Draw(dc_buffer, ClientRectangle); CanvasWrapper dc = new CanvasWrapper(this, Graphics.FromHwnd(Handle), ClientRectangle); RectangleF invalidaterect = ScreenUtils.ConvertRect(ScreenUtils.ToScreenNormalized(dc, obj.GetBoundingRect(dc))); obj.Draw(dc_buffer, invalidaterect); this.Refresh(); } public static object ChangeType(object value, Type type) { if (type == typeof(RectangleF)) return Common.CommonPropertyUtil.Parse(value.ToString(), type); return Common.CommonPropertyUtil.ChangeType(value, type); } public UnitPoint GetMousePoint() { Point point = this.PointToClient(System.Windows.Forms.Control.MousePosition); return ToUnit(point); } public void SetCenter(UnitPoint unitPoint) { PointF point = ToScreen(unitPoint); m_lastCenterPoint = unitPoint; SetCenterScreen(point, false); } public void SetCenter() { Point point = this.PointToClient(System.Windows.Forms.Control.MousePosition); SetCenterScreen(point, true); } public UnitPoint GetCenter() { return ToUnit(new PointF(this.ClientRectangle.Width / 2, this.ClientRectangle.Height / 2)); } protected void SetCenterScreen(PointF screenPoint, bool setCursor) { float centerX = ClientRectangle.Width / 2; m_panOffset.X += centerX - screenPoint.X; float centerY = ClientRectangle.Height / 2; m_panOffset.Y += centerY - screenPoint.Y; if (setCursor) Cursor.Position = this.PointToScreen(new Point((int)centerX, (int)centerY)); DoInvalidate(true); } protected override void OnPaint(PaintEventArgs e) { grafx.Render(e.Graphics); ClearPens(); e.Graphics.SmoothingMode = m_smoothingMode; CanvasWrapper dc = new CanvasWrapper(this, e.Graphics, ClientRectangle); Rectangle cliprectangle = e.ClipRectangle; if (m_staticImage == null) { cliprectangle = ClientRectangle; m_staticImage = new Bitmap(ClientRectangle.Width, ClientRectangle.Height); m_staticDirty = true; } RectangleF r = ScreenUtils.ToUnitNormalized(dc, cliprectangle); if (float.IsNaN(r.Width) || float.IsInfinity(r.Width)) { r = ScreenUtils.ToUnitNormalized(dc, cliprectangle); } if (m_staticDirty) { m_staticDirty = false; CanvasWrapper dcStatic = new CanvasWrapper(this, Graphics.FromImage(m_staticImage), ClientRectangle); dcStatic.Graphics.SmoothingMode = m_smoothingMode; //1.Background 그림 if (((DataModel)Model).EnableCanvasColor == false) { m_model.BackgroundLayer.BackgroundColor = Color.Black; m_model.BackgroundLayer.FieldColor = Color.White; } m_model.BackgroundLayer.Draw(dcStatic, r); //2.1.Scanner Field Scan Image 그림 if ((((DataModel)Model).CanvasImageEnable == true) && (((DataModel)Model).CanvasImage != null)) { DrawScoutImage(dcStatic); } //2.2. Grid 그림 if (((DataModel)Model).EnableCanvasGrid == true)//(m_model.GridLayer.Enabled) { m_model.GridLayer.Draw(dcStatic, r); } //3.중심 십자선을 그림 PointF nullPoint = ToScreen(new UnitPoint(0, 0)); dcStatic.Graphics.DrawLine(Pens.Blue, nullPoint.X - 10, nullPoint.Y, nullPoint.X + 10, nullPoint.Y); dcStatic.Graphics.DrawLine(Pens.Blue, nullPoint.X, nullPoint.Y - 10, nullPoint.X, nullPoint.Y + 10); //4.Drawlayer 드림 ICanvasLayer[] layers = m_model.Layers; for (int layerindex = layers.Length - 1; layerindex >= 0; layerindex--) { if ((layers[layerindex] == m_model.ActiveLayer) && layers[layerindex].Visible) { layers[layerindex].Draw(dcStatic, r); } } //시뮬레이션 그리기 if (m_canvasType == eCanvasType.Monitor && evtGetMarkingSimulationPositionList != null) { List pointList = new List(); pointList = evtGetMarkingSimulationPositionList(); foreach (UnitPoint point in pointList) { PointF location = dcStatic.ToScreen(point); Rectangle rect = new Rectangle((int)Math.Round(location.X, 0, MidpointRounding.AwayFromZero) - 2, (int)Math.Round(location.Y, 0, MidpointRounding.AwayFromZero) - 2, 4, 4); dcStatic.Graphics.FillEllipse(Brushes.Red, rect); } } dcStatic.Dispose(); } e.Graphics.DrawImage(m_staticImage, cliprectangle, cliprectangle, GraphicsUnit.Pixel); //선택된 객체의 선택 모양을 그림 foreach (IDrawObject drawobject in m_model.SelectedObjects) { drawobject.Draw(dc, r); } //현재 새로운 객체가 그려지고 있으면 그림. if (m_newObject != null) { m_newObject.Draw(dc, r); } if (m_snappoint != null) { m_snappoint.Draw(dc); } if (m_selection != null) { m_selection.Reset(); m_selection.SetMousePoint(e.Graphics, this.PointToClient(System.Windows.Forms.Control.MousePosition)); } if (m_moveHelper.IsEmpty == false) { m_moveHelper.DrawObjects(dc, r); } if (m_nodeMoveHelper.IsEmpty == false) { m_nodeMoveHelper.DrawObjects(dc, r); } dc.Dispose(); ClearPens(); } void RepaintStatic(Rectangle r) { if (m_staticImage == null) return; Graphics dc = Graphics.FromHwnd(Handle); if (r.X < 0) r.X = 0; if (r.X > m_staticImage.Width) r.X = 0; if (r.Y < 0) r.Y = 0; if (r.Y > m_staticImage.Height) r.Y = 0; if (r.Width > m_staticImage.Width || r.Width < 0) r.Width = m_staticImage.Width; if (r.Height > m_staticImage.Height || r.Height < 0) r.Height = m_staticImage.Height; dc.DrawImage(m_staticImage, r, r, GraphicsUnit.Pixel); dc.Dispose(); } void RepaintSnappoint(ISnapPoint snappoint) { if (snappoint == null) return; CanvasWrapper dc = new CanvasWrapper(this, Graphics.FromHwnd(Handle), ClientRectangle); snappoint.Draw(dc); dc.Graphics.Dispose(); dc.Dispose(); } void RepaintObject(IDrawObject obj) { if (obj == null) return; CanvasWrapper dc = new CanvasWrapper(this, Graphics.FromHwnd(Handle), ClientRectangle); RectangleF invalidaterect = ScreenUtils.ConvertRect(ScreenUtils.ToScreenNormalized(dc, obj.GetBoundingRect(dc))); obj.Draw(dc, invalidaterect); dc.Graphics.Dispose(); dc.Dispose(); } void RepaintObjects(List objects) { CanvasWrapper dc = new CanvasWrapper(this, Graphics.FromHwnd(Handle), ClientRectangle); foreach (IDrawObject obj in objects) { if (obj == null) continue; RectangleF invalidaterect = ScreenUtils.ConvertRect(ScreenUtils.ToScreenNormalized(dc, obj.GetBoundingRect(dc))); obj.Draw(dc, invalidaterect); } dc.Graphics.Dispose(); dc.Dispose(); } public void DoInvalidate(bool dostatic, RectangleF rect) { if (dostatic) m_staticDirty = true; Invalidate(ScreenUtils.ConvertRect(rect)); } public void DoInvalidate(bool dostatic) { if (dostatic) m_staticDirty = true; Invalidate(); } public IDrawObject NewObject { get { return m_newObject; } } public float BackgroundSize { get { return m_backgroundSize; } set { m_backgroundSize = value; } } protected void HandleSelection(List selected) { bool add = System.Windows.Forms.Control.ModifierKeys == Keys.Shift; bool toggle = System.Windows.Forms.Control.ModifierKeys == Keys.Control; bool invalidate = false; bool anyoldsel = false; int selcount = 0; if (selected != null) selcount = selected.Count; foreach (IDrawObject obj in m_model.SelectedObjects) { anyoldsel = true; break; } if (toggle && selcount > 0) { invalidate = true; foreach (IDrawObject obj in selected) { if (m_model.IsSelected(obj)) m_model.RemoveSelectedObject(obj); else m_model.AddSelectedObject(obj); } } if (add && selcount > 0) { invalidate = true; foreach (IDrawObject obj in selected) m_model.AddSelectedObject(obj); } if (add == false && toggle == false && selcount > 0) { invalidate = true; m_model.ClearSelectedObjects(); foreach (IDrawObject obj in selected) m_model.AddSelectedObject(obj); } if (add == false && toggle == false && selcount == 0 && anyoldsel) { invalidate = true; m_model.ClearSelectedObjects(); } if (invalidate) DoInvalidate(false); } void FinishNodeEdit() { m_commandType = eCommandType.select; m_snappoint = null; } protected virtual void HandleMouseDownWhenDrawing(UnitPoint mouseunitpoint, ISnapPoint snappoint) { if (m_commandType == eCommandType.draw) { if (m_drawObjectType == "Dot" || m_drawObjectType == "Spline") { m_newObject = m_model.CreateObject(m_drawObjectType, mouseunitpoint, snappoint); DoInvalidate(false, m_newObject.GetBoundingRect(m_canvaswrapper)); eDrawObjectMouseDown result = m_newObject.OnMouseDown(m_canvaswrapper, mouseunitpoint, snappoint); switch (result) { case eDrawObjectMouseDown.Done: m_model.AddObject(m_model.ActiveLayer, m_newObject); m_newObject = null; CommandEscape(); DoInvalidate(true); break; case eDrawObjectMouseDown.DoneRepeat: m_model.AddObject(m_model.ActiveLayer, m_newObject); m_newObject = m_model.CreateObject(m_newObject.Type, m_newObject.RepeatStartingPoint, null); DoInvalidate(true); break; case eDrawObjectMouseDown.Continue: break; } } else { if (m_newObject == null) { m_newObject = m_model.CreateObject(m_drawObjectType, mouseunitpoint, snappoint); DoInvalidate(false, m_newObject.GetBoundingRect(m_canvaswrapper)); } else { if (m_newObject != null) { eDrawObjectMouseDown result = m_newObject.OnMouseDown(m_canvaswrapper, mouseunitpoint, snappoint); switch (result) { case eDrawObjectMouseDown.Done: m_model.AddObject(m_model.ActiveLayer, m_newObject); m_newObject = null; CommandEscape(); DoInvalidate(true); break; case eDrawObjectMouseDown.DoneRepeat: m_model.AddObject(m_model.ActiveLayer, m_newObject); m_newObject = m_model.CreateObject(m_newObject.Type, m_newObject.RepeatStartingPoint, null); DoInvalidate(true); break; case eDrawObjectMouseDown.Continue: break; } } } } } } protected override void OnMouseDoubleClick(MouseEventArgs e) { base.OnMouseDoubleClick(e); if (e.Button == MouseButtons.Middle) { CommandScaleToFit(); CommandCenter(); } } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); m_mousedownPoint = new PointF(e.X, e.Y); // used when panning m_dragOffset = new PointF(0, 0); if (m_canvasType == eCanvasType.Teach && e.Button == MouseButtons.Left) { UnitPoint mousepoint = ToUnit(m_mousedownPoint); if (m_snappoint != null) mousepoint = m_snappoint.SnapPoint; if (m_commandType == eCommandType.editNode) { bool handled = false; if (m_nodeMoveHelper.HandleMouseDown(mousepoint, ref handled)) { FinishNodeEdit(); base.OnMouseDown(e); return; } } if (m_commandType == eCommandType.select) { bool handled = false; if (m_nodeMoveHelper.HandleMouseDown(mousepoint, ref handled)) { m_commandType = eCommandType.editNode; m_snappoint = null; base.OnMouseDown(e); return; } //// 히트 테스트 List hitlist = null; hitlist = m_model.GetHitObjects(m_canvaswrapper, mousepoint); bool isSwitchingCommand = false; if (hitlist != null) { foreach (IDrawObject obj in m_model.SelectedObjects) { if (obj.PointInObject(m_canvaswrapper, ToUnit(movingP))) { isSwitchingCommand = true; break; } } } //// 히트 됬다면. if (isSwitchingCommand) { DoInvalidate(true); CommandMove(); } else { m_selection = new SelectionRectangle(m_mousedownPoint); } } if ((m_commandType == eCommandType.move) || (m_commandType == eCommandType.copy)) { m_moveHelper.HandleMouseDownForMove(mousepoint, m_snappoint, m_commandType); } if (m_commandType == eCommandType.draw) { HandleMouseDownWhenDrawing(mousepoint, null); DoInvalidate(true); } if (m_commandType == eCommandType.edit) { if (m_editTool == null) m_editTool = m_model.GetEditTool(m_editToolId); if (m_editTool != null) { if (m_editTool.SupportSelection) m_selection = new SelectionRectangle(m_mousedownPoint); eDrawObjectMouseDown mouseresult = m_editTool.OnMouseDown(m_canvaswrapper, mousepoint, m_snappoint); /* if (mouseresult == eDrawObjectMouseDown.Continue) { if (m_editTool.SupportSelection) m_selection = new SelectionRectangle(m_mousedownPoint); } * */ if (mouseresult == eDrawObjectMouseDown.Done) { m_editTool.Finished(); m_editTool = m_model.GetEditTool(m_editToolId); // continue with new tool //m_editTool = null; if (m_editTool.SupportSelection) m_selection = new SelectionRectangle(m_mousedownPoint); } } DoInvalidate(true); UpdateCursor(); } } } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if ((m_locked == false) && (m_commandType == eCommandType.pan || e.Button == MouseButtons.Middle)) { m_panOffset.X += m_dragOffset.X; m_panOffset.Y += m_dragOffset.Y; m_dragOffset = new PointF(0, 0); } List hitlist = null; Rectangle screenSelRect = Rectangle.Empty; if (m_selection != null) { screenSelRect = m_selection.ScreenRect(); RectangleF selectionRect = m_selection.Selection(m_canvaswrapper); if (selectionRect != RectangleF.Empty) { // is any selection rectangle. use it for selection // 파워포인트와 동일하게 직사각형이 모든 객체를 포함할 때만 선택되도록 설정. //hitlist = m_model.GetHitObjects(m_canvaswrapper, selectionRect, m_selection.AnyPoint()); hitlist = m_model.GetHitObjects(m_canvaswrapper, selectionRect, false); DoInvalidate(true); } else { // else use mouse point UnitPoint mousepoint = ToUnit(new PointF(e.X, e.Y)); hitlist = m_model.GetHitObjects(m_canvaswrapper, mousepoint); } m_selection = null; } if (m_commandType == eCommandType.select) { if (hitlist != null) { HandleSelection(hitlist); if (hitlist.Count != 0) { ((DataModel)Model).evtSelectObjects(hitlist); } } } if (m_commandType == eCommandType.move)//&& isSwitchingCommand) // ToolStrip에서 Move 버튼 제외할꺼라면, isSwitchingCommand 필요없음. { UnitPoint mousepoint = ToUnit(new PointF(e.X, e.Y)); m_moveHelper.HandleMouseDownForMove(mousepoint, m_snappoint, m_commandType); } if (m_commandType == eCommandType.edit && m_editTool != null) { UnitPoint mousepoint = ToUnit(m_mousedownPoint); if (m_snappoint != null) mousepoint = m_snappoint.SnapPoint; if (screenSelRect != Rectangle.Empty) m_editTool.SetHitObjects(mousepoint, hitlist); m_editTool.OnMouseUp(m_canvaswrapper, mousepoint, m_snappoint); } if (m_commandType == eCommandType.draw && m_newObject != null) { UnitPoint mousepoint = ToUnit(m_mousedownPoint); if (m_snappoint != null) mousepoint = m_snappoint.SnapPoint; m_newObject.OnMouseUp(m_canvaswrapper, mousepoint, m_snappoint); } } protected PointF movingP; protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (m_selection != null) { Graphics dc = Graphics.FromHwnd(Handle); m_selection.SetMousePoint(dc, new PointF(e.X, e.Y)); dc.Dispose(); return; } if ((m_locked == false) && (m_commandType == eCommandType.pan) && e.Button == MouseButtons.Left) { m_dragOffset.X = -(m_mousedownPoint.X - e.X); m_dragOffset.Y = -(m_mousedownPoint.Y - e.Y); m_lastCenterPoint = CenterPointUnit(); DoInvalidate(true); } if (e.Button == MouseButtons.Middle) { m_dragOffset.X = -(m_mousedownPoint.X - e.X); m_dragOffset.Y = -(m_mousedownPoint.Y - e.Y); m_lastCenterPoint = CenterPointUnit(); DoInvalidate(true); } UnitPoint mousepoint; UnitPoint unitpoint = ToUnit(new PointF(e.X, e.Y)); movingP = new PointF(e.X, e.Y); if (m_commandType == eCommandType.draw || m_commandType == eCommandType.move || m_nodeMoveHelper.IsEmpty == false || m_commandType == eCommandType.copy) { Rectangle invalidaterect = Rectangle.Empty; ISnapPoint newsnap = null; mousepoint = GetMousePoint(); if (RunningSnapsEnabled) newsnap = m_model.SnapPoint(m_canvaswrapper, mousepoint, m_runningSnapTypes, null); if (newsnap == null) newsnap = m_model.GridLayer.SnapPoint(m_canvaswrapper, mousepoint, null); if ((m_snappoint != null) && ((newsnap == null) || (newsnap.SnapPoint != m_snappoint.SnapPoint) || m_snappoint.GetType() != newsnap.GetType())) { invalidaterect = ScreenUtils.ConvertRect(ScreenUtils.ToScreenNormalized(m_canvaswrapper, m_snappoint.BoundingRect)); invalidaterect.Inflate(2, 2); RepaintStatic(invalidaterect); // remove old snappoint m_snappoint = newsnap; } if (m_commandType == eCommandType.move || m_commandType == eCommandType.copy) Invalidate(invalidaterect); if (m_snappoint == null) m_snappoint = newsnap; } m_owner.SetPositionInfo(unitpoint); m_owner.SetSnapInfo(m_snappoint); //UnitPoint mousepoint; if (m_snappoint != null) mousepoint = m_snappoint.SnapPoint; else mousepoint = GetMousePoint(); if (m_newObject != null) { // 기존을 DoubleBuffer 활용하도록 변경. //Rectangle invalidaterect = ScreenUtils.ConvertRect(ScreenUtils.ToScreenNormalized(m_canvaswrapper, m_newObject.GetBoundingRect(m_canvaswrapper))); //invalidaterect.Inflate(2, 2); // 이부분이 원인. //RepaintStatic(ClientRectangle); // 임시 방편 //RepaintStatic(invalidaterect); m_newObject.OnMouseMove(m_canvaswrapper, mousepoint); DrawToBuffer(grafx.Graphics, m_newObject); //RepaintObject(m_newObject); } else { dc_buffer = new CanvasWrapper(this, grafx.Graphics, ClientRectangle); } if (m_snappoint != null) RepaintSnappoint(m_snappoint); if (m_moveHelper.HandleMouseMoveForMove(mousepoint)) Refresh(); //Invalidate(); RectangleF rNoderect = m_nodeMoveHelper.HandleMouseMoveForNode(mousepoint); if (rNoderect != RectangleF.Empty) { //// 기존 코드를 더블 버퍼 활용하게 변경. //Rectangle invalidaterect = ScreenUtils.ConvertRect(ScreenUtils.ToScreenNormalized(m_canvaswrapper, rNoderect)); //RepaintStatic(invalidaterect); //CanvasWrapper dc = new CanvasWrapper(this, Graphics.FromHwnd(Handle), ClientRectangle); //dc.Graphics.Clip = new Region(ClientRectangle); // m_nodeMoveHelper.DrawOriginalObjects(dc, rNoderect); m_nodeMoveHelper.DrawObjects(dc_buffer, rNoderect); if (m_snappoint != null) RepaintSnappoint(m_snappoint); this.Refresh(); //dc.Graphics.Dispose(); //dc.Dispose(); } } protected void CalcScreen(PointF p, float z0, float z1) { //// Screen의 좌표(PointF)는 변화가 없어야 함. (같은 위치에 커서가 위치하여야하므로) //// Zoom에 따른 Unit을 구하여줌. 이 차를 구함. UnitToScreen 활용 PanOffset에 작용. UnitPoint pointDistance0 = ZoomToUnit(p, z0), pointDistance1 = ZoomToUnit(p, z1);// UnitPoint pointDistance2 = new UnitPoint(0, 0); pointDistance2.X = pointDistance1.X - pointDistance0.X; pointDistance2.Y = pointDistance1.Y - pointDistance0.Y; PointF screen = new PointF(0, 0); screen = ChangePointByZoom(pointDistance2); m_panOffset.X += screen.X; m_panOffset.Y += screen.Y; } protected float m_minZoom = 1.2f; public float MinZoom { get { return m_minZoom; } set { m_minZoom = value; } } protected float m_maxZoom = 10.0f; public float MaxZoom { get { return m_maxZoom; } set { m_maxZoom = value; } } protected override void OnMouseWheel(MouseEventArgs e) { if (m_locked == false) { UnitPoint p = GetMousePoint(); float wheeldeltatick = 120; float zoomdelta = (1.25f * (Math.Abs(e.Delta) / wheeldeltatick)); float temporaryZoom = 0; float defaultZoom = m_model.Zoom; if (e.Delta < 0) temporaryZoom = m_model.Zoom / zoomdelta; else temporaryZoom = m_model.Zoom * zoomdelta; if (temporaryZoom > m_maxZoom) m_model.Zoom = m_maxZoom; else if (temporaryZoom < m_minZoom) m_model.Zoom = m_minZoom; else m_model.Zoom = temporaryZoom; CalcScreen(movingP, defaultZoom, m_model.Zoom); //SetCenterScreen(ToScreen(p), false); DoInvalidate(true); } base.OnMouseWheel(e); } protected override void OnResize(EventArgs e) { base.OnResize(e); if (m_lastCenterPoint != UnitPoint.Empty && Width != 0) { SetCenterScreen(ToScreen(m_lastCenterPoint), false); } m_lastCenterPoint = new UnitPoint(0, 0);// CenterPointUnit(); m_staticImage = null; DoInvalidate(true); } UnitPoint m_lastCenterPoint; PointF m_panOffset = new PointF(25, -25); PointF m_dragOffset = new PointF(0, 0); const float m_screenResolution = 96; //96dpi에서 96dpi는 1inch const float m_inchTommRatio = 25.4f; //계산된 inch에서 mm으로 unit 변경 PointF Translate(UnitPoint point) { return point.Point; } public float ScreenHeight() { return (float)(ToUnit(this.ClientRectangle.Height) / m_model.Zoom); } public float ScreenWidth() { return (float)(ToUnit(this.ClientRectangle.Width) / m_model.Zoom); } #region ICanvas public UnitPoint CenterPointUnit() { UnitPoint p1 = ScreenTopLeftToUnitPoint(); UnitPoint p2 = ScreenBottomRightToUnitPoint(); UnitPoint center = new UnitPoint(); center.X = (p1.X + p2.X) / 2; center.Y = (p1.Y + p2.Y) / 2; return center; } public UnitPoint ScreenTopLeftToUnitPoint() { return ToUnit(new PointF(0, 0)); } public UnitPoint ScreenBottomRightToUnitPoint() { return ToUnit(new PointF(this.ClientRectangle.Width, this.ClientRectangle.Height)); } public PointF ToScreen(UnitPoint point) { PointF transformedPoint = Translate(point); transformedPoint.Y = -transformedPoint.Y; // ScreenHeight 제외 transformedPoint.Y *= ((m_screenResolution * m_model.Zoom) / m_inchTommRatio); transformedPoint.X *= ((m_screenResolution * m_model.Zoom) / m_inchTommRatio); transformedPoint.X += m_panOffset.X + m_dragOffset.X; transformedPoint.Y += m_panOffset.Y + m_dragOffset.Y; return transformedPoint; } public PointF ChangePointByZoom(UnitPoint point) { PointF transformedPoint = Translate(point); // transformedPoint.X = transformedPoint.X - ScreenWidth(); transformedPoint.Y = -transformedPoint.Y; transformedPoint.Y *= ((m_screenResolution * m_model.Zoom) / m_inchTommRatio); transformedPoint.X *= ((m_screenResolution * m_model.Zoom) / m_inchTommRatio); //transformedPoint.X += m_panOffset.X + m_dragOffset.X; //transformedPoint.Y += m_panOffset.Y + m_dragOffset.Y; return transformedPoint; } public float ToScreen(double value) { return (float)((value / m_inchTommRatio) * m_screenResolution * m_model.Zoom); } public double ToUnit(float screenvalue) { return (double)(screenvalue / (double)(m_screenResolution * m_model.Zoom)) * m_inchTommRatio; } public UnitPoint ToUnit(PointF screenpoint) { float panoffsetX = m_panOffset.X + m_dragOffset.X; float panoffsetY = m_panOffset.Y + m_dragOffset.Y; float xpos = ((screenpoint.X - panoffsetX) / (m_screenResolution * m_model.Zoom)) * m_inchTommRatio; float ypos = -(((screenpoint.Y - panoffsetY)) / (m_screenResolution * m_model.Zoom)) * m_inchTommRatio; // ScreenHeight() 필요없는 듯. return new UnitPoint(xpos, ypos); } public UnitPoint ZoomToUnit(PointF screenpoint, float Zoom) { float panoffsetX = m_panOffset.X + m_dragOffset.X; float panoffsetY = m_panOffset.Y + m_dragOffset.Y; float xpos = ((screenpoint.X - panoffsetX) / (m_screenResolution * Zoom)) * m_inchTommRatio; float ypos = 0 - (((screenpoint.Y - panoffsetY)) / (m_screenResolution * Zoom)) * m_inchTommRatio; return new UnitPoint(xpos, ypos); } public Pen CreatePen(Color color, float unitWidth) { return GetPen(color, ToScreen(unitWidth)); } public void DrawLine(ICanvas canvas, Pen pen, UnitPoint p1, UnitPoint p2) { PointF tmpp1 = ToScreen(p1); PointF tmpp2 = ToScreen(p2); canvas.Graphics.DrawLine(pen, tmpp1, tmpp2); } public void DrawArc(ICanvas canvas, Pen pen, UnitPoint center, float radius, float startAngle, float sweepAngle) { try { PointF p1 = ToScreen(center); radius = (float)Math.Round(ToScreen(radius)); RectangleF r = new RectangleF(p1, new SizeF()); r.Inflate(radius, radius); if (radius > 0 && radius < 1e8f) canvas.Graphics.DrawArc(pen, r, -startAngle, -sweepAngle); } catch (Exception e) { } } public void DrawRectangle(ICanvas canvas, Pen pen, RectangleF rectF) { Rectangle rect = ScreenUtils.ConvertRect(ScreenUtils.ToScreen(canvas, rectF)); canvas.Graphics.DrawRectangle(pen, rect); } public void DrawEllipse(ICanvas canvas, Pen pen, UnitPoint center, RectangleF rectF, float startangle, float endangle, float angle) { // 화면 기준의 좌표값들을 구한다 PointF p = ToScreen(center); RectangleF rect = ScreenUtils.ToScreen(canvas, rectF); // 그래픽 컨텍스트를 angle 만큼 회전 canvas.Graphics.TranslateTransform((float)p.X, (float)p.Y); canvas.Graphics.RotateTransform(-angle); canvas.Graphics.TranslateTransform(-(float)p.X, -(float)p.Y); // 타원 대신 아크로 그린다 canvas.Graphics.DrawArc(pen, rect, startangle, endangle - startangle); // 그래픽 컨텍스트에 적용된 Transform 을 초기화 canvas.Graphics.ResetTransform(); } #endregion System.Drawing.Drawing2D.AdjustableArrowCap cusCap = new System.Drawing.Drawing2D.AdjustableArrowCap(3, 3); Dictionary> m_penCache = new Dictionary>(); Pen GetPen(Color color, float width) { if (m_penCache.ContainsKey(width) == false) m_penCache[width] = new Dictionary(); if (m_penCache[width].ContainsKey(color) == false) { m_penCache[width][color] = new Pen(color, width); } return m_penCache[width][color]; } void ClearPens() { m_penCache.Clear(); } void UpdateCursor() { Cursor = m_cursors.GetCursor(m_commandType); } Dictionary m_QuickSnap = new Dictionary(); public void AddQuickSnapType(Keys key, Type snaptype) { m_QuickSnap.Add(key, snaptype); } #region Command 함수 선언 public void CommandSelectDrawTool(string drawobjectType) { CommandEscape(); m_model.ClearSelectedObjects(); m_commandType = eCommandType.draw; m_drawObjectType = drawobjectType; UpdateCursor(); } public void CommandEscape() { bool dirty = (m_newObject != null) || (m_snappoint != null); m_newObject = null; m_snappoint = null; if (m_editTool != null) m_editTool.Finished(); m_editTool = null; m_commandType = eCommandType.select; m_moveHelper.HandleCancelMove(); m_nodeMoveHelper.HandleCancelMove(); DoInvalidate(dirty); UpdateCursor(); } public void CommandPan() { if (m_commandType == eCommandType.select || m_commandType == eCommandType.move) { m_commandType = eCommandType.pan; } UpdateCursor(); } public void CommandMove() { if (m_model.SelectedCount > 0) { m_commandType = eCommandType.move; UpdateCursor(); } } public void CommandDeleteSelected() { if (m_model.SelectedCount > 0) { m_model.DeleteObjects(m_model.SelectedObjects); m_model.ClearSelectedObjects(); DoInvalidate(true); UpdateCursor(); } } public void CommandEdit(string editid) { CommandEscape(); m_model.ClearSelectedObjects(); m_commandType = eCommandType.edit; m_editToolId = editid; m_editTool = m_model.GetEditTool(m_editToolId); UpdateCursor(); } public void CommandScaleToFit() { Model.Zoom = ((DataModel)Model).ScaleToFit; DoInvalidate(true); } public void CommandSetCenter(UnitPoint center) { SetCenter(center); DoInvalidate(true); } public void CommandCenter() { SetCenter(new UnitPoint(0, 0)); DoInvalidate(true); } public void CommandZoomIn() { float zoomdelta = Settings.Default.ZoomDeltaValue; m_model.Zoom -= m_model.Zoom / zoomdelta; DoInvalidate(true); } public void CommandZoomOut() { float zoomdelta = Settings.Default.ZoomDeltaValue; m_model.Zoom += m_model.Zoom / zoomdelta; DoInvalidate(true); } public void CommandSelectAll() { Model.ClearSelectedObjects(); foreach (IDrawObject obj in ((DataModel)Model).ActiveLayer.Objects) { Model.AddSelectedObject(obj); } DoInvalidate(false); } public void CommandSelect(int id, bool addMode = false) { CommandEscape(); ((DataModel)Model).SelectObject(id, addMode); DoInvalidate(false); } public void CommandDeselectAll() { Model.ClearSelectedObjects(); DoInvalidate(false); ((DataModel)Model).evtDeselectAllObjects(); } public void CommandGroup() { if (m_model.SelectedCount > 0) { ((DataModel)Model).GroupObjects(); DoInvalidate(true); } } public void CommandUngroup() { if (m_model.SelectedCount > 0) { ((DataModel)Model).UngroupObjects(); DoInvalidate(true); } } public void CommandChangeLayer(int no) { ((DataModel)Model).ChangeLayer(no); DoInvalidate(true); } public void CommandCopy() { if (m_model.SelectedCount > 0) { m_commandType = eCommandType.copy; UpdateCursor(); } } public void CommandDoUndo() { if (Model.DoUndo()) DoInvalidate(true); } public void CommandDoRedo() { if (Model.DoRedo()) DoInvalidate(true); } #endregion void HandleQuickSnap(KeyEventArgs e) { if (m_commandType == eCommandType.select || ((m_commandType == eCommandType.pan) && (m_locked == false))) { return; } ISnapPoint p = null; UnitPoint mousepoint = GetMousePoint(); if (m_QuickSnap.ContainsKey(e.KeyCode)) { p = m_model.SnapPoint(m_canvaswrapper, mousepoint, null, m_QuickSnap[e.KeyCode]); } if (p != null) { if (m_commandType == eCommandType.draw) { HandleMouseDownWhenDrawing(p.SnapPoint, p); if (m_newObject != null) m_newObject.OnMouseMove(m_canvaswrapper, GetMousePoint()); DoInvalidate(true); e.Handled = true; } if ((m_commandType == eCommandType.move) || (m_commandType == eCommandType.copy)) { m_moveHelper.HandleMouseDownForMove(p.SnapPoint, p, m_commandType); e.Handled = true; } if (m_nodeMoveHelper.IsEmpty == false) { bool handled = false; m_nodeMoveHelper.HandleMouseDown(p.SnapPoint, ref handled); FinishNodeEdit(); e.Handled = true; } if (m_commandType == eCommandType.edit) { } } } private List copies = new List(); private double iterationOffsetValue = 0; public void RunningSnapsModeChange() { RunningSnapsEnabled = !RunningSnapsEnabled; DoInvalidate(false); } protected override void OnKeyDown(KeyEventArgs e) { HandleQuickSnap(e); if (m_nodeMoveHelper.IsEmpty == false) { m_nodeMoveHelper.OnKeyDown(m_canvaswrapper, e); if (e.Handled) return; } base.OnKeyDown(e); if (e.Handled) { UpdateCursor(); return; } if (m_editTool != null) { m_editTool.OnKeyDown(m_canvaswrapper, e); if (e.Handled) return; } if (m_newObject != null) { m_newObject.OnKeyDown(m_canvaswrapper, e); if (e.Handled) return; } foreach (IDrawObject obj in m_model.SelectedObjects) { obj.OnKeyDown(m_canvaswrapper, e); if (e.Handled) return; } if ((System.Windows.Forms.Control.ModifierKeys & Keys.Control) == Keys.Control) { if (e.KeyCode >= Keys.D1 && e.KeyCode <= Keys.D9) { int id = e.KeyCode - Keys.D0; foreach (var obj in m_model.ActiveLayer.Objects) { if (obj.ScannerParamID == id) m_model.AddSelectedObject(obj); } DoInvalidate(true); } else { switch (e.KeyCode) { case Keys.G: m_model.GridLayer.Enabled = !m_model.GridLayer.Enabled; DoInvalidate(true); break; case Keys.S: RunningSnapsModeChange(); break; case Keys.Right: if (evtGetOffsetValue != null) { float offsetValue = evtGetOffsetValue(); ((DataModel)Model).RotateObjects((float)(-1 * offsetValue), Model.SelectedObjects, true); DoInvalidate(true); } break; case Keys.Left: if (evtGetOffsetValue != null) { float offsetValue = evtGetOffsetValue(); ((DataModel)Model).RotateObjects((float)offsetValue, Model.SelectedObjects, true); DoInvalidate(true); } break; case Keys.C: copies = new List(); foreach (IDrawObject obj in Model.SelectedObjects) { copies.Add(obj.Clone()); } iterationOffsetValue = 0; DoInvalidate(true); break; case Keys.V: if (copies.Count != 0) { double offsetValue = 3; ((DataModel)Model).CopyObjects(new UnitPoint(iterationOffsetValue + offsetValue, iterationOffsetValue + offsetValue), copies); iterationOffsetValue = iterationOffsetValue + offsetValue; DoInvalidate(true); } break; case Keys.Z: //Undo CommandDoUndo(); break; case Keys.Y: //Redo CommandDoRedo(); break; //키보드로 객체 이동 case Keys.Up://선택된 객체를 지정된 위치값 만큼 상승 if (evtGetOffsetValue != null) { float offsetValue = evtGetOffsetValue(); Model.MoveObjects(new UnitPoint(0, offsetValue), Model.SelectedObjects, true); DoInvalidate(true); } break; case Keys.Down://선택된 객체를 지정된 위치값 만큼 하강 if (evtGetOffsetValue != null) { float offsetValue = evtGetOffsetValue(); Model.MoveObjects(new UnitPoint(0, -1 * offsetValue), Model.SelectedObjects, true); DoInvalidate(true); } break; case Keys.A: foreach (var obj in m_model.ActiveLayer.Objects) { m_model.AddSelectedObject(obj); } break; } return; } } //if (e.KeyCode >= Keys.D1 && e.KeyCode <= Keys.D9) { // int layerindex = (int)e.KeyCode - (int)Keys.D1; // if (layerindex >= 0 && layerindex < m_model.Layers.Length) { // m_model.ActiveLayer = m_model.Layers[layerindex]; // DoInvalidate(true); // } //} //사용자 키보드 키에 대한 수행 switch (e.KeyCode) { case Keys.Escape: CommandEscape(); if (m_drawObjectType == "PolyLine") { CommandGroup(); } break; case Keys.M: CommandPan(); break; case Keys.F: CommandScaleToFit(); break; case Keys.C: CommandCenter(); break; case Keys.Delete: CommandDeleteSelected(); break; case Keys.O: // CommandEdit("linesmeet"); break; //키보드로 객체 이동 case Keys.Up://선택된 객체를 지정된 위치값 만큼 상승 if (evtGetOffsetValue != null) { float offsetValue = evtGetOffsetValue(); Model.MoveObjects(new UnitPoint(0, offsetValue), Model.SelectedObjects, true); DoInvalidate(true); } break; case Keys.Down://선택된 객체를 지정된 위치값 만큼 하강 if (evtGetOffsetValue != null) { float offsetValue = evtGetOffsetValue(); Model.MoveObjects(new UnitPoint(0, -1 * offsetValue), Model.SelectedObjects, true); DoInvalidate(true); } break; case Keys.Right://선택된 객체를 지정된 위치값 만큼 오른쪽으로 이동 if (evtGetOffsetValue != null) { float offsetValue = evtGetOffsetValue(); Model.MoveObjects(new UnitPoint(offsetValue, 0), Model.SelectedObjects, true); DoInvalidate(true); } break; case Keys.Left://선택된 객체를 지정된 위치값 만큼 왼쪽으로 이동 if (evtGetOffsetValue != null) { double offsetValue = evtGetOffsetValue(); Model.MoveObjects(new UnitPoint(-1 * offsetValue, 0), Model.SelectedObjects, true); DoInvalidate(true); } break; case Keys.E://선택된 객체를 지정된 각도값 만큼 시계방향으로 회전 if (evtGetAngleOffsetValue != null) { float angleOffset = evtGetAngleOffsetValue(); ((DataModel)Model).RotateObjects(-1 * (float)angleOffset, Model.SelectedObjects, true); DoInvalidate(true); } break; case Keys.Q://선택된 객체를 지정된 각도값 만큼 반시계방향으로 회전 if (evtGetAngleOffsetValue != null) { float angleOffset = evtGetAngleOffsetValue(); ((DataModel)Model).RotateObjects((float)angleOffset, Model.SelectedObjects, true); DoInvalidate(true); } break; default: break; } UpdateCursor(); } protected override bool IsInputKey(Keys keyData) { switch (keyData) { case Keys.Right: case Keys.Left: case Keys.Up: case Keys.Down: return true; case Keys.Shift | Keys.Right: case Keys.Shift | Keys.Left: case Keys.Shift | Keys.Up: case Keys.Shift | Keys.Down: return true; } return base.IsInputKey(keyData); } #region 스캔 필드 이미지 관련 함수 public void DrawScoutImage(ICanvas canvas) { try { UnitPoint pt = new UnitPoint(-m_owner.WorkSize.Width / 2, m_owner.WorkSize.Height / 2); PointF location = canvas.ToScreen(pt); RectangleF rect = new RectangleF(location, new SizeF(canvas.ToScreen(((DataModel)Model).CanvasImageSize.Width), canvas.ToScreen(((DataModel)Model).CanvasImageSize.Height))); canvas.Graphics.DrawImage(((DataModel)Model).CanvasImage, rect); } catch { } } public void SaveRoiImage(ICanvas canvas, RectangleF unitRect) { Rectangle screenRect = ScreenUtils.ConvertRect(unitRect); //Rectangle imageRect = ScreenUtils.ToUnitNormalized(canvas, screenRect); } #endregion } }