Kean Walmsley


  • About the Author
    Kean on Google+

July 2014

Sun Mon Tue Wed Thu Fri Sat
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    








« Adding a new annotation scale in AutoCAD using .NET | Main | Adding a context menu to AutoCAD objects using .NET »

April 27, 2007

Making AutoCAD objects annotative using .NET

In the last post we looked at how to add a new annotative scale to an AutoCAD drawing.

In this post we'll look at what's needed to make an object annotative - providing it's of a type that supports annotation scaling, of course. Once again, this post is based on functionality introduced in AutoCAD 2008.

I hit my head against the problem for a while, having tried my best to convert the technique shown in the AnnotationScaling ObjectARX sample (which uses a protocol extension to access objects stored in an annotative entity's extension dictionary) to .NET. I finally ended up asking our Engineering team: Ravi Pothineni came back with some code that uses an internal assembly (but one that ships with AutoCAD) to do this. Apparently this will become standard functionality in a future release of AutoCAD - it'll just be available directly from DBObject, rather than being in a separate "helper" - but in the meantime you will have to use slightly more cumbersome code, such as that shown below, and add a reference to AcMgdInternal.dll for it to work. As indicated by the name, this functionality is unsupported and to be used at your own risk.

Here's the C# code - the "ADS" command is basically the one shown previously (renamed from "AS") and the "ATS" function is the new command that makes an object annotative, attaching annotation scales to it:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.Internal;


namespace AnnotationScaling

{

  public class Commands

  {

    [CommandMethod("ADS")]

    static public void addScale()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

      try

      {

        ObjectContextManager ocm =

          db.ObjectContextManager;

        if (ocm != null)

        {

          // Now get the Annotation Scaling context collection

          // (named ACDB_ANNOTATIONSCALES_COLLECTION)

          ObjectContextCollection occ =

            ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");


          if (occ != null)

          {

            // Create a brand new scale context

            AnnotationScale asc = new AnnotationScale();

            asc.Name = "MyScale 1:28";

            asc.PaperUnits = 1;

            asc.DrawingUnits = 28;

            // Add it to the drawing's context collection

            occ.AddContext(asc);

          }

        }

      }

      catch (System.Exception ex)

      {

        ed.WriteMessage(ex.ToString());

      }

    }


    [CommandMethod("ATS")]

    static public void attachScale()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

      ObjectContextManager ocm =

        db.ObjectContextManager;

      ObjectContextCollection occ =

        ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");


      Transaction tr =

        doc.TransactionManager.StartTransaction();

      using (tr)

      {

        PromptEntityOptions opts =

          new PromptEntityOptions("\nSelect entity: ");

        opts.SetRejectMessage(

          "\nEntity must support annotation scaling."

        );

        opts.AddAllowedClass(typeof(DBText), false);

        opts.AddAllowedClass(typeof(MText), false);

        opts.AddAllowedClass(typeof(Dimension), false);

        opts.AddAllowedClass(typeof(Leader), false);

        opts.AddAllowedClass(typeof(Hatch), false);


        PromptEntityResult per = ed.GetEntity(opts);

        if (per.ObjectId != ObjectId.Null)

        {

          DBObject obj =

            tr.GetObject(per.ObjectId, OpenMode.ForRead);

          if (obj != null)

          {

            obj.UpgradeOpen();

            obj.Annotative = AnnotativeStates.True;

            ObjectContexts.AddContext(obj, occ.GetContext("1:1"));

            ObjectContexts.AddContext(obj, occ.GetContext("1:2"));

            ObjectContexts.AddContext(obj, occ.GetContext("1:10"));

            ObjectContext oc = occ.GetContext("MyScale 1:28");

            if (oc != null)

            {

              ObjectContexts.AddContext(obj, oc);

            }

          }

        }

        tr.Commit();

      }

    }

  }

}

You'll notice that if you run the ADS command before ATS, you'll also get the newly-added annotation scale in the selected object's list:

Attached_annotation_scale

 

Update:

From AutoCAD 2009 onwards, it's now possible to modify annotation scales on an object directly without relying on unsupported funcitonality in acmgdinternal.dll.

Here's the modified C# code:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

 

namespace AnnotationScaling

{

  public class Commands

  {

    [CommandMethod("ADS")]

    static public void addScale()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

      try

      {

        ObjectContextManager ocm =

          db.ObjectContextManager;

        if (ocm != null)

        {

          // Now get the Annotation Scaling context collection

          // (named ACDB_ANNOTATIONSCALES_COLLECTION)

          ObjectContextCollection occ =

            ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");

 

          if (occ != null)

          {

            // Create a brand new scale context

            AnnotationScale asc = new AnnotationScale();

            asc.Name = "MyScale 1:28";

            asc.PaperUnits = 1;

            asc.DrawingUnits = 28;

            // Add it to the drawing's context collection

            occ.AddContext(asc);

          }

        }

      }

      catch (System.Exception ex)

      {

        ed.WriteMessage(ex.ToString());

      }

    }

 

    [CommandMethod("ATS")]

    static public void attachScale()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

      ObjectContextManager ocm =

        db.ObjectContextManager;

      ObjectContextCollection occ =

        ocm.GetContextCollection("ACDB_ANNOTATIONSCALES");

 

      Transaction tr =

        doc.TransactionManager.StartTransaction();

      using (tr)

      {

        PromptEntityOptions opts =

          new PromptEntityOptions("\nSelect entity: ");

        opts.SetRejectMessage(

          "\nEntity must support annotation scaling."

        );

        opts.AddAllowedClass(typeof(DBText), false);

        opts.AddAllowedClass(typeof(MText), false);

        opts.AddAllowedClass(typeof(Dimension), false);

        opts.AddAllowedClass(typeof(Leader), false);

        opts.AddAllowedClass(typeof(Table), false);

        opts.AddAllowedClass(typeof(Hatch), false);

 

        PromptEntityResult per = ed.GetEntity(opts);

        if (per.ObjectId != ObjectId.Null)

        {

          DBObject obj =

            tr.GetObject(per.ObjectId, OpenMode.ForRead);

          if (obj != null)

          {

            obj.UpgradeOpen();

            obj.Annotative = AnnotativeStates.True;

            obj.AddContext(occ.GetContext("1:1"));

            obj.AddContext(occ.GetContext("1:2"));

            obj.AddContext(occ.GetContext("1:10"));

            ObjectContext oc = occ.GetContext("MyScale 1:28");

            if (oc != null)

            {

              obj.AddContext(oc);           

            }

          }

        }

        tr.Commit();

      }

    }

  }

}

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83452464869e200d8348e45d453ef

Listed below are links to weblogs that reference Making AutoCAD objects annotative using .NET:

blog comments powered by Disqus

10 Random Posts