// Variation on how to select all instances of a Dynameic block, originally by Kean Walmsley
// http://through-the-interface.typepad.com/through_the_interface/2012/09/creating-a-selection-filter-that-finds-dynamic-blocks-in-autocad-using-net.html
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using System.Collections.Generic;
namespace EntitySelection
{
public class Commands
{
[CommandMethod("SDB")]
static public void SelectDynamicBlocks()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var ed = doc.Editor;
var pso =
"\nName of dynamic block to search for"
);
pso.AllowSpaces = true;
var pr = ed.GetString(pso);
if (pr.Status != PromptStatus.OK)
return;
string blkName = pr.StringResult;
List
<string> blkNames
= new List
<string>(); blkNames.Add(blkName);
PromptSelectionResult psr;
using (var tr = doc.TransactionManager.StartTransaction())
{
var bt =
(BlockTable)tr.GetObject(
doc.Database.BlockTableId,
OpenMode.ForRead
);
// Start by getting access to our block, if it exists
if (!bt.Has(blkName))
{
ed.WriteMessage(
"\nCannot find block called \"{0}\".", blkName
);
return;
}
// Skip the test for IsDynamicBlock, since this will work
// for standard blocks regardless
// Define an event handler in the current scope
SelectionAddedEventHandler handler =
delegate(object sender, SelectionAddedEventArgs e)
{
foreach (int i in e.AddedObjects.GetIndicesToRemove(bt[blkName]))
e.Remove(i);
};
// Select anonymous "`**" and regular "*" block references
SelectionFilter sf =
new SelectionFilter
(new TypedValue
[] { (int)DxfCode.BlockName, "`**,*")});
ed.SelectionAdded += handler;
try
{
psr = ed.SelectAll(sf);
}
finally
{
ed.SelectionAdded -= handler;
}
tr.Commit();
}
if (psr == null || psr.Value == null)
{
ed.WriteMessage("\nNo entities found. ");
return;
}
ed.WriteMessage(
"\nFound {0} entit{1}.",
psr.Value.Count,
(psr.Value.Count == 1 ? "y" : "ies")
);
}
}
static class IEnumerable
{
// Extension to SelectionSet which opens all block references that pass
// the SelectionFilter. Returns a sequence of integer indices corresponding
// to the block's position in the SelectionSet, which will remove them from it.
// Don't return any index for a block refences whose DynamicBlockTableRecord
// property isn't equal to the ObjectId of our wanted block's prototype definition
public static IEnumerable<int> GetIndicesToRemove(this SelectionSet added, ObjectId btrOid)
{
int i = 0;
foreach (SelectedObject so in added)
{
var br =
(BlockReference)so.ObjectId.GetObject(OpenMode.ForRead);
if (br.DynamicBlockTableRecord != btrOid)
yield return i;
i++;
}
}
}
}