Regardless it possible use/benefit an AutoCAD user may find, here is the code to do this. Yes, as you may have guessed, I used TransientGraphics again.
Here is the class that do the dynamic dragging. At the end of AngledDrag() call, the class provides two points (Point3d) - StartPoint and EndPoint as public read-only properties for the calling procedure to use.
using System; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.GraphicsInterface; namespace AngleLockedDrag { public class AngledDrag { private Document _dwg; private Database _db; private Editor _editor; private Point3d _startPoint = new Point3d(0.0, 0.0, 0.0); private Point3d _endPoint = new Point3d(0.0, 0.0, 0.0); private double _dragAngle = 45.0; private Line _dragLine = null; private int _colorIndex = 1; public AngledDrag(Document dwg) { _dwg = dwg; _db = dwg.Database; _editor = dwg.Editor; } public Point3d StartPoint { get { return _startPoint; } } public Point3d EndPoint { get { return _endPoint; } } #region public methods public bool DragAtAngle() { _endPoint = _startPoint; _editor.PointMonitor += new PointMonitorEventHandler(Editor_PointMonitor); try { //Get end point if (GetEndPoint()) { return true; } else { return false; } } finally { ClearTransientGraphics(); _editor.PointMonitor -= Editor_PointMonitor; } } #endregion #region private methods private void Editor_PointMonitor( object sender, PointMonitorEventArgs e) { DrawDragLine(e.Context.RawPoint); if (_dragLine != null) { e.AppendToolTipText("Angle: " + _dragAngle.ToString() + "\nLength: " + _dragLine.Length.ToString()); } else { e.AppendToolTipText(""); } } private void DrawDragLine(Point3d mousePoint) { ClearTransientGraphics(); Point3d pt = CalculateEndPoint(mousePoint); _dragLine = new Line(_startPoint, pt); _dragLine.SetDatabaseDefaults(_db); _dragLine.ColorIndex = _colorIndex; IntegerCollection col = new IntegerCollection(); TransientManager.CurrentTransientManager.AddTransient( _dragLine, TransientDrawingMode.Highlight, 128, col); //whenever the dragged line updated, reset _endPoint _endPoint = pt; } private void ClearTransientGraphics() { if (_dragLine != null) { IntegerCollection col = new IntegerCollection(); TransientManager.CurrentTransientManager. EraseTransient(_dragLine, col); _dragLine.Dispose(); _dragLine = null; } } private Point3d CalculateEndPoint(Point3d mousePoint) { Point3d pt = mousePoint; if (_dragAngle <= 90.0 || _dragAngle >= 270.0) { if (mousePoint.X <= _startPoint.X) { pt = _startPoint; } else { if (_dragAngle <= 45.0 || _dragAngle >= 315.0) { double y = (mousePoint.X - _startPoint.X) * Math.Tan(_dragAngle * Math.PI / 180); pt = new Point3d( mousePoint.X, _startPoint.Y + y, 0.0); } else { if (_dragAngle > 45.0 && _dragAngle <= 90.0) { if (mousePoint.Y < _startPoint.Y) { pt = _startPoint; } else { double x = (mousePoint.Y - _startPoint.Y) / Math.Tan(_dragAngle * Math.PI / 180); pt = new Point3d( _startPoint.X + x, mousePoint.Y, 0.0); } } else { if (mousePoint.Y > _startPoint.Y) { pt = _startPoint; } else { double x = (mousePoint.Y - _startPoint.Y) / Math.Tan(_dragAngle * Math.PI / 180); pt = new Point3d( _startPoint.X + x, mousePoint.Y, 0.0); } } } return pt; } } if (_dragAngle >= 90.0 && _dragAngle <= 270.0) { if (mousePoint.X >= _startPoint.X) { pt = _startPoint; } else { if (_dragAngle >= 135.0 && _dragAngle <= 225.0) { double y = (mousePoint.X - _startPoint.X) * Math.Tan(_dragAngle * Math.PI / 180); pt = new Point3d( mousePoint.X, _startPoint.Y + y, 0.0); } else { if (_dragAngle >=90.0 && _dragAngle < 135.0) { if (mousePoint.Y <= _startPoint.Y) { pt = _startPoint; } else { double x = (mousePoint.Y - _startPoint.Y) / Math.Tan(_dragAngle * Math.PI / 180); pt = new Point3d( _startPoint.X + x, mousePoint.Y, 0.0); } } else { if (mousePoint.Y >= _startPoint.Y) { pt = _startPoint; } else { double x = (mousePoint.Y - _startPoint.Y) / Math.Tan(_dragAngle * Math.PI / 180); pt = new Point3d( _startPoint.X + x, mousePoint.Y, 0.0); } } } return pt; } } return pt; } private bool GetEndPoint() { //endPoint = new Point3d(); bool go = true; bool picked = false; while (go) { PromptPointOptions opt = new PromptPointOptions("\nPick point:"); //opt.BasePoint = _startPoint; //opt.UseBasePoint = true; opt.Keywords.Add("Start point"); opt.Keywords.Add("Angle"); opt.Keywords.Add("End point"); opt.Keywords.Add("eXit"); opt.Keywords.Default = "End point"; opt.AppendKeywordsToMessage = true; opt.AllowArbitraryInput = false; opt.AllowNone = false; PromptPointResult res = _editor.GetPoint(opt); if (res.Status == PromptStatus.Cancel) { go = false; ; } else { switch (res.Status) { case PromptStatus.Keyword: //_editor.WriteMessage("\n" + res.StringResult); if (res.StringResult.StartsWith("Start")) { SetStartPoint(); go = true; } if (res.StringResult.StartsWith("Angle")) { SetAngle(); go = true; } if (res.StringResult.StartsWith("eXit")) { go = false; } break; case PromptStatus.OK: //endPoint = res.Value; picked = true; go = false; break; default: go = true; break; } } } return picked; } private void SetStartPoint() { ClearTransientGraphics(); _editor.PointMonitor -= Editor_PointMonitor; PromptPointOptions opt = new PromptPointOptions("\nStart point:"); PromptPointResult res = _editor.GetPoint(opt); if (res.Status == PromptStatus.OK) { _startPoint = res.Value; } _editor.PointMonitor += new PointMonitorEventHandler(Editor_PointMonitor); } private void SetAngle() { ClearTransientGraphics(); _editor.PointMonitor -= Editor_PointMonitor; PromptDoubleOptions opt = new PromptDoubleOptions("\nEnter drag-angle in degree [" + _dragAngle.ToString() + "]: "); opt.AllowNegative = false; opt.AllowZero = true; opt.AllowNone = true; PromptDoubleResult res = _editor.GetDouble(opt); if (res.Status == PromptStatus.OK) { _dragAngle = res.Value; if (_dragAngle > 360.0) _dragAngle -= 360.0; } _editor.PointMonitor += new PointMonitorEventHandler(Editor_PointMonitor); } #endregion } }
Here is the command class that uses the AngleLockedDrag class to draw a Line in AutoCAD.
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.Geometry; [assembly: CommandClass(typeof(AngleLockedDrag.DragCommand))] namespace AngleLockedDrag { public class DragCommand { [CommandMethod("AngledDrag")] public void RunThisMethod() { Document dwg = Autodesk.AutoCAD.ApplicationServices. Application.DocumentManager.MdiActiveDocument; AngledDrag drag = new AngledDrag(dwg); try { if (drag.DragAtAngle()) { GenerateLine(dwg, drag.StartPoint, drag.EndPoint); dwg.Editor.WriteMessage("\nMyCommand executed."); } } catch (Autodesk.AutoCAD.Runtime.Exception ex) { dwg.Editor.WriteMessage("\nError: {0}\n", ex.Message); } } private static void GenerateLine( Document dwg, Point3d startPt, Point3d endPt) { using (Transaction tran = dwg.Database.TransactionManager.StartTransaction()) { BlockTableRecord br = (BlockTableRecord)tran.GetObject( dwg.Database.CurrentSpaceId, OpenMode.ForWrite); Line line = new Line(startPt, endPt); line.SetDatabaseDefaults(dwg.Database); br.AppendEntity(line); tran.AddNewlyCreatedDBObject(line, true); tran.Commit(); } } } }
Here is the video clip that shows the "angled dragging" effect.