Kean Walmsley

July 2009

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  

Twitter Updates

    follow me on Twitter



    « Free AutoCAD programming webcast: .NET for LISP Programmers | Main | Offline reading of "Through the Interface" »

    October 15, 2008

    Changing the colour of the contents of an AutoCAD block using .NET

    Here's a question that came in to us, recently:

    How can I show the AutoCAD color dialog from .NET? I need to allow the user to select a block, show the AutoCAD color dialog and apply the selected color to the contents of the selected block.

    A new member of DevTech Americas - Augusto Gonçalves, who's based in our São Paulo office - answered with the following code (which I've modified slightly, mostly to follow this blog's coding conventions). Thanks, Augusto!

    By the way, these previous posts may also be useful to those interested in this topic.

    Here's the C# code:

    using Autodesk.AutoCAD.ApplicationServices;

    using Autodesk.AutoCAD.DatabaseServices;

    using Autodesk.AutoCAD.EditorInput;

    using Autodesk.AutoCAD.Runtime;

    using Autodesk.AutoCAD.Windows;

    using Autodesk.AutoCAD.Colors;


    namespace ColorPicking

    {

      public class Commands

      {

        [CommandMethod("CB")]

        public void ColorBlock()

        {

          Document doc =

              Application.DocumentManager.MdiActiveDocument;

          Database db = doc.Database;

          Editor ed = doc.Editor;


          // Ask the user to select a block


          PromptEntityOptions peo =

            new PromptEntityOptions("\nSelect a block:");      

          peo.AllowNone = false;

          peo.SetRejectMessage("\nMust select a block.");

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


          PromptEntityResult per =

            ed.GetEntity(peo);


          if (per.Status != PromptStatus.OK)

            return;


          // Open the entity using a transaction


          Transaction tr =

            db.TransactionManager.StartTransaction();

          using (tr)

          {

            try

            {

              Entity ent =

                (Entity)tr.GetObject(

                  per.ObjectId,

                  OpenMode.ForRead

                );


              // Should always be a block reference,

              // but let's make sure


              BlockReference br = ent as BlockReference;

              if (br != null)

              {

                // Select the new color


                ColorDialog cd = new ColorDialog();

                cd.IncludeByBlockByLayer = true;

                cd.ShowDialog();


                // Change the color of the block itself


                br.UpgradeOpen();

                br.Color = cd.Color;


                // Change every entity to be of color ByBlock


                BlockTableRecord btr =

                  (BlockTableRecord)tr.GetObject(

                    br.BlockTableRecord,

                    OpenMode.ForRead

                  );


                // Iterate through the BlockTableRecord contents


                foreach (ObjectId id in btr)

                {

                  // Open the entity


                  Entity ent2 =

                    (Entity)tr.GetObject(id, OpenMode.ForWrite);


                  // Change each entity's color to ByBlock


                  ent2.Color =

                    Color.FromColorIndex(ColorMethod.ByBlock, 0);

                }

              }


              // Commit if there hasn't been a problem

              // (even if no objects changed: it's just quicker)


              tr.Commit();

            }

            catch (Autodesk.AutoCAD.Runtime.Exception e)

            {

              // Something went wrong


              ed.WriteMessage(e.ToString());

            }

          }

        }

      }

    }

    Here's a quick example of running the CB command on a block inserted from the "Architectural - Imperial" sample block library that ships with AutoCAD.

    After launching the CB command selecting our sports car, we can see the colour selection dialog, which allows us to select an AutoCAD colour index, a true color or a standard colour from a color book:

    Select color for block contents

    We can then see our block is changed to this colour (well, in fact the block is changed to be this colour and all its contents are all changed to be coloured ByBlock):

    Purple sports car

    This block happens to be a dynamic block, so if we change it to its truck representation, we see the colour has propagated there, also (as the geometry for this view also resides in the block table record, of course):

    Purple truck

    By the way, for those of you who are confused by my apparently inconsistent use of spelling, please see this previous post. :-)

    TrackBack

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

    Listed below are links to weblogs that reference Changing the colour of the contents of an AutoCAD block using .NET:

    Comments

    I should probably add that this code clearly doesn't deal with nested blocks, but that would be a relatively easy thing to address (should you so wish).

    Kean

    Kean,
    I was looking back at some of your posts, and noticed one on F#. It had the pretty green 3d math plotting pictures.
    You mentioned that you used the mouse middle click to do something, and that it sometimes needed a "drag" for the handler to kick in.
    I believe this is exactly the same problem I've been running into with the snap menu, and the behavior started in Acad 2006, when the CUI system was introduced.
    What I do is set mbuttonpan to 1. Then set my side mouse button as middle button.
    For the wheel click, I set my mouse driver to run keystroke F11, which brings up the snap menu due to having set F11 to do that in the acad CUI.
    Works great, but you must move the mouse after clicking the wheel, or no snap menu.
    This messes me up because I type the mnemonic of the snap, the mous stays still while doing so. I end up typing before the snap menu shows and it messes up the input, have to cancel out.

    Is there any possibility of ridding the need to move the mouse, for the handler to kick in?
    I really like realtime pan on side button, and osnap menu on wheel click, but have abandoned it for mbuttonpan set to 0 for now...
    thx

    James,

    The form this occurs in has nothing much to do with AutoCAD: it's a modal form thrown up by AutoCAD using DirectX to view a pretty 3D graph. So I suspect the problem I hit is a general Windows programming issue: something to do with window messages coming through from the mouse. Maybe it's the same one you're hitting, maybe not.

    Beyond me, I'm afraid - and there's no great need for me to fix this for the demo app I've thrown together - but hopefully you'll manage to work it out.

    Kean

    I NOT A JOB

    I HAVE C++ DEMO

    Verify your Comment

    Previewing your Comment

    This is only a preview. Your comment has not yet been posted.

    Working...
    Your comment could not be posted. Error type:
    Your comment has been posted. Post another comment

    The letters and numbers you entered did not match the image. Please try again.

    As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

    Having trouble reading this image? View an alternate.

    Working...

    Post a comment

    Feed & Share

    Search