Author Topic: a better entity highlight?  (Read 9248 times)

0 Members and 1 Guest are viewing this topic.

dugk

  • Guest
a better entity highlight?
« on: August 25, 2010, 11:04:48 AM »
I spent some time trying to code a better highlight method.  My goal was to make it run for a period of time and blink the entity in some way.

I tried alternating the highlight property in successive passes of a for loop and I included a call to Thread.Sleep(1000) but it was not visibly recognizable when run.

In another trial on a line entity I tried drawing a series of polylines with width over top and then change their color during a for loop but it too was not visibly recognizable when run.

Any suggestions?

Thanks!
Doug

BillZndl

  • Guest
Re: a better entity highlight?
« Reply #1 on: August 26, 2010, 07:00:40 AM »


 change their color during a for loop but it too was not visibly recognizable when run.

Any suggestions?


Care to post the code?


n.yuan

  • Bull Frog
  • Posts: 348
Re: a better entity highlight?
« Reply #2 on: August 26, 2010, 10:19:42 AM »
You can look into TransientGraphics object, which is designed for doing, well, "transient graphics" in Acad editor to provide visual hint to the user.

I have 2 blog articles on this topic with short video clips attached http://drive-cad-with-code.blogspot.com/2009/07/help-autocad-users-visually-with.html. From the sample code I am sure you can easily figure out a way to have "better entity highlight".

dugk

  • Guest
Re: a better entity highlight?
« Reply #3 on: August 26, 2010, 10:28:21 AM »
Norman,

Thanks for you post and the interesting examples that you posted on your blog!  I've added your blog to my RSS feeds. :)

I think your example will prove to be a good resource.  I'll post my code soon.

Thanks,
Doug

Jeff H

  • Needs a day job
  • Posts: 6150
Re: a better entity highlight?
« Reply #4 on: August 26, 2010, 02:30:01 PM »
That was neat Norman
I saw something by Fenton Webb and he used the pointMoniterEvents (I believe that right)
You check that out.

BillZndl

  • Guest
Re: a better entity highlight?
« Reply #5 on: August 26, 2010, 03:06:22 PM »
dugk,

I was thinking in terms when you said that your color changes were not showing up in real time
that you were not using QueueForGraphicsFlush during the transaction.

Here's how I change the colors of the entities in a Group:

Code: [Select]
using (Transaction trans = doc.TransactionManager.StartTransaction())
            {
                Group EntGrpDic = (Group)trans.GetObject(GID, OpenMode.ForRead);
                ObjectId[] Eids = EntGrpDic.GetAllEntityIds();
               
                foreach (ObjectId eid in Eids)
                {
                    Entity ent = trans.GetObject(eid, OpenMode.ForWrite) as Entity;
                    ent.RecordGraphicsModified(true);
                    trans.TransactionManager.QueueForGraphicsFlush();
                   
                    if (flag == 1)
                    {                       
                        colorIndex = (short)3;
                        ent.ColorIndex = colorIndex;
                       
                    }
                    else
                    {                       
                        colorIndex = (short)256;
                        ent.ColorIndex = colorIndex;
                       
                    }                   
                }
               
                trans.Commit();
                ed.UpdateScreen();               
            }

dugk

  • Guest
Re: a better entity highlight?
« Reply #6 on: August 27, 2010, 04:35:02 PM »
Norman,

Your code helped me create what I was hoping to create.  Here is the code I created with your help:
Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;

using AcApSrvApp = Autodesk.AutoCAD.ApplicationServices.Application;
using AcApDbSrv = Autodesk.AutoCAD.DatabaseServices;

using System;

namespace transientGraphics
{
    public class tgLineJig
    {
        private AcApDbSrv.Polyline mTGPolyline = null;
        private AcApDbSrv.Line mTargetLine;
        private Editor mEditor;
        private Database mDB;
        private Document mDoc;

        private Point3d mBasePoint;
        private int mColorIndex = 1;

        private Plane planeXY = new Plane(new Point3d(0, 0, 0), Vector3d.ZAxis);

        public tgLineJig(Document doc)
        {
            mDoc = doc;
            mDB = doc.Database;
            mEditor = doc.Editor;
        }

        public void ShowTGJig()
        {
            transientGraphics.Methods.setOsMode(0);

            //Option to pick the target polyline
            PromptEntityOptions eOpt = new PromptEntityOptions("\nPick a line:");

            //Only allow to pick line
            eOpt.SetRejectMessage("\nYou must pick a line:");
            eOpt.AddAllowedClass(typeof(AcApDbSrv.Line), true);

            //Do the pick
            PromptEntityResult eRes = mEditor.GetEntity(eOpt);
            if (eRes.Status != PromptStatus.OK) return;

            //Get the target polyline
            ObjectId targetId = eRes.ObjectId;
            AcApDbSrv.Line target = GetLine(targetId);
            if (target == null) return;

            mTargetLine = target;

            //Set base point
            mBasePoint = mTargetLine.StartPoint;

            //Set base point for second pick so that a rubberband will be shown when mouse is moving
            PromptPointOptions opt2 = new PromptPointOptions("\nClick anywhere to exit:");
            opt2.AllowArbitraryInput = true;

            //Start monitoring pointer move
            mEditor.PointMonitor += new PointMonitorEventHandler(mEditor_PointMonitor);

            //Start asking user to do second pick (exit) so that the "jig" image will move with mouse
            mEditor.GetPoint(opt2);

            //Once the second point is picked, clear the transient graphic "jig". After this, since
            //a new point is obtained with the jig;s visual help, one can then do copy/move/insert...
            ClearTGPolyline();

            //End pointer move monitoring
            mEditor.PointMonitor -= new PointMonitorEventHandler(mEditor_PointMonitor);
        }

        private void mEditor_PointMonitor(object sender, PointMonitorEventArgs e)
        {
            //Whenever point moves, draw a new transient graphic image at mouse point
            DrawTGPolyline(e.Context.RawPoint);

            //iterate colorindex, so the jig's color changes with mouse move, thus more eye-catching
            mColorIndex += 1;
            if (mColorIndex > 8) mColorIndex = 1;
        }

        private AcApDbSrv.Line GetLine(ObjectId id)
        {
            AcApDbSrv.Line ln = null;
            using (Transaction tran = mDB.TransactionManager.StartOpenCloseTransaction())
            {
                ln = tran.GetObject(id, OpenMode.ForRead) as AcApDbSrv.Line;
                tran.Commit();
            }
            return ln;
        }

        private void DrawTGPolyline(Point3d movePoint)
        {
            //Clear existing transient graphic image
            ClearTGPolyline();

            //Create a polyline for the transient graphics
            mTGPolyline = new AcApDbSrv.Polyline(2);
            mTGPolyline.AddVertexAt(0, mTargetLine.StartPoint.Convert2d(planeXY), 0.0, 1.0, 1.0);
            mTGPolyline.AddVertexAt(0, mTargetLine.EndPoint.Convert2d(planeXY), 0.0, 1.0, 1.0);
            mTGPolyline.SetDatabaseDefaults();

            //Set color
            mTGPolyline.ColorIndex = mColorIndex;
            mTGPolyline.ConstantWidth = transientGraphics.Methods.screenAspectRatio(Convert.ToByte(10.0 * mColorIndex));

            //Add transient graphics
            IntegerCollection col = new IntegerCollection();
            TransientManager.CurrentTransientManager.AddTransient(mTGPolyline, TransientDrawingMode.DirectShortTerm, 128, col);
        }

        private void ClearTGPolyline()
        {
            if (mTGPolyline != null)
            {
                //Remove transient graphic effect
                IntegerCollection intCol = new IntegerCollection();
                TransientManager.CurrentTransientManager.EraseTransient(mTGPolyline, intCol);

                //dispose the polyline used to show transient graphic effect
                mTGPolyline.Dispose();
                mTGPolyline = null;
            }
        }
    }
}

Here is a video demonstrating my code: http://screencast.com/t/MzgxOWE5MDIt

I've also demonstrated your code from your blog post: http://drive-cad-with-code.blogspot.com/2009/07/help-autocad-users-visually-with_24.html

I've also attached the Visual Studio project and compile DLL.  I hope it is OK that I included your code from that blog post.

I'm not completely happy with the results as it is very radical from the entity highlight property but you code certainly provides many opportunities.  As you'll see I added code to change the width, based on the screen zoom ratio, as the user moves the cursor.

Thanks for you help!
Doug
« Last Edit: August 27, 2010, 04:42:00 PM by dugk »

n.yuan

  • Bull Frog
  • Posts: 348
Re: a better entity highlight?
« Reply #7 on: August 27, 2010, 04:55:10 PM »
Glad if my code is of any help. No problem if you quoted/used some of the code.

In my code, I made the entity color change with the mouse moving. It is just to show a possibility of making different visual hint. But in your particular case, seeing from your video clip, the color changing might be a bit annoying to user :-(



Norman,

Your code helped me create what I was hoping to create.  Here is the code I created with your help:
Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;

using AcApSrvApp = Autodesk.AutoCAD.ApplicationServices.Application;
using AcApDbSrv = Autodesk.AutoCAD.DatabaseServices;

using System;

namespace transientGraphics
{
    public class tgLineJig
    {
        private AcApDbSrv.Polyline mTGPolyline = null;
        private AcApDbSrv.Line mTargetLine;
        private Editor mEditor;
        private Database mDB;
        private Document mDoc;

        private Point3d mBasePoint;
        private int mColorIndex = 1;

        private Plane planeXY = new Plane(new Point3d(0, 0, 0), Vector3d.ZAxis);

        public tgLineJig(Document doc)
        {
            mDoc = doc;
            mDB = doc.Database;
            mEditor = doc.Editor;
        }

        public void ShowTGJig()
        {
            transientGraphics.Methods.setOsMode(0);

            //Option to pick the target polyline
            PromptEntityOptions eOpt = new PromptEntityOptions("\nPick a line:");

            //Only allow to pick line
            eOpt.SetRejectMessage("\nYou must pick a line:");
            eOpt.AddAllowedClass(typeof(AcApDbSrv.Line), true);

            //Do the pick
            PromptEntityResult eRes = mEditor.GetEntity(eOpt);
            if (eRes.Status != PromptStatus.OK) return;

            //Get the target polyline
            ObjectId targetId = eRes.ObjectId;
            AcApDbSrv.Line target = GetLine(targetId);
            if (target == null) return;

            mTargetLine = target;

            //Set base point
            mBasePoint = mTargetLine.StartPoint;

            //Set base point for second pick so that a rubberband will be shown when mouse is moving
            PromptPointOptions opt2 = new PromptPointOptions("\nClick anywhere to exit:");
            opt2.AllowArbitraryInput = true;

            //Start monitoring pointer move
            mEditor.PointMonitor += new PointMonitorEventHandler(mEditor_PointMonitor);

            //Start asking user to do second pick (exit) so that the "jig" image will move with mouse
            mEditor.GetPoint(opt2);

            //Once the second point is picked, clear the transient graphic "jig". After this, since
            //a new point is obtained with the jig;s visual help, one can then do copy/move/insert...
            ClearTGPolyline();

            //End pointer move monitoring
            mEditor.PointMonitor -= new PointMonitorEventHandler(mEditor_PointMonitor);
        }

        private void mEditor_PointMonitor(object sender, PointMonitorEventArgs e)
        {
            //Whenever point moves, draw a new transient graphic image at mouse point
            DrawTGPolyline(e.Context.RawPoint);

            //iterate colorindex, so the jig's color changes with mouse move, thus more eye-catching
            mColorIndex += 1;
            if (mColorIndex > 8) mColorIndex = 1;
        }

        private AcApDbSrv.Line GetLine(ObjectId id)
        {
            AcApDbSrv.Line ln = null;
            using (Transaction tran = mDB.TransactionManager.StartOpenCloseTransaction())
            {
                ln = tran.GetObject(id, OpenMode.ForRead) as AcApDbSrv.Line;
                tran.Commit();
            }
            return ln;
        }

        private void DrawTGPolyline(Point3d movePoint)
        {
            //Clear existing transient graphic image
            ClearTGPolyline();

            //Create a polyline for the transient graphics
            mTGPolyline = new AcApDbSrv.Polyline(2);
            mTGPolyline.AddVertexAt(0, mTargetLine.StartPoint.Convert2d(planeXY), 0.0, 1.0, 1.0);
            mTGPolyline.AddVertexAt(0, mTargetLine.EndPoint.Convert2d(planeXY), 0.0, 1.0, 1.0);
            mTGPolyline.SetDatabaseDefaults();

            //Set color
            mTGPolyline.ColorIndex = mColorIndex;
            mTGPolyline.ConstantWidth = transientGraphics.Methods.screenAspectRatio(Convert.ToByte(10.0 * mColorIndex));

            //Add transient graphics
            IntegerCollection col = new IntegerCollection();
            TransientManager.CurrentTransientManager.AddTransient(mTGPolyline, TransientDrawingMode.DirectShortTerm, 128, col);
        }

        private void ClearTGPolyline()
        {
            if (mTGPolyline != null)
            {
                //Remove transient graphic effect
                IntegerCollection intCol = new IntegerCollection();
                TransientManager.CurrentTransientManager.EraseTransient(mTGPolyline, intCol);

                //dispose the polyline used to show transient graphic effect
                mTGPolyline.Dispose();
                mTGPolyline = null;
            }
        }
    }
}

Here is a video demonstrating my code: http://screencast.com/t/MzgxOWE5MDIt

I've also demonstrated your code from your blog post: http://drive-cad-with-code.blogspot.com/2009/07/help-autocad-users-visually-with_24.html

I've also attached the Visual Studio project and compile DLL.  I hope it is OK that I included your code from that blog post.

I'm not completely happy with the results as it is very radical from the entity highlight property but you code certainly provides many opportunities.  As you'll see I added code to change the width, based on the screen zoom ratio, as the user moves the cursor.

Thanks for you help!
Doug

dugk

  • Guest
Re: a better entity highlight?
« Reply #8 on: August 27, 2010, 05:16:04 PM »
I agree that the user probably won't like my result.  I don't much either.

I was thinking of dividing the line down into multiple lines and then coloring them to create a "piano"ing effect.  It shouldn't be too difficult.  Any other creative ideas for the UI would be appreciated.

And if someone wants to suggest now to make it a timed sequence as opposed to the PointMonitorEventHandler/getPoint method I would like to incorporate that as well.

Thanks!
Doug

dugk

  • Guest
Re: a better entity highlight?
« Reply #9 on: August 28, 2010, 01:59:03 AM »
I've gotten another version for you to take a look at:  http://screencast.com/t/NWMyMDkyN

This version uses multiple polylines and is animated as the mouse moves.

Let me know what you think of this version.

Here is the main code and I've attached the Visual Studio project.
Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;

using AcApSrvApp = Autodesk.AutoCAD.ApplicationServices.Application;
using AcApDbSrv = Autodesk.AutoCAD.DatabaseServices;

using System;

namespace transientGraphics
{
    public class tgLineJig2
    {
        private static AcApDbSrv.Line mTargetLine;
        private static AcApDbSrv.Polyline[] tgPolylines = new AcApDbSrv.Polyline[0];
        private static double screenRatio;
        private static double nPlines;
        private static double plineLength;
        private static double lineAngle;
        private static int widthIndex = 1;
        private static Plane planeXY = new Plane(new Point3d(0, 0, 0), Vector3d.ZAxis);
        private static Editor mEditor;
        private static Database mDB;

        public tgLineJig2(Document doc)
        {
            mDB = doc.Database;
            mEditor = doc.Editor;
        }

        public void ShowTGJig()
        {
            //Option to pick the target polyline
            PromptEntityOptions eOpt = new PromptEntityOptions("\nPick a line:");

            //Only allow to pick line
            eOpt.SetRejectMessage("\nYou must pick a line:");
            eOpt.AddAllowedClass(typeof(AcApDbSrv.Line), true);

            //Do the pick
            PromptEntityResult eRes = mEditor.GetEntity(eOpt);
            if (eRes.Status != PromptStatus.OK) return;

            //Get the target polyline
            ObjectId targetId = eRes.ObjectId;
            AcApDbSrv.Line target = Methods.GetLine(mDB, targetId);
            if (target == null) return;

            mTargetLine = target;
            lineAngle = mTargetLine.Angle;

            Methods.setOsMode(0);

            //Set base point for second pick so that a rubberband will be shown when mouse is moving
            PromptPointOptions opt2 = new PromptPointOptions("\nClick anywhere to exit:");
            opt2.AllowArbitraryInput = true;

            //Start monitoring pointer move
            mEditor.PointMonitor += new PointMonitorEventHandler(mEditor_PointMonitor);

            //Start asking user to do second pick (exit) so that the "jig" image will move with mouse
            mEditor.GetPoint(opt2);

            //Once the second point is picked, clear the transient graphic "jig". After this, since
            //a new point is obtained with the jig;s visual help, one can then do copy/move/insert...
            ClearTGPolyline();

            //End pointer move monitoring
            mEditor.PointMonitor -= new PointMonitorEventHandler(mEditor_PointMonitor);
        }

        private static void mEditor_PointMonitor(object sender, PointMonitorEventArgs e)
        {
            //Whenever point moves, draw a new transient graphic image at mouse point
            DrawTGPolyline(e.Context.RawPoint);
        }

        private static void DrawTGPolyline(Point3d movePoint)
        {
            //Clear existing transient graphic image
            ClearTGPolyline();

            tgPolylines = new AcApDbSrv.Polyline[0];
           
            screenRatio = Methods.screenAspectRatio();
            nPlines = (int)Math.Truncate(mTargetLine.Length / screenRatio) / 4;
            plineLength = mTargetLine.Length / nPlines;

            Point3d sp = mTargetLine.StartPoint;
            Point3d ep = Methods.Polar(sp, lineAngle, plineLength);
            for (int i = 0; i < nPlines; i++)
            {
                if (widthIndex % 8 == 0)
                {
                    //Create a polyline for the transient graphics
                    AcApDbSrv.Polyline tgPolyline = new AcApDbSrv.Polyline(2);
                    tgPolyline.AddVertexAt(0, sp.Convert2d(planeXY), 0.0, 1.0, 1.0);
                    tgPolyline.AddVertexAt(0, ep.Convert2d(planeXY), 0.0, 1.0, 1.0);
                    tgPolyline.SetDatabaseDefaults();

                    //Set width
                    tgPolyline.ConstantWidth = Methods.screenAspectRatio(Convert.ToByte(5));

                    //Add transient graphics
                    IntegerCollection col = new IntegerCollection();
                    TransientManager.CurrentTransientManager.AddTransient(tgPolyline, TransientDrawingMode.DirectShortTerm, 128, col);
                    tgPolylines = (AcApDbSrv.Polyline[])Methods.ResizeArray(tgPolylines, tgPolylines.Length + 1);
                    tgPolylines[tgPolylines.Length - 1] = tgPolyline;
                }
               
                sp = Methods.Polar(sp, lineAngle, plineLength);
                ep = Methods.Polar(ep, lineAngle, plineLength);

                widthIndex++;
                if (widthIndex > 8)
                    widthIndex = 1;
            }
        }

        private static void ClearTGPolyline()
        {
            if (tgPolylines.Length > 0)
            {
                IntegerCollection intCol = new IntegerCollection();
                for (int i = 0; i < tgPolylines.Length; i++)
                {
                    //Remove transient graphic effect
                    TransientManager.CurrentTransientManager.EraseTransient(tgPolylines[i], intCol);

                    //dispose the polyline used to show transient graphic effect
                    tgPolylines[i].Dispose();
                }
            }
        }
    }
}

dugk

  • Guest
Re: a better entity highlight?
« Reply #10 on: August 28, 2010, 02:46:02 AM »
Here is my unsuccessful attempt at getting it to run for a certain amount of time and not based on the movement of the mouse and a getPoint:
Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;

using AcApSrvApp = Autodesk.AutoCAD.ApplicationServices.Application;
using AcApDbSrv = Autodesk.AutoCAD.DatabaseServices;

using System;
using System.Threading;

namespace transientGraphics
{
    public class tgLineJig3
    {
        private static AcApDbSrv.Line mTargetLine;
        private static AcApDbSrv.Polyline[] tgPolylines = new AcApDbSrv.Polyline[0];
        private static double screenRatio;
        private static double nPlines;
        private static double plineLength;
        private static double lineAngle;
        private static int widthIndex = 1;
        private static Plane planeXY = new Plane(new Point3d(0, 0, 0), Vector3d.ZAxis);
        private static Editor mEditor;
        private static Database mDB;

        public tgLineJig3(Document doc)
        {
            mDB = doc.Database;
            mEditor = doc.Editor;
        }

        public void ShowTGJig()
        {
            //Option to pick the target polyline
            PromptEntityOptions eOpt = new PromptEntityOptions("\nPick a line:");

            //Only allow to pick line
            eOpt.SetRejectMessage("\nYou must pick a line:");
            eOpt.AddAllowedClass(typeof(AcApDbSrv.Line), true);

            //Do the pick
            PromptEntityResult eRes = mEditor.GetEntity(eOpt);
            if (eRes.Status != PromptStatus.OK) return;

            //Get the target polyline
            ObjectId targetId = eRes.ObjectId;
            AcApDbSrv.Line target = Methods.GetLine(mDB, targetId);
            if (target == null) return;

            mTargetLine = target;
            lineAngle = mTargetLine.Angle;

            for (int i = 0; i < 100; i++)
            {
                DrawTGPolylines();
                Thread.Sleep(100);
            }

            //Once the second point is picked, clear the transient graphic "jig". After this, since
            //a new point is obtained with the jig;s visual help, one can then do copy/move/insert...
            ClearTGPolyline();
        }

        private static void DrawTGPolylines()
        {
            //Clear existing transient graphic image
            ClearTGPolyline();

            tgPolylines = new AcApDbSrv.Polyline[0];

            screenRatio = Methods.screenAspectRatio();
            nPlines = (int)Math.Truncate(mTargetLine.Length / screenRatio) / 4;
            plineLength = mTargetLine.Length / nPlines;

            Point3d sp = mTargetLine.StartPoint;
            Point3d ep = Methods.Polar(sp, lineAngle, plineLength);
            for (int i = 0; i < nPlines; i++)
            {
                if (widthIndex % 8 == 0)
                {
                    //Create a polyline for the transient graphics
                    AcApDbSrv.Polyline tgPolyline = new AcApDbSrv.Polyline(2);
                    tgPolyline.AddVertexAt(0, sp.Convert2d(planeXY), 0.0, 1.0, 1.0);
                    tgPolyline.AddVertexAt(0, ep.Convert2d(planeXY), 0.0, 1.0, 1.0);
                    tgPolyline.SetDatabaseDefaults();

                    //Set width
                    tgPolyline.ConstantWidth = Methods.screenAspectRatio(Convert.ToByte(5));

                    //Add transient graphics
                    IntegerCollection col = new IntegerCollection();
                    TransientManager.CurrentTransientManager.AddTransient(tgPolyline, TransientDrawingMode.DirectShortTerm, 128, col);
                    tgPolylines = (AcApDbSrv.Polyline[])Methods.ResizeArray(tgPolylines, tgPolylines.Length + 1);
                    tgPolylines[tgPolylines.Length - 1] = tgPolyline;
                }

                sp = Methods.Polar(sp, lineAngle, plineLength);
                ep = Methods.Polar(ep, lineAngle, plineLength);

                widthIndex++;
                if (widthIndex > 8)
                    widthIndex = 1;
            }
        }

        private static void ClearTGPolyline()
        {
            if (tgPolylines.Length > 0)
            {
                IntegerCollection intCol = new IntegerCollection();
                for (int i = 0; i < tgPolylines.Length; i++)
                {
                    //Remove transient graphic effect
                    TransientManager.CurrentTransientManager.EraseTransient(tgPolylines[i], intCol);

                    //dispose the polyline used to show transient graphic effect
                    tgPolylines[i].Dispose();
                }
            }
        }
    }
}

Suggestions on how to make it work are appreciated. :)

n.yuan

  • Bull Frog
  • Posts: 348
Re: a better entity highlight?
« Reply #11 on: September 02, 2010, 10:43:17 AM »
Another possible approach you can look into: HighlightOverrule.

I just posted some simple code on this here:

http://drive-cad-with-code.blogspot.com/2010/09/highlight-autocad-entity-in-your-own.html

It might open your mind for more choices.

dugk

  • Guest
Re: a better entity highlight?
« Reply #12 on: September 02, 2010, 11:03:31 AM »
Hi Norman,

Thanks for adding that example as well!!!

Doug

kaefer

  • Guest
Re: a better entity highlight?
« Reply #13 on: September 03, 2010, 03:59:08 AM »
Another possible approach you can look into: HighlightOverrule.

I just posted some simple code on this here:

http://drive-cad-with-code.blogspot.com/2010/09/highlight-autocad-entity-in-your-own.html
Hi Norman,

wonder why it's necessary to lock the document, since the operation is on the current doc.

Hope you dont't mind that I've ported your example to f#, which allows a succinct expression of the singleton pattern required in Overrule and avoids the pitfalls associated with properties on uninitialized objects. What happens if you execute HLColor before MyHLOn? <evil grin>

Code: [Select]
// Originally c# by Norman Yuan
// http://drive-cad-with-code.blogspot.com/2010/09/highlight-autocad-entity-in-your-own.html
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Runtime

type acApp = Autodesk.AutoCAD.ApplicationServices.Application

type MyHighlightOverrule() as this =
    inherit HighlightOverrule()

    let mutable _colorIndex = 1
    let mutable _oldColorIndex = 1

    do  MyHighlightOverrule.AddOverrule(
            RXClass.GetClass typeof<Polyline>, this, true )
       
    member x.ColorIndex
        with set v = _colorIndex <- v
        and get() = _colorIndex
       
    override x.Highlight(entity, subId, highlightAll) =
        match entity with
        | :? Polyline as pline ->
            let doc = acApp.DocumentManager.MdiActiveDocument
            use dl = doc.LockDocument()
            use tr = doc.TransactionManager.StartTransaction()
           
            pline.UpgradeOpen()
            _oldColorIndex <- pline.ColorIndex
            pline.ColorIndex <- _colorIndex
            pline.DowngradeOpen()
               
            base.Highlight(entity, subId, highlightAll)
        | _ -> ()

    override x.Unhighlight(entity, subId, highlightAll) =
        match entity with
        | :? Polyline as pline ->
            let doc = acApp.DocumentManager.MdiActiveDocument
            use dl = doc.LockDocument()
            use tr = doc.TransactionManager.StartTransaction()
           
            pline.UpgradeOpen()
            pline.ColorIndex <- _oldColorIndex
            pline.DowngradeOpen()
               
            base.Unhighlight(entity, subId, highlightAll)
        | _ -> ()

module Commands =

    let hlOverRule = lazy(new MyHighlightOverrule())
   
    [<CommandMethod "MyHLOn">]
    let TurnOnMyHighlight() =
        hlOverRule.Force() |> ignore
        MyHighlightOverrule.Overruling <- true

    [<CommandMethod "MyHLOff">]
    let TurnOffMyHighlight() =
        hlOverRule.Force() |> ignore
        MyHighlightOverrule.Overruling <- false
       
    [<CommandMethod "HLColor">]
    let SetHighlightColor() =
        let ed = acApp.DocumentManager.MdiActiveDocument.Editor
        let pir =
            new PromptIntegerOptions(
                "\nEnter color index (a number form 1 to 7):",
                LowerLimit = 1,
                UpperLimit = 7 )
            |> ed.GetInteger
        if pir.Status = PromptStatus.OK then
            hlOverRule.Value.ColorIndex <- pir.Value
Cheers, Thorsten

n.yuan

  • Bull Frog
  • Posts: 348
Re: a better entity highlight?
« Reply #14 on: September 03, 2010, 09:33:55 AM »
1. Yes, that is a bug that if you execute "HLColor" before "MyHLOn". IN the "HLColor" command method, I am supposed to start with something like below as the first line of code:

If (_hlOverrule==null) return;

2. Locking document. SInce the custom HighlightOverrule might be used in other programs, such as a modeless window, where locking document might be required, so I simply do the locking inside the Highlight/Unhighlight, so that the other programs that use this component would not have to lock document just because of the custom highlight/unhighlight. Of course if the other programs need to lock document because of their own process, there would be nested locking, and there may be penalties on Acad performance, but it would be safer and easier for the other programs to use this component.


Another possible approach you can look into: HighlightOverrule.

I just posted some simple code on this here:

http://drive-cad-with-code.blogspot.com/2010/09/highlight-autocad-entity-in-your-own.html
Hi Norman,

wonder why it's necessary to lock the document, since the operation is on the current doc.

Hope you dont't mind that I've ported your example to f#, which allows a succinct expression of the singleton pattern required in Overrule and avoids the pitfalls associated with properties on uninitialized objects. What happens if you execute HLColor before MyHLOn? <evil grin>

Code: [Select]
// Originally c# by Norman Yuan
// http://drive-cad-with-code.blogspot.com/2010/09/highlight-autocad-entity-in-your-own.html
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Runtime

type acApp = Autodesk.AutoCAD.ApplicationServices.Application

type MyHighlightOverrule() as this =
    inherit HighlightOverrule()

    let mutable _colorIndex = 1
    let mutable _oldColorIndex = 1

    do  MyHighlightOverrule.AddOverrule(
            RXClass.GetClass typeof<Polyline>, this, true )
       
    member x.ColorIndex
        with set v = _colorIndex <- v
        and get() = _colorIndex
       
    override x.Highlight(entity, subId, highlightAll) =
        match entity with
        | :? Polyline as pline ->
            let doc = acApp.DocumentManager.MdiActiveDocument
            use dl = doc.LockDocument()
            use tr = doc.TransactionManager.StartTransaction()
           
            pline.UpgradeOpen()
            _oldColorIndex <- pline.ColorIndex
            pline.ColorIndex <- _colorIndex
            pline.DowngradeOpen()
               
            base.Highlight(entity, subId, highlightAll)
        | _ -> ()

    override x.Unhighlight(entity, subId, highlightAll) =
        match entity with
        | :? Polyline as pline ->
            let doc = acApp.DocumentManager.MdiActiveDocument
            use dl = doc.LockDocument()
            use tr = doc.TransactionManager.StartTransaction()
           
            pline.UpgradeOpen()
            pline.ColorIndex <- _oldColorIndex
            pline.DowngradeOpen()
               
            base.Unhighlight(entity, subId, highlightAll)
        | _ -> ()

module Commands =

    let hlOverRule = lazy(new MyHighlightOverrule())
   
    [<CommandMethod "MyHLOn">]
    let TurnOnMyHighlight() =
        hlOverRule.Force() |> ignore
        MyHighlightOverrule.Overruling <- true

    [<CommandMethod "MyHLOff">]
    let TurnOffMyHighlight() =
        hlOverRule.Force() |> ignore
        MyHighlightOverrule.Overruling <- false
       
    [<CommandMethod "HLColor">]
    let SetHighlightColor() =
        let ed = acApp.DocumentManager.MdiActiveDocument.Editor
        let pir =
            new PromptIntegerOptions(
                "\nEnter color index (a number form 1 to 7):",
                LowerLimit = 1,
                UpperLimit = 7 )
            |> ed.GetInteger
        if pir.Status = PromptStatus.OK then
            hlOverRule.Value.ColorIndex <- pir.Value
Cheers, Thorsten