In the last post, we looked at how to stop entities from being highlighted during selection. This post looks at how to stop entities from being selected at all. Thanks again to Balaji Ramamoorthy for providing the underlying technique shown in today’s code.
The basic scenario we’re using is similar to the last post – we maintain a list of DXF names for the classes we want to stop from being selected – but it could easily be adapted to using different criteria for removing objects from the selection: an example being the use of a similar (although admittedly not identical, as we respond to a different event) technique in the OffsetInXref Plugin of the Month to remove a selected xref from the current selection and replace it with a cloned copy of the nested object.
If we were using single entity selection (GetEntity() rather than GetSelection()) then we’d probably use a different approach when filtering at a class level: we’d probably go with PromptEntityOptions.AddAllowedClass() to enable specific classes. But we could also use this technique with entity picking, in case, especially if we used other criteria for disallowing selection (i.e. not based on the object’s type) or wanted to disallow certain types rather than allowing others.
Here’s the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System.Collections.Generic;
using System.Text;
namespace PreventSelection
{
public class Test : IExtensionApplication
{
void OnSelectionAdded(object sender, SelectionAddedEventArgs e)
{
ObjectId[] addedIds = e.AddedObjects.GetObjectIds();
for (int i=0; i < addedIds.Length; i++)
{
ObjectId oid = addedIds[i];
if (IsInList(oid.ObjectClass.DxfName))
{
e.Remove(i);
}
}
}
[CommandMethod("US")]
public static void Unselect()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
// Print the list of currently unhighlighted classes
ed.WriteMessage(ListToPrint());
// Get the type to add to the list
PromptResult pr =
ed.GetString(
"\nEnter the type of object to stop from " +
"being selected: "
);
if (pr.Status != PromptStatus.OK)
return;
if (IsInList(pr.StringResult))
{
ed.WriteMessage("\nItem already in the list.");
}
else
{
AddToList(pr.StringResult);
ed.WriteMessage("\nItem added to the list.");
}
}
// Would call this command RS, but it's taken by RSCRIPT,
// so using the somewhat unwieldy UUS, instead
[CommandMethod("UUS")]
public static void Ununselect()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
// Print the list of currently unhighlighted classes
ed.WriteMessage(ListToPrint());
// Get the type to remove from the list
PromptResult pr =
ed.GetString(
"\nEnter the type of object to remove from the " +
"list: "
);
if (pr.Status != PromptStatus.OK)
return;
if (!IsInList(pr.StringResult))
{
ed.WriteMessage("\nItem not currently in the list.");
}
else
{
RemoveFromList(pr.StringResult);
ed.WriteMessage("\nItem removed from the list.");
}
}
void IExtensionApplication.Initialize()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
ed.SelectionAdded +=
new SelectionAddedEventHandler(OnSelectionAdded);
}
void IExtensionApplication.Terminate()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
ed.SelectionAdded -=
new SelectionAddedEventHandler(OnSelectionAdded);
}
// The list of types to unhighlight
static List<string> _unhighlighted = new List<string>();
// Add a type to the list
public static void AddToList(string name)
{
string upper = name.ToUpper();
if (!_unhighlighted.Contains(upper))
{
_unhighlighted.Add(upper);
}
}
// Remove a type from the list
public static void RemoveFromList(string name)
{
string upper = name.ToUpper();
if (_unhighlighted.Contains(upper))
{
_unhighlighted.Remove(upper);
}
}
// Check whether the list contains a type
public static bool IsInList(string name)
{
return _unhighlighted.Contains(name.ToUpper());
}
// Get a string printing the contents of the list
public static string ListToPrint()
{
string toPrint;
if (_unhighlighted.Count == 0)
{
toPrint =
"\nThere are currently no objects in the list " +
"to stop from being selected.";
}
else
{
StringBuilder sb =
new StringBuilder(
"\nObjects of these types will not be selected:"
);
foreach (string name in _unhighlighted)
{
sb.Append(" " + name);
}
toPrint = sb.ToString();
}
return toPrint;
}
}
}
Once again, we’ll take a look at the code running on some basic geometry:
And we can see it’s all very selectable:
Then we can use our US command to force circles and lines from not being selected:
Command: US
There are currently no objects in the list to stop from being selected.
Enter the type of object to stop from being selected: circle
Item added to the list.
Command: US
Objects of these types will not be selected: CIRCLE
Enter the type of object to stop from being selected: line
Item added to the list.
Which we can see means our arcs are the only objects selected when we window-select everything: