November 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            










« Smoothly transitioning between 3D AutoCAD views using .NET - Part 2 | Main | Painting properties between dynamic AutoCAD blocks using .NET »

March 04, 2009

Accessing the properties of a dynamic AutoCAD block using .NET

This is one of those funny scenarios... I was just thinking about what to do for my next post - whether to dive into some new features of AutoCAD 2010 (which I will do soon, I promise! :-) or whether to choose something from my ever-increasing to-do list, when I received two emails.

One was from our old friend Fernando Malard, suggesting a topic for a blog post, and the other was from Philippe Leefsma, a member of our DevTech team in Europe, in response to an ADN members question. It provided some code that could eventually form the basis for a response to Fernando's question. Coincidence? Maybe. Am I one to ignore serendipity at work (or to look a gift horse in the mouth)? No!

So, here's Fernando's question:

Just would suggest a new topic for your Blog. An article explaining how to insert a dynamic block and modifying its dynamic properties like point, rotation, dimension. This is something I’m currently working on .NET and I think it would be a very interesting topic to evolve.

Philippe's code is a little different - it shows how to retrieve and display the "dynamic" properties of a dynamic block read in from an external file - but it was a great start for my first step towards Fernando's goal, which was simply to access the dynamic properties for a block selected by the user.

Here's the C# code I based on Philippe's:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Geometry;

using Autodesk.AutoCAD.Runtime;

 

namespace DynamicBlocks

{

  public class Commands

  {

    [CommandMethod("DBP")]

    static public void DynamicBlockProps()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Database db = doc.Database;

      Editor ed = doc.Editor;

 

      PromptStringOptions pso =

        new PromptStringOptions(

          "\nEnter dynamic block name or enter to select: "

        );

 

      pso.AllowSpaces = true;

      PromptResult pr = ed.GetString(pso);

 

      if (pr.Status != PromptStatus.OK)

        return;

 

      Transaction tr =

        db.TransactionManager.StartTransaction();

      using (tr)

      {

        BlockReference br = null;

 

        // If a null string was entered allow entity selection

 

        if (pr.StringResult == "")

        {

          // Select a block reference

 

          PromptEntityOptions peo =

            new PromptEntityOptions(

              "\nSelect dynamic block reference: "

            );

 

          peo.SetRejectMessage("\nEntity is not a block.");

          peo.AddAllowedClass(typeof(BlockReference), false);

 

          PromptEntityResult per =

            ed.GetEntity(peo);

 

          if (per.Status != PromptStatus.OK)

            return;

 

          // Access the selected block reference

 

          br =

            tr.GetObject(

              per.ObjectId,

              OpenMode.ForRead

            ) as BlockReference;

        }

        else

        {

          // Otherwise we look up the block by name

 

          BlockTable bt =

            tr.GetObject(

              db.BlockTableId,

              OpenMode.ForRead) as BlockTable;

 

          if (!bt.Has(pr.StringResult))

          {

            ed.WriteMessage(

              "\nBlock \"" + pr.StringResult + "\" does not exist."

            );

            return;

          }

 

          // Create a new block reference referring to the block

 

          br =

            new BlockReference(

              new Point3d(),

              bt[pr.StringResult]

            );

        }

 

        BlockTableRecord btr =

          (BlockTableRecord)tr.GetObject(

            br.DynamicBlockTableRecord,

            OpenMode.ForRead

          );

 

        // Call our function to display the block properties

 

        DisplayDynBlockProperties(ed, br, btr.Name);

 

        // Committing is cheaper than aborting

 

        tr.Commit();

      }

    }

 

    private static void DisplayDynBlockProperties(

      Editor ed, BlockReference br, string name

    )

    {

      // Only continue is we have a valid dynamic block

 

      if (br != null && br.IsDynamicBlock)

      {

        ed.WriteMessage(

          "\nDynamic properties for \"{0}\"\n",

          name

        );

 

        // Get the dynamic block's property collection

 

        DynamicBlockReferencePropertyCollection pc =

          br.DynamicBlockReferencePropertyCollection;

 

        // Loop through, getting the info for each property

 

        foreach (DynamicBlockReferenceProperty prop in pc)

        {

          // Start with the property name, type and description

 

          ed.WriteMessage(

            "\nProperty: \"{0}\" : {1}",

            prop.PropertyName,

            prop.UnitsType

          );

 

          if (prop.Description != "")

            ed.WriteMessage(

              "\n  Description: {0}",

              prop.Description

            );

 

          // Is it read-only?

 

          if (prop.ReadOnly)

            ed.WriteMessage(" (Read Only)");

 

          // Get the allowed values, if it's constrained

 

          bool first = true;

 

          foreach (object value in prop.GetAllowedValues())

          {

            ed.WriteMessage(

              (first ? "\n  Allowed values: [" : ", ")

            );

            ed.WriteMessage("\"{0}\"", value);

 

            first = false;

          }

          if (!first)

            ed.WriteMessage("]");

 

          // And finally the current value

 

          ed.WriteMessage(

            "\n  Current value: \"{0}\"\n",

            prop.Value

          );

        }

      }

    }

  }

}


Here's what happens when we run the DBP command, selecting the "Hex Socket Bolt (Side) - Metric" block from the "Mechanical - Metric.dwg" file in the Samples\Dynamic Blocks folder of your AutoCAD installation.

Command: DBP

Enter dynamic block name or enter to select:

Select dynamic block reference:

 

Dynamic properties for "Hex Socket Bolt (Side) - Metric"

 

Property: "d1" : Distance

  Allowed values: ["3", "4", "5", "6", "8", "10", "12", "14", "16", "20", "24",

"27", "30", "36"]

  Current value: "14"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(97.714,-5,0)"

 

Property: "b" : Distance

  Allowed values: ["18", "20", "22", "24", "28", "32", "36", "40", "44", "52",

"57", "60", "65", "66", "72", "73", "84", "85"]

  Current value: "40"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(100,-3.5,0)"

 

Property: "k" : Distance

  Allowed values: ["3", "4", "5", "6", "8", "10", "12", "14", "16", "20", "24",

"27", "30", "36"]

  Current value: "14"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(5.64204767561892E-15,-7,0)"

 

Property: "d2" : Distance

  Allowed values: ["5.5", "7", "8.5", "10", "13", "16", "18", "21", "24", "30",

"36", "40", "45", "54"]

  Current value: "21"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(3.5527136788005E-15,-8,0)"

 

Property: "Size" : NoUnits

  Allowed values: ["M3", "M4", "M5", "M6", "M8", "M10", "M12", "M14"]

  Current value: "M14"

 

Property: "Visibility" : NoUnits

  Allowed values: ["M3", "M4", "M5", "M6", "M8", "M10", "M12", "M14"]

  Current value: "M14"

 

Property: "Length (M3)" : Distance

  Description: Set the bolt length

  Allowed values: ["25", "30", "35", "40", "45", "50", "60"]

  Current value: "100"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(0,0,0)"

 

Property: "Length (M4)" : Distance

  Description: Set the bolt length

  Allowed values: ["30", "35", "40", "45", "50", "60", "70", "80"]

  Current value: "100"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(0,0,0)"

 

Property: "Length (M5)" : Distance

  Description: Set the bolt length

  Allowed values: ["30", "35", "40", "45", "50", "55", "60", "70", "80", "90",

"100"]

  Current value: "100"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(0,0,0)"

 

Property: "Length (M6)" : Distance

  Description: Set the bolt length

  Allowed values: ["35", "40", "45", "50", "55", "60", "65", "70", "75", "80",

"90", "100", "110", "120"]

  Current value: "100"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(2.25597318603832E-14,0,0)"

 

Property: "Length (M8)" : Distance

  Description: Set the bolt length

  Allowed values: ["40", "45", "50", "55", "60", "65", "70", "75", "80", "85",

"90", "100", "110", "120", "130", "140", "150", "160", "180", "200"]

  Current value: "100"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(2.25597318603832E-14,0,0)"

 

Property: "Length (M10)" : Distance

  Description: Set the bolt length

  Allowed values: ["45", "50", "55", "60", "65", "70", "75", "80", "85", "90",

"100", "110", "120", "130", "140", "150", "160", "180", "200"]

  Current value: "100"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(2.25597318603832E-14,0,0)"

 

Property: "Length (M12)" : Distance

  Description: Set the bolt length

  Allowed values: ["55", "60", "65", "70", "75", "80", "85", "90", "100",

"110", "120", "130", "140", "150", "160", "180", "200"]

  Current value: "100"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(2.25597318603832E-14,0,0)"

 

Property: "Length (M14)" : Distance

  Description: Set the bolt length

  Allowed values: ["60", "65", "70", "75", "80", "90", "100", "110", "120",

"130", "140", "150", "160"]

  Current value: "100"

 

Property: "Origin" : NoUnits (Read Only)

  Current value: "(2.25597318603832E-14,0,0)"


Many of the properties are actually 0, but have ended up being printed as a very small number... it would be simple enough to check these against a tolerance rather than trusting them to be understood as being zero.

OK, that's a good enough start for today. In the next post we'll address the need to capture dynamic properties from an inserted dynamic block and copy them across to another, already-inserted dynamic block. A bit like a "property painter" for dynamic blocks. (If you're thinking that this doesn't sound quite like what Fernando originally asked for, then you'd be quite right. We exchanged a few emails, and I then opted for a "property painter" approach to address the problem.)

Thanks for the inspiration, Fernando and Philippe! :-)

TrackBack

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

Listed below are links to weblogs that reference Accessing the properties of a dynamic AutoCAD block using .NET:

blog comments powered by Disqus

Feed/Share

10 Random Posts