Hi,
I am trying to implement custom grips with a custom context menu. I have studied the code at the following two posts and I have been unable to get them to work.
GripData OnHover How to add a context menu
How to handle ctrl click in a move grip point
I have run and compiled each of code samples provided in the posts and I have come across the same problem in each example. When I insert the entity and add the overrule everything appears to work correctly. However, when i select the entity the custom grips do not show up. Additionally, whenever the OnGripStatusChanged event fires, Autocad crashes to the point of shutting down the application. I have tried the code in 2017 and 2018 with the same results. Additionally, i had a co-worker try the same code and they obtained the same results. Below is one of the examples that i have tried. The example was created by Balaji_Ram and the only modifications that I made were to format a couple lines for better readability. The full project can be downloaded in the second link above.
Has anyone successfully implemented Protocol Extensions in .NET? (I know the answer has to be yes). Can anyone else get the sample to run correctly? Does anyone know what I am doing wrong? Is there some simple step that i have missed? I would really love to get this implemented into my application.
// (C) Copyright 2010 by Microsoft // using System; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.GraphicsInterface; using System.Collections.Generic; namespace DevDaysGripMenusSample { public class TestOverrule { static DrawOverrule m_drawOverrule = new DrawOverrule(); static PropsOverrule m_propertiesOverrule = new PropsOverrule(); static XformOverrule m_xformOverrule = new XformOverrule(); static ObjectSnapOverrule m_osnapOverrule = new ObjectSnapOverrule(); static GripPointOverrule m_gripOverrule = new GripPointOverrule(); static HiliteOverrule m_hightlightOverrule = new HiliteOverrule(); static ObjOverrule m_objectOverrule = new ObjOverrule(); static Overrule[] m_overrules = new Overrule[] { m_drawOverrule, m_propertiesOverrule, m_xformOverrule, m_osnapOverrule, m_gripOverrule, m_hightlightOverrule, m_objectOverrule }; static System.Collections.Generic.List<ObjectId> m_overruledObjects = new System.Collections.Generic.List<ObjectId>(); static readonly string RegAppName = "AsdkOverruleTest"; static bool m_overruleAdded = false; [CommandMethod("overrule")] static public void Start() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; PromptEntityResult res = ed.GetEntity("Select a circle to overrule"); if (res.Status != PromptStatus.OK) return; if (res.ObjectId.ObjectClass != RXObject.GetClass(typeof(Circle))) { ed.WriteMessage("Selected object is not a circle!\n"); return; } if (m_overruledObjects.Count == 0) { Application.DocumentManager.DocumentToBeDestroyed += new DocumentCollectionEventHandler(DocumentManager_DocumentToBeDestroyed); } if (!m_overruledObjects.Contains(res.ObjectId)) { Database db = res.ObjectId.Database; using (Transaction t = db.TransactionManager.StartTransaction()) { RegAppTable tbl = (RegAppTable)t.GetObject(db.RegAppTableId, OpenMode.ForRead, false); if (!tbl.Has(RegAppName)) { RegAppTableRecord app = new RegAppTableRecord(); app.Name = RegAppName; tbl = (RegAppTable)t.GetObject(db.RegAppTableId, OpenMode.ForWrite, false); tbl.Add(app); t.AddNewlyCreatedDBObject(app, true); } Circle c = (Circle)t.GetObject(res.ObjectId, OpenMode.ForRead); if (c.GetXDataForApplication(RegAppName) == null) { c = (Circle)t.GetObject(res.ObjectId, OpenMode.ForWrite); c.XData = new ResultBuffer( new TypedValue((int)DxfCode.ExtendedDataRegAppName, RegAppName), new TypedValue((int)DxfCode.ExtendedDataReal, Math.PI / 6) //start with 30 degrees ); m_overruledObjects.Add(res.ObjectId); } t.Commit(); } } ObjectId[] ids = m_overruledObjects.ToArray(); foreach (Overrule o in m_overrules) { o.SetIdFilter(ids); if (!m_overruleAdded) Overrule.AddOverrule(RXObject.GetClass(typeof(Circle)), o, false); } m_overruleAdded = true; Application.DocumentManager.MdiActiveDocument.Editor.Regen(); } static void End() { foreach (Overrule o in m_overrules) { Overrule.RemoveOverrule(RXObject.GetClass(typeof(Circle)), o); } Overrule.Overruling = false; Application.DocumentManager.MdiActiveDocument.Editor.Regen(); } static void DocumentManager_DocumentToBeDestroyed(object sender, DocumentCollectionEventArgs e) { //remove the ids that are going away for (int i = m_overruledObjects.Count - 1; i >= 0; i--) if (m_overruledObjects[i].Database == e.Document.Database) m_overruledObjects.RemoveAt(i); ObjectId[] ids = m_overruledObjects.ToArray(); foreach (Overrule o in m_overrules) o.SetIdFilter(ids); } static double GetAngle(Circle c) { ResultBuffer rb = c.GetXDataForApplication(RegAppName); return (double)rb.AsArray()[1].Value; } static LineSegment3d[] GetLines(Circle c) { LineSegment3d[] lines = new LineSegment3d[2]; double angle = GetAngle(c); Point3d center = c.Center; Vector3d normal = c.Normal; Vector3d axis = normal.GetPerpendicularVector() * c.Radius; Vector3d vec = axis.RotateBy(angle, normal); lines[0] = new LineSegment3d(center - vec, center + vec); vec = axis.RotateBy(-angle, normal); lines[1] = new LineSegment3d(center - vec, center + vec); return lines; } class DrawOverrule : DrawableOverrule { public override bool WorldDraw(Drawable drawable, WorldDraw wd) { Circle c = (Circle)drawable; LineSegment3d[] lines = GetLines(c); foreach (LineSegment3d l in lines) wd.Geometry.WorldLine(l.StartPoint, l.EndPoint); return base.WorldDraw(drawable, wd); } } class PropsOverrule : PropertiesOverrule { public override void List(Entity entity) { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; ed.WriteMessage("\tOverrule test\n"); ed.WriteMessage("\t\tAngle is {0}", GetAngle((Circle)entity)); } } class XformOverrule : TransformOverrule { public override void Explode(Entity entity, DBObjectCollection entitySet) { Circle c = (Circle)entity; entitySet.Add((Circle)entity.Clone()); LineSegment3d[] lines = GetLines(c); foreach (LineSegment3d l in lines) entitySet.Add(new Line(l.StartPoint, l.EndPoint)); } } class CircleMFMGPE : MultiModesGripPE { internal CircleMFMGPE(GripPointOverrule overrule) : base() { m_overrule = overrule; } public override GripMode CurrentMode(Entity entity, GripData gripData) { if (gripData is GripPointOverrule.MyGrip) { int index = (int)((GripPointOverrule.MyGrip)gripData).CurrentModeId - (int)GripMode.ModeIdentifier.CustomStart; return ((GripPointOverrule.MyGrip)gripData).Modes[index]; } else return null; } public override uint CurrentModeId(Entity entity, GripData gripData) { if (gripData is GripPointOverrule.MyGrip) return (uint)(gripData as GripPointOverrule.MyGrip).CurrentModeId; return 0; } public override bool GetGripModes(Entity entity, GripData gripData, GripModeCollection modes, ref uint curMode) { if (!(gripData is GripPointOverrule.MyGrip)) return false; return (gripData as GripPointOverrule.MyGrip).GetGripModes(ref modes, ref curMode); } public override MultiModesGripPE.GripType GetGripType(Entity entity, GripData gripData) { return (gripData is GripPointOverrule.MyGrip) ? MultiModesGripPE.GripType.Secondary : MultiModesGripPE.GripType.Primary; } public override void Reset(Entity entity) { } public override bool SetCurrentMode(Entity entity, GripData gripData, uint curMode) { if (!(gripData is GripPointOverrule.MyGrip)) return false; (gripData as GripPointOverrule.MyGrip).CurrentModeId = (GripMode.ModeIdentifier)curMode; return true; } private GripPointOverrule m_overrule; } class GripPointOverrule : GripOverrule { CircleMFMGPE __theMFMGPE = null; internal GripPointOverrule() { __theMFMGPE = new CircleMFMGPE(this); RXObject.GetClass(typeof(Circle)).AddX(RXObject.GetClass(typeof(CircleMFMGPE)), __theMFMGPE); } internal abstract class MyGrip : GripData { protected MyGrip() { __modes = new GripModeCollection(); } GripMode.ModeIdentifier __curModeId = GripMode.ModeIdentifier.CustomStart; public virtual GripMode.ModeIdentifier CurrentModeId { get { return __curModeId; } set { __curModeId = value; } } GripModeCollection __modes; public virtual GripModeCollection Modes { get { return __modes; } } public abstract void Move(Entity entity, Vector3d offset); public abstract bool GetGripModes(ref GripModeCollection modes, ref uint curMode); public override bool ViewportDraw(ViewportDraw vd, ObjectId entityId, GripData.DrawType type, Point3d? imageGripPoint, int gripSize) { Point2d unit = vd.Viewport.GetNumPixelsInUnitSquare(GripPoint); vd.Geometry.Circle(GripPoint, gripSize / unit.X, vd.Viewport.ViewDirection); return true; } protected void MoveWorker(Entity entity, Vector3d offset) { Circle c = (Circle)entity; Point3d newGripPoint = GripPoint + offset; c.Radius = newGripPoint.DistanceTo(c.Center); } } public class RowGripMenuItem : Autodesk.AutoCAD.Runtime.IMenuItem { private GripData _Grip; private Action _Action; private List<IMenuItem> _Items = new List<IMenuItem>(); public delegate void Action(GripData g, RowGripMenuItem r); public RowGripMenuItem(GripData g, Action a) { _Grip = g; _Action = a; } public bool Checked { get; set; } public bool Enabled { get; set; } public System.Drawing.Icon Icon { get; set; } public string Text { get; set; } public bool Visible { get; set; } public System.Collections.Generic.IEnumerable<Autodesk.AutoCAD.Runtime.IMenuItem> Items { get { return _Items; } } public void OnClicked(System.EventArgs eventArgs) { if (_Action != null) _Action.Invoke(_Grip, this); } public void Add(IMenuItem m) { _Items.Add(m); } public void Remove(IMenuItem m) { _Items.Remove(m); } public event EventHandler Click; } class LowerLeftGrip : MyGrip { public enum myMFMGPEModeId { kStretchRadiusX = GripMode.ModeIdentifier.CustomStart, kStretchRadiusY, kIncrementRadiusByOne } public LowerLeftGrip() { GripMode m1 = new GripMode(); m1.ModeId = (uint)myMFMGPEModeId.kStretchRadiusX; m1.DisplayString = "Stretch radius, offset mapped to X diection."; m1.CLIPromptString = "\nSpecify new vertex point:"; m1.CLIKeywordList = "STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo _STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo"; m1.CLIDisplayString = "\n** STRETCH X **"; m1.Action = GripMode.ActionType.DragOn; Modes.Add(m1); GripMode m2 = new GripMode(); m2.ModeId = (uint)myMFMGPEModeId.kStretchRadiusY; m2.DisplayString = "Stretch radius, offset mapped to Y diection."; m2.CLIDisplayString = "\n** STRETCH Y **"; m1.CLIKeywordList = "STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo _STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo"; m2.CLIPromptString = "\nSpecify new vertex point:"; m2.Action = GripMode.ActionType.DragOn; Modes.Add(m2); GripMode m3 = new GripMode(); m3.ModeId = (uint)myMFMGPEModeId.kIncrementRadiusByOne; m3.DisplayString = "Increment radius by 1."; m3.CLIPromptString = "\nSpecify new vertex point:"; m3.CLIKeywordList = "STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo _STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo"; m3.CLIDisplayString = "\n** INCREMENT RADIUS BY 1 **"; m3.Action = GripMode.ActionType.Immediate; Modes.Add(m3); CurrentModeId = 0; } public override bool GetGripModes(ref GripModeCollection modes, ref uint curMode) { //modes = __modes; /* foreach (GripMode m in Modes) modes.Add(m); curMode = (uint)CurrentModeId; */ return true; } public override void Move(Entity entity, Vector3d offset) { switch ((myMFMGPEModeId)CurrentModeId) { case myMFMGPEModeId.kStretchRadiusX: offset = offset.Subtract(new Vector3d(0, offset.Y, 0)); break; case myMFMGPEModeId.kStretchRadiusY: offset = offset.Subtract(new Vector3d(offset.X, 0, 0)); break; case myMFMGPEModeId.kIncrementRadiusByOne: Vector3d v = GripPoint - ((Circle)entity).Center; offset += v.GetNormal(); break; } MoveWorker(entity, offset); return; } public override IEnumerable<Autodesk.AutoCAD.Runtime.IMenuItem> OnRightClick(GripDataCollection hotGrips, ObjectIdCollection entities) { List<RowGripMenuItem> GripMenu = new List<RowGripMenuItem>(); GripMenu.Add( new RowGripMenuItem(this, null) { Text = "Test-1", Icon = Resource1.MyTestIcon } ); GripMenu.Add( new RowGripMenuItem(this, null) { Text = "Test - 2", Icon = Resource1.MyTestIcon } ); return GripMenu; } } class UpperRightGrip : MyGrip { public override bool GetGripModes(ref GripModeCollection modes, ref uint curMode) { GripMode m1 = new GripMode(); m1.ModeId = 0; m1.DisplayString = "Upper right not implemeted"; m1.Action = GripMode.ActionType.Immediate; modes.Add(m1); curMode = 0; return true; } public override void Move(Entity entity, Vector3d offset) { MoveWorker(entity, offset); } } class UpperLeftGrip : MyGrip { public override bool GetGripModes(ref GripModeCollection modes, ref uint curMode) { GripMode m1 = new GripMode(); m1.ModeId = 0; m1.DisplayString = "Upper left not implemeted"; m1.Action = GripMode.ActionType.Immediate; modes.Add(m1); curMode = 0; return true; } public override void Move(Entity entity, Vector3d offset) { MoveWorker(entity, offset); } } class LowerRightGrip : MyGrip { public override bool GetGripModes(ref GripModeCollection modes, ref uint curMode) { GripMode m1 = new GripMode(); m1.ModeId = 0; m1.DisplayString = "Lower right not implemeted"; m1.Action = GripMode.ActionType.Immediate; modes.Add(m1); curMode = 0; return true; } public override void Move(Entity entity, Vector3d offset) { MoveWorker(entity, offset); } } GripData[] m_grips = new GripData[4]; public override void GetGripPoints(Entity entity, GripDataCollection grips, double curViewUnitSize, int gripSize, Vector3d curViewDir, Autodesk.AutoCAD.DatabaseServices.GetGripPointsFlags bitFlags) { base.GetGripPoints(entity, grips, curViewUnitSize, gripSize, curViewDir, bitFlags); Circle c = (Circle)entity; LineSegment3d[] lines = GetLines(c); m_grips[0] = new LowerLeftGrip(); m_grips[0].GripPoint = lines[0].StartPoint; m_grips[1] = new UpperRightGrip(); m_grips[1].GripPoint = lines[0].EndPoint; m_grips[2] = new UpperLeftGrip(); m_grips[2].GripPoint = lines[1].StartPoint; m_grips[3] = new LowerRightGrip(); m_grips[3].GripPoint = lines[1].EndPoint; foreach (GripData g in m_grips) grips.Add(g); } public override void MoveGripPointsAt(Entity entity, GripDataCollection grips, Vector3d offset, Autodesk.AutoCAD.DatabaseServices.MoveGripPointsFlags bitFlags) { foreach (GripData grip in grips) { MyGrip myGrip = grip as MyGrip; if (myGrip != null) myGrip.Move(entity, offset); else base.MoveGripPointsAt(entity, grips, offset, bitFlags); } } } class ObjectSnapOverrule : OsnapOverrule { public override void GetObjectSnapPoints(Entity entity, ObjectSnapModes snapMode, IntPtr gsSelectionMark, Point3d pickPoint, Point3d lastPoint, Matrix3d viewTransform, Point3dCollection snapPoints, IntegerCollection geometryIds) { base.GetObjectSnapPoints(entity, snapMode, gsSelectionMark, pickPoint, lastPoint, viewTransform, snapPoints, geometryIds); if ((snapMode & ObjectSnapModes.ModeEnd) == ObjectSnapModes.ModeEnd) { Circle c = (Circle)entity; LineSegment3d[] lines = GetLines(c); foreach (LineSegment3d l in lines) { snapPoints.Add(l.StartPoint); snapPoints.Add(l.EndPoint); } } } } class HiliteOverrule : HighlightOverrule { public override void Highlight(Entity entity, FullSubentityPath subId, bool highlightAll) { base.Highlight(entity, subId, highlightAll); } public override void Unhighlight(Entity entity, FullSubentityPath subId, bool highlightAll) { base.Unhighlight(entity, subId, highlightAll); } } class ObjOverrule : ObjectOverrule { public override void Erase(DBObject dbObject, bool erasing) { //prevent the object from being deleted base.Erase(dbObject, erasing); if (erasing) throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.CannotBeErasedByCaller); } } } }
Hello
I tried the demo and get the same exact results...crashing. I've tried some different things but no luck. Anyone have a solution?
Thank you
Jeff
Hi Keith,
This seems to work - at least I don't get any crashes and the grip menu appears:
// (C) Copyright 2010 by Microsoft using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.GraphicsInterface; using Autodesk.AutoCAD.Runtime; using System; using System.Collections.Generic; namespace DevDaysGripMenusSample { public class TestOverrule { private static DrawOverrule m_drawOverrule = new DrawOverrule(); private static PropsOverrule m_propertiesOverrule = new PropsOverrule(); private static XformOverrule m_xformOverrule = new XformOverrule(); private static ObjectSnapOverrule m_osnapOverrule = new ObjectSnapOverrule(); private static GripPointOverrule m_gripOverrule = new GripPointOverrule(); private static HiliteOverrule m_hightlightOverrule = new HiliteOverrule(); private static ObjOverrule m_objectOverrule = new ObjOverrule(); private static Overrule[] m_overrules = new Overrule[] { m_drawOverrule, m_propertiesOverrule, m_xformOverrule, m_osnapOverrule, m_gripOverrule, m_hightlightOverrule, m_objectOverrule }; private static System.Collections.Generic.List<ObjectId> m_overruledObjects = new System.Collections.Generic.List<ObjectId>(); private static readonly string RegAppName = "AsdkOverruleTest"; private static bool m_overruleAdded = false; [CommandMethod("overrule")] static public void Start() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; PromptEntityResult res = ed.GetEntity("Select a circle to overrule"); if (res.Status != PromptStatus.OK) return; if (res.ObjectId.ObjectClass != RXObject.GetClass(typeof(Circle))) { ed.WriteMessage("Selected object is not a circle!\n"); return; } if (m_overruledObjects.Count == 0) { Application.DocumentManager.DocumentToBeDestroyed += new DocumentCollectionEventHandler(DocumentManager_DocumentToBeDestroyed); } if (!m_overruledObjects.Contains(res.ObjectId)) { Database db = res.ObjectId.Database; using (Transaction t = db.TransactionManager.StartTransaction()) { RegAppTable tbl = (RegAppTable)t.GetObject(db.RegAppTableId, OpenMode.ForRead, false); if (!tbl.Has(RegAppName)) { RegAppTableRecord app = new RegAppTableRecord(); app.Name = RegAppName; tbl = (RegAppTable)t.GetObject(db.RegAppTableId, OpenMode.ForWrite, false); tbl.Add(app); t.AddNewlyCreatedDBObject(app, true); } Circle c = (Circle)t.GetObject(res.ObjectId, OpenMode.ForRead); if (c.GetXDataForApplication(RegAppName) == null) { c = (Circle)t.GetObject(res.ObjectId, OpenMode.ForWrite); c.XData = new ResultBuffer( new TypedValue((int)DxfCode.ExtendedDataRegAppName, RegAppName), new TypedValue((int)DxfCode.ExtendedDataReal, Math.PI / 6) //start with 30 degrees ); m_overruledObjects.Add(res.ObjectId); } t.Commit(); } } ObjectId[] ids = m_overruledObjects.ToArray(); foreach (Overrule o in m_overrules) { o.SetIdFilter(ids); if (!m_overruleAdded) Overrule.AddOverrule(RXObject.GetClass(typeof(Circle)), o, false); } m_overruleAdded = true; Application.DocumentManager.MdiActiveDocument.Editor.Regen(); } private static void End() { foreach (Overrule o in m_overrules) { Overrule.RemoveOverrule(RXObject.GetClass(typeof(Circle)), o); } Overrule.Overruling = false; Application.DocumentManager.MdiActiveDocument.Editor.Regen(); } private static void DocumentManager_DocumentToBeDestroyed(object sender, DocumentCollectionEventArgs e) { //remove the ids that are going away for (int i = m_overruledObjects.Count - 1; i >= 0; i--) if (m_overruledObjects[i].Database == e.Document.Database) m_overruledObjects.RemoveAt(i); ObjectId[] ids = m_overruledObjects.ToArray(); foreach (Overrule o in m_overrules) o.SetIdFilter(ids); } private static double GetAngle(Circle c) { ResultBuffer rb = c.GetXDataForApplication(RegAppName); return (double)rb.AsArray()[1].Value; } private static LineSegment3d[] GetLines(Circle c) { LineSegment3d[] lines = new LineSegment3d[2]; double angle = GetAngle(c); Point3d center = c.Center; Vector3d normal = c.Normal; Vector3d axis = normal.GetPerpendicularVector() * c.Radius; Vector3d vec = axis.RotateBy(angle, normal); lines[0] = new LineSegment3d(center - vec, center + vec); vec = axis.RotateBy(-angle, normal); lines[1] = new LineSegment3d(center - vec, center + vec); return lines; } private class DrawOverrule : DrawableOverrule { public override bool WorldDraw(Drawable drawable, WorldDraw wd) { Circle c = (Circle)drawable; LineSegment3d[] lines = GetLines(c); foreach (LineSegment3d l in lines) wd.Geometry.WorldLine(l.StartPoint, l.EndPoint); return base.WorldDraw(drawable, wd); } } private class PropsOverrule : PropertiesOverrule { public override void List(Entity entity) { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; ed.WriteMessage("\tOverrule test\n"); ed.WriteMessage("\t\tAngle is {0}", GetAngle((Circle)entity)); } } private class XformOverrule : TransformOverrule { public override void Explode(Entity entity, DBObjectCollection entitySet) { Circle c = (Circle)entity; entitySet.Add((Circle)entity.Clone()); LineSegment3d[] lines = GetLines(c); foreach (LineSegment3d l in lines) entitySet.Add(new Line(l.StartPoint, l.EndPoint)); } } private class CircleMFMGPE : MultiModesGripPE { internal CircleMFMGPE(GripPointOverrule overrule) : base() { m_overrule = overrule; } public override GripMode CurrentMode(Entity entity, GripData gripData) { if (gripData is GripPointOverrule.MyGrip) { int index = (int)((GripPointOverrule.MyGrip)gripData).CurrentModeId - (int)GripMode.ModeIdentifier.CustomStart; return ((GripPointOverrule.MyGrip)gripData).Modes[index]; } else return null; } public override uint CurrentModeId(Entity entity, GripData gripData) { if (gripData is GripPointOverrule.MyGrip) return (uint)(gripData as GripPointOverrule.MyGrip).CurrentModeId; return 0; } public override bool GetGripModes(Entity entity, GripData gripData, GripModeCollection modes, ref uint curMode) { if (!(gripData is GripPointOverrule.MyGrip)) return false; return (gripData as GripPointOverrule.MyGrip).GetGripModes(ref modes, ref curMode); } public override MultiModesGripPE.GripType GetGripType(Entity entity, GripData gripData) { return (gripData is GripPointOverrule.MyGrip) ? MultiModesGripPE.GripType.Secondary : MultiModesGripPE.GripType.Primary; } public override void Reset(Entity entity) { } public override bool SetCurrentMode(Entity entity, GripData gripData, uint curMode) { if (!(gripData is GripPointOverrule.MyGrip)) return false; (gripData as GripPointOverrule.MyGrip).CurrentModeId = (GripMode.ModeIdentifier)curMode; return true; } private GripPointOverrule m_overrule; } private class GripPointOverrule : GripOverrule { private CircleMFMGPE __theMFMGPE = null; internal GripPointOverrule() { __theMFMGPE = new CircleMFMGPE(this); RXObject.GetClass(typeof(Circle)).AddX(RXObject.GetClass(typeof(CircleMFMGPE)), __theMFMGPE); } internal abstract class MyGrip : GripData { protected MyGrip() { __modes = new GripModeCollection(); } private GripMode.ModeIdentifier __curModeId = GripMode.ModeIdentifier.CustomStart; public virtual GripMode.ModeIdentifier CurrentModeId { get { return __curModeId; } set { __curModeId = value; } } private GripModeCollection __modes; public virtual GripModeCollection Modes { get { return __modes; } } public abstract void Move(Entity entity, Vector3d offset); public abstract bool GetGripModes(ref GripModeCollection modes, ref uint curMode); public override bool ViewportDraw(ViewportDraw vd, ObjectId entityId, GripData.DrawType type, Point3d? imageGripPoint, int gripSize) { Point2d unit = vd.Viewport.GetNumPixelsInUnitSquare(GripPoint); vd.Geometry.Circle(GripPoint, gripSize / unit.X, vd.Viewport.ViewDirection); return true; } protected void MoveWorker(Entity entity, Vector3d offset) { Circle c = (Circle)entity; Point3d newGripPoint = GripPoint + offset; c.Radius = newGripPoint.DistanceTo(c.Center); } } public class RowGripMenuItem : Autodesk.AutoCAD.Runtime.IMenuItem { private GripData _Grip; private Action _Action; private List<IMenuItem> _Items = new List<IMenuItem>(); public delegate void Action(GripData g, RowGripMenuItem r); public RowGripMenuItem(GripData g, Action a) { _Grip = g; _Action = a; } public bool Checked { get; set; } public bool Enabled { get; set; } public System.Drawing.Icon Icon { get; set; } public string Text { get; set; } public bool Visible { get; set; } public System.Collections.Generic.IEnumerable<Autodesk.AutoCAD.Runtime.IMenuItem> Items { get { return _Items; } } public void OnClicked(System.EventArgs eventArgs) { if (_Action != null) _Action.Invoke(_Grip, this); } public void Add(IMenuItem m) { _Items.Add(m); } public void Remove(IMenuItem m) { _Items.Remove(m); } public event EventHandler Click; } private class LowerLeftGrip : MyGrip { public enum myMFMGPEModeId { kStretchRadiusX = GripMode.ModeIdentifier.CustomStart, kStretchRadiusY, kIncrementRadiusByOne } public LowerLeftGrip() { GripMode m1 = new GripMode(); m1.ModeId = (uint)myMFMGPEModeId.kStretchRadiusX; m1.DisplayString = "Stretch radius, offset mapped to X diection."; m1.CLIPromptString = "\nSpecify new vertex point:"; m1.CLIKeywordList = "STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo _STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo"; m1.CLIDisplayString = "\n** STRETCH X **"; m1.Action = GripMode.ActionType.DragOn; Modes.Add(m1); GripMode m2 = new GripMode(); m2.ModeId = (uint)myMFMGPEModeId.kStretchRadiusY; m2.DisplayString = "Stretch radius, offset mapped to Y diection."; m2.CLIDisplayString = "\n** STRETCH Y **"; m1.CLIKeywordList = "STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo _STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo"; m2.CLIPromptString = "\nSpecify new vertex point:"; m2.Action = GripMode.ActionType.DragOn; Modes.Add(m2); GripMode m3 = new GripMode(); m3.ModeId = (uint)myMFMGPEModeId.kIncrementRadiusByOne; m3.DisplayString = "Increment radius by 1."; m3.CLIPromptString = "\nSpecify new vertex point:"; m3.CLIKeywordList = "STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo _STretch MOve ROtate SCale MIrror Base Copy Undo X EXit dummy GMove CGizmo"; m3.CLIDisplayString = "\n** INCREMENT RADIUS BY 1 **"; m3.Action = GripMode.ActionType.Immediate; Modes.Add(m3); CurrentModeId = 0; } public override bool GetGripModes(ref GripModeCollection modes, ref uint curMode) { //modes = __modes; foreach (GripMode m in Modes) modes.Add(m); //curMode = (uint)CurrentModeId; return true; } public override void Move(Entity entity, Vector3d offset) { switch ((myMFMGPEModeId)CurrentModeId) { case myMFMGPEModeId.kStretchRadiusX: offset = offset.Subtract(new Vector3d(0, offset.Y, 0)); break; case myMFMGPEModeId.kStretchRadiusY: offset = offset.Subtract(new Vector3d(offset.X, 0, 0)); break; case myMFMGPEModeId.kIncrementRadiusByOne: Vector3d v = GripPoint - ((Circle)entity).Center; offset += v.GetNormal(); break; } MoveWorker(entity, offset); return; } public override IEnumerable<Autodesk.AutoCAD.Runtime.IMenuItem> OnRightClick(GripDataCollection hotGrips, ObjectIdCollection entities) { List<RowGripMenuItem> GripMenu = new List<RowGripMenuItem>(); GripMenu.Add(new RowGripMenuItem(this, null) { Text = "Test-1", Icon = Resource1.MyTestIcon } ); GripMenu.Add(new RowGripMenuItem(this, null) { Text = "Test - 2", Icon = Resource1.MyTestIcon } ); return GripMenu; } } private class UpperRightGrip : MyGrip { public override bool GetGripModes(ref GripModeCollection modes, ref uint curMode) { GripMode m1 = new GripMode(); m1.ModeId = 0; m1.DisplayString = "Upper right not implemeted"; m1.Action = GripMode.ActionType.Immediate; modes.Add(m1); curMode = 0; return true; } public override void Move(Entity entity, Vector3d offset) { MoveWorker(entity, offset); } } private class UpperLeftGrip : MyGrip { public override bool GetGripModes(ref GripModeCollection modes, ref uint curMode) { GripMode m1 = new GripMode(); m1.ModeId = 0; m1.DisplayString = "Upper left not implemeted"; m1.Action = GripMode.ActionType.Immediate; modes.Add(m1); curMode = 0; return true; } public override void Move(Entity entity, Vector3d offset) { MoveWorker(entity, offset); } } private class LowerRightGrip : MyGrip { public override bool GetGripModes(ref GripModeCollection modes, ref uint curMode) { GripMode m1 = new GripMode(); m1.ModeId = 0; m1.DisplayString = "Lower right not implemeted"; m1.Action = GripMode.ActionType.Immediate; modes.Add(m1); curMode = 0; return true; } public override void Move(Entity entity, Vector3d offset) { MoveWorker(entity, offset); } } private GripData[] m_grips = new GripData[4]; public override void GetGripPoints(Entity entity, GripDataCollection grips, double curViewUnitSize, int gripSize, Vector3d curViewDir, Autodesk.AutoCAD.DatabaseServices.GetGripPointsFlags bitFlags) { base.GetGripPoints(entity, grips, curViewUnitSize, gripSize, curViewDir, bitFlags); Circle c = (Circle)entity; LineSegment3d[] lines = GetLines(c); m_grips[0] = new LowerLeftGrip(); m_grips[0].GripPoint = lines[0].StartPoint; m_grips[1] = new UpperRightGrip(); m_grips[1].GripPoint = lines[0].EndPoint; m_grips[2] = new UpperLeftGrip(); m_grips[2].GripPoint = lines[1].StartPoint; m_grips[3] = new LowerRightGrip(); m_grips[3].GripPoint = lines[1].EndPoint; foreach (GripData g in m_grips) grips.Add(g); } public override void MoveGripPointsAt(Entity entity, GripDataCollection grips, Vector3d offset, Autodesk.AutoCAD.DatabaseServices.MoveGripPointsFlags bitFlags) { foreach (GripData grip in grips) { MyGrip myGrip = grip as MyGrip; if (myGrip != null) myGrip.Move(entity, offset); else base.MoveGripPointsAt(entity, grips, offset, bitFlags); } } } private class ObjectSnapOverrule : OsnapOverrule { public override void GetObjectSnapPoints(Entity entity, ObjectSnapModes snapMode, IntPtr gsSelectionMark, Point3d pickPoint, Point3d lastPoint, Matrix3d viewTransform, Point3dCollection snapPoints, IntegerCollection geometryIds) { base.GetObjectSnapPoints(entity, snapMode, gsSelectionMark, pickPoint, lastPoint, viewTransform, snapPoints, geometryIds); if ((snapMode & ObjectSnapModes.ModeEnd) == ObjectSnapModes.ModeEnd) { Circle c = (Circle)entity; LineSegment3d[] lines = GetLines(c); foreach (LineSegment3d l in lines) { snapPoints.Add(l.StartPoint); snapPoints.Add(l.EndPoint); } } } } private class HiliteOverrule : HighlightOverrule { public override void Highlight(Entity entity, FullSubentityPath subId, bool highlightAll) { base.Highlight(entity, subId, highlightAll); } public override void Unhighlight(Entity entity, FullSubentityPath subId, bool highlightAll) { base.Unhighlight(entity, subId, highlightAll); } } private class ObjOverrule : ObjectOverrule { public override void Erase(DBObject dbObject, bool erasing) { //prevent the object from being deleted base.Erase(dbObject, erasing); if (erasing) throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.CannotBeErasedByCaller); } } } }
All I did was uncomment a couple of the lines in GetGripModes for the LowerLeftGrip.
I haven't read the other posts in detail so there may be other stuff but that you're expecting but from a quick glance over, it seems to be doing what it's supposed to?
Regards
Paul
No luck here. Redownloaded the sample. Pasted new code - with part uncommented - and ran. Same crash. I did have to move to Framework 4.5 to get it to work with AutoCAD 2017. Anyhow, drew circle. OverRuled. Lines drawn but no extra grip points. If you move another grip...crash.
@Keith.Brown - Any luck?
Jeff
@Paulio wrote:
All I did was uncomment a couple of the lines in GetGripModes for the LowerLeftGrip.
Hi Paulio,
I think i commented out those lines in my testing as the code was never reaching there. I copied your code into a new project and ran it and unfortunately i have the exact same issue. The custom grips are never being drawn. If i put a break point on the viewport draw method in the abstract class mygrip, it is never being hit.
At this point I really don't feel like there is anything wrong with the code but something is wrong with my project setup or possibly even my autocad installation. My coworker is having the same issue with the code that you posted so that makes the mystery even more mysterious to me.
Would you mind sharing your entire project zipped up?
Hi Kieth,
Zipped solution attached.
I haven't tried it in 2017 so I don't know if that's the problem. I'm using it in 18 and referencing the AutoCAD dlls from the 2018 OARX download if that helps.
Paul
So I had the exact same issue with the project you sent. I also targeted the ObjectARX 2018 dlls.
The only thing that I can think of that might be wrong is that I have a third party application that is causing the issue. I develop applications for CADWorx and it could be causing an issue. I make sure to start AutoCAD without loading their application but it is possible that they load somethings in the background.
We have a few spare computers laying around so I am going to try a fresh install of AutoCAD on one of them and see what happens. Thanks for all of your help.
That's really odd then considering that Jeff got the same problem you did.
The only other thing I can think to check would be if we have different service packs installed. Mine is O.161.0.0 AutoCAD 2018 1.2 Update
Paul
Sorry for the extreme delay in getting back.
I have downloaded DevDaysGripMenusSample.zip from the second link and tested in ACAD 2018 and ACAD 2019 with all updates and I can see the custom grips being generated.
Can you please provide a reproducible sample project if the issue still persists at your end, so that we can recreate the issue for investigation.
Hi Deepak,
Here is the project that I used. I downloaded it from @Paulio's post above and made no modifications. I ran the project got the error shown below in the video and then zipped it up. I used the 2018 ObjectArx dlls and AutoCAD MEP 2018 to run the project in.
So the plot thickens, i copied the dll that was created with the above project to a personal computer of mine and loaded outside of the visual studio development environment and it ran just fine. I really expected it to as others have gotten the code to work without issues. I then tried to netload the dll outside of the ide on my work computer and again i got the crash except this time it generated a crash report. I have attached the crash report to this post. The only modification that I made was to remove my serial number from the user info.
@deepak.a.s.nadig, hopefully the report can help you analyze the situation.