Using the pickfirst selection from an AutoCAD .NET application

Many AutoCAD commands that work on sets of entities support two styles of working: verb-noun or noun-verb. This basically means that if the user has pre-selected a set of entities (the "noun") and then launch the command (the "verb") then the command will not need to request the user select them.

This is enabled using something called the pickfirst or implied selection set inside AutoCAD. To take advantage of this feature inside your commands the first thing to do is to use a special command-flag called "UsePickSet": this tells the AutoCAD editor not to clear the pickfirst set when the command is invoked. Next the command implementation will use the SelectImplied() method on the editor object to retrieve the pickfirst set, should one be available. At this stage it's also good practice to clear the pickfirst set with SetImpliedSelection().

The following C# sample shows a few extras, such as how to fall back on asking the user to select the objects if there isn't a pickfirst set. As for what we do with the selected entities... in this simple example each entity is opened for read and has its list() method called to dump out its contents to the command-line (just as the LIST command does). You could, of course, do something much more interesting with the object at this point (I'll try to show more examples of getting specific entity properties in a later post).

Here's the code:

using Autodesk.AutoCAD;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

namespace SelectionTest

{

  public class PickfirstTestCmds

  {

    // Must have UsePickSet specified

    [CommandMethod("PFT", CommandFlags.UsePickSet |

                          CommandFlags.Redraw |

                          CommandFlags.Modal)

    ]

    static public void PickFirstTest()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;

      try

      {

        PromptSelectionResult selectionRes =

          ed.SelectImplied();

        // If there's no pickfirst set available...

        if (selectionRes.Status == PromptStatus.Error)

        {

          // ... ask the user to select entities

          PromptSelectionOptions selectionOpts =

            new PromptSelectionOptions();

          selectionOpts.MessageForAdding =

            "\nSelect objects to list: ";

          selectionRes =

            ed.GetSelection(selectionOpts);

        }

        else

        {

          // If there was a pickfirst set, clear it

          ed.SetImpliedSelection(new ObjectId[0]);

        }

        // If the user has not cancelled...

        if (selectionRes.Status == PromptStatus.OK)

        {

          // ... take the selected objects one by one

          Transaction tr =

            doc.TransactionManager.StartTransaction();

          try

          {

            ObjectId[] objIds = selectionRes.Value.GetObjectIds();

            foreach (ObjectId objId in objIds)

            {

              Entity ent =

                (Entity)tr.GetObject(objId, OpenMode.ForRead);

              // In this simple case, just dump their properties

              // to the command-line using list

              ent.List();

              ent.Dispose();

            }

            // Although no changes were made, use Commit()

            // as this is much quicker than rolling back

            tr.Commit();

          }

          catch (Autodesk.AutoCAD.Runtime.Exception ex)

          {

            ed.WriteMessage(ex.Message);

            tr.Abort();

          }

        }

      }

      catch(Autodesk.AutoCAD.Runtime.Exception ex)

      {

        ed.WriteMessage(ex.Message);

      }

    }

  }

}

24 responses to “Using the pickfirst selection from an AutoCAD .NET application”

  1. Thanks for the information. Some times we are using Editor interactions from a PaletteSet control. But it's unable to focus Editor ( drawing window ) via .NET API. Is there any way to control this behavior.
    Thanks again.

    1. Old question but the answer to this was introduced in 2014 I believe.
      Autodesk.AutoCAD.ApplicationServices.Application...
      ...DocumentManager.MdiActiveDocument.Window.Focus()

  2. It's hard to tell exactly what you mean by "focus" (it might be understood in the Windows sense of taking the active application focus, or something related to zooming inside the AutoCAD editor).

    I'd suggest submitting your question to my team through the ADN website, or posting it to the .NET Discussion Group.

  3. Hi Erhan,

    I wouldn't be using the Editor methods from a palette (or any other modeless UI) if I were you. When the modeless UI needs to interact with the editor or database you should post a command (using Document.SendStringToExecute) and do the editor or database interaction inside the command.

  4. Hi Kean,

    The code above could be simplified by using Editor.GetSelection(). GetSelection will do everything you want:
    1. Get the implied selection if available and clear it.
    2. Prompt the user with "Select objects:" if an implied set isn't available.

    You would only want to do what is shown above if you want to customize the prompt issued.

    1. Brilliant m8 brilliant

  5. Cool - thanks for that tip, Albert.

    Kean

  6. Jimmy Bergmark Avatar
    Jimmy Bergmark

    What should be used instead of ed.SetImpliedSelection(new ObjectId[0]); as it does not work in AutoCAD 2010?

  7. Jimmy Bergmark Avatar
    Jimmy Bergmark

    To answer my own question it seems like I don't need to clear the pickfirst set at all.

  8. Kean Walmsley Avatar

    Interesting - thanks, Jimmy.

    Kean

  9. hi,Kean
    i tested you code,but when i run the .dll file under autocad2006,error happened:could not find the mothod"Void Autodesk.AutoCAD.EditorInput.Editor.SetImpliedSelection(Autodesk.AutoCAD.DatabaseServices.ObjectId[])”
    could you tell me why?

  10. It's very possible that this method was introduced in AutoCAD 2007.

    Kean

  11. Hi Kean,,

    How I can get selection set :
    from "0" layer and object type text only.

    I tried:
    TypedValue[] acTypValAr = new TypedValue[2];
    acTypValAr.SetValue(new TypedValue((int)DxfCode.LayerName, "0"), 0);
    acTypValAr.SetValue(new TypedValue((int)DxfCode.Start, "TEXT"), 1);
    SelectionFilter acSelFtr = new SelectionFilter(acTypValAr);

    PromptSelectionResult acSSPrompt;

    acSSPrompt = ed.GetSelection(acSelFtr);

    Here the problem is, its asking for user to select. I do not want user to select. I want complete selection set from "0" layer and object type text only without user interaction. How I can do it?

  12. sorry its solved..using SelectAll()

    acSSPrompt = ed.SelectAll(acSelFtr);

  13. Hey Kean - excellent information it's a godsend really

    there is something which is a little confusing in your program: the CommandMethod flags three flags, two of which are CommandFlags.Redraw and also ComandFlags.UsePickSet

    The .net developer's guide says the following about the CommandFlags:

    (a) UsePickSet - When the pickfirst set is retrieved, it is cleared.

    (b) Redraw - When the pickfirst set or grip set are retrieved, they are not cleared.

    the two commandflags seem to conflict with each other. One clears the pickset, whereas the other does not - yet both are invoked.

    am confused. any ideas?

    1. The ObjectARX reference says this:

      "If both ACRX_CMD_USEPICKSET and ACRX_CMD_REDRAW are set, the effect is the same as if only ACRX_CMD_REDRAW is set."

      So they're not exactly conflicting, but specifying UsePickSet is indeed redundant.

      Kean

  14. Hi Kean and readers,

    In this example, we use the UsePickSet commandflag - but doesn't the CommandFlags.Redraw do exactly the same thing as UsePickSet?

    1. Kean Walmsley Avatar

      Yes, that's what I said in the comment just above: disq.us/8nfc69

      Kean

      1. Oh God. this is embarrasing. I forgot entirely. thx

  15. Pedro Liberato Avatar
    Pedro Liberato

    Thanks for the information, but I have a doubt. I need to set a pre-selection and then continue with the selection using the function Editor.GetSelection.

    When I use Autodesk.AutoCAD.Internal.Utils.SelectObjects to pre-select some entities, Editor.GetSelection doesn't stop for the user. Do you have some idea what can I do? Thanks again!

    1. Pedro Liberato Avatar
      Pedro Liberato

      I found one solution.
      forums.autodesk.com/

      But now I have another problem, I need to use the selection with Keywords.

  16. This entire blog is amazing. Thanks mate.

  17. Thanks for this example code. I was able to use it for a BricsCAD tool.

  18. Thanks for your code. I was able to reuse with a BricsCAD tool I wrote.

Leave a Reply

Your email address will not be published. Required fields are marked *