hi all. my code :
Dim editor As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim db As Database = HostApplicationServices.WorkingDatabase
Dim tr As Transaction = db.TransactionManager.StartTransaction()
Try
Dim values(0) As TypedValue
values(0) = New TypedValue(DxfCode.Start, "INSERT")
Dim selFilter As New SelectionFilter(values)
Dim prompSelRes As PromptSelectionResult = editor.SelectAll(selFilter)
If prompSelRes.Status = PromptStatus.OK Then
Dim objSelectSet As SelectionSet = prompSelRes.Value
......
the only prob is : I want selec all block but not the block on layer frozen, off or not visible...
How i can do that ?
I can check all layer stat on each block.. (i do that already for check each block (name) but i want a solution more easy.)
thanks
Try this filter
Dim curlay As String = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("clayer").ToString() Dim values(3) As TypedValue values(0) = New TypedValue(DxfCode.Operator, "<and") values(1) = New TypedValue(DxfCode.Start, "insert") values(2) = New TypedValue(DxfCode.LayerName, curlay) values(3) = New TypedValue(DxfCode.Operator, "and>") Dim selFilter As New SelectionFilter(values) Dim prompSelRes As PromptSelectionResult = ed.SelectAll(selFilter) If prompSelRes.Status <> PromptStatus.OK Then Return Dim objSelectSet As SelectionSet = prompSelRes.Value ed.WriteMessage(vbLf + "{0}", objSelectSet.Count)
~'J'~
Hi,
If you really want to use a selection set, you can handle the Editor.SelectionAdded event to filter the blocks:
public PromptSelectionResult SelectAllVisible(TypedValue[] filter) { Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor; PromptSelectionResult psr = null; try { ed.SelectionAdded += new SelectionAddedEventHandler(onSelectionAdded); psr = ed.SelectAll(new SelectionFilter(filter)); } finally { ed.SelectionAdded -= new SelectionAddedEventHandler(onSelectionAdded); } return psr; } void onSelectionAdded(object sender, SelectionAddedEventArgs e) { Database db = HostApplicationServices.WorkingDatabase; using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable lt = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead); List<string> layers = new List<string>(); foreach (ObjectId ltrId in lt) { LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(ltrId, OpenMode.ForRead); if (ltr.IsFrozen || ltr.IsHidden || ltr.IsOff) layers.Add(ltr.Name); } List<int> toRemove = new List<int>(); SelectionSet ss = e.AddedObjects; for (int i = 0; i < ss.Count; i++) { BlockReference br = (BlockReference)ss[i].ObjectId.GetObject(OpenMode.ForRead); if (layers.Contains(br.Layer)) toRemove.Add(i); } foreach (int i in toRemove) e.Remove(i); tr.Commit(); } }
Using example:
TypedValue[] filter = new TypedValue[] { new TypedValue(0, "INSERT") }; PromptSelectionResult psr = SelectAllVisible(filter);
Anyway, the EditorSelectAll does iterate all the layouts. IMO it's more simple to do it by yourself.
Here's an example using Linq which must be launch from within a transaction and returns an IEnumerable<BlockReference> (lazy sequence):
public IEnumerable<BlockReference> GetAllVisibleBlocks(Database db) { LayerTable lt = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead); List<string> layers = lt .Cast<ObjectId>() .Select(id => (LayerTableRecord)id.GetObject(OpenMode.ForRead)) .Where(ltr => ltr.IsFrozen || ltr.IsHidden || ltr.IsOff) .Select(ltr => ltr.Name) .ToList(); BlockTable bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead); return bt.Cast<ObjectId>() .Select(id => (BlockTableRecord)id.GetObject(OpenMode.ForRead)) .Where(btr => btr.IsLayout) .SelectMany(btr => btr.Cast<ObjectId>()) .Where(id => id.ObjectClass.DxfName == "INSERT") .Select(id => (BlockReference)id.GetObject(OpenMode.ForRead)) .Where(br => !layers.Contains(br.Layer)); }
I don't like VB
There're free code converters:
Using SelectionAdded event handler
Public Function SelectAllVisible(filter As TypedValue()) As PromptSelectionResult Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor Dim psr As PromptSelectionResult = Nothing Try AddHandler ed.SelectionAdded, AddressOf Me.onSelectionAdded psr = ed.SelectAll(New SelectionFilter(filter)) Finally RemoveHandler ed.SelectionAdded, AddressOf Me.onSelectionAdded End Try Return psr End Function Private Sub onSelectionAdded(sender As Object, e As SelectionAddedEventArgs) Dim db As Database = HostApplicationServices.WorkingDatabase Using tr As Transaction = db.TransactionManager.StartTransaction() Dim lt As LayerTable = DirectCast(db.LayerTableId.GetObject(OpenMode.ForRead), LayerTable) Dim layers As New List(Of String)() For Each ltrId As ObjectId In lt Dim ltr As LayerTableRecord = DirectCast(tr.GetObject(ltrId, OpenMode.ForRead), LayerTableRecord) If ltr.IsFrozen OrElse ltr.IsHidden OrElse ltr.IsOff Then layers.Add(ltr.Name) End If Next Dim toRemove As New List(Of Integer)() Dim ss As SelectionSet = e.AddedObjects For i As Integer = 0 To ss.Count - 1 Dim br As BlockReference = DirectCast(ss(i).ObjectId.GetObject(OpenMode.ForRead), BlockReference) If layers.Contains(br.Layer) Then toRemove.Add(i) End If Next For Each i As Integer In toRemove e.Remove(i) Next tr.Commit() End Using End Sub
Using example:
Dim filter As TypedValue() = New TypedValue() {New TypedValue(0, "INSERT")} Dim psr As PromptSelectionResult = SelectAllVisible(filter)
Using Linq extension methods (must be launched from within a transaction).
Public Function GetAllVisibleBlocks(db As Database) As IEnumerable(Of BlockReference) Dim lt As LayerTable = DirectCast(db.LayerTableId.GetObject(OpenMode.ForRead), LayerTable) Dim layers As List(Of String) = lt.Cast(Of ObjectId)() _ .Select(Function(id) DirectCast(id.GetObject(OpenMode.ForRead), LayerTableRecord)) _ .Where(Function(ltr) ltr.IsFrozen OrElse ltr.IsHidden OrElse ltr.IsOff) _ .Select(Function(ltr) ltr.Name).ToList() Dim bt As BlockTable = DirectCast(db.BlockTableId.GetObject(OpenMode.ForRead), BlockTable) Return bt.Cast(Of ObjectId) _ .Select(Function(id) DirectCast(id.GetObject(OpenMode.ForRead), BlockTableRecord)) _ .Where(Function(btr) btr.IsLayout) _ .SelectMany(Function(btr) btr.Cast(Of ObjectId)) _ .Where(Function(id) id.ObjectClass.DxfName = "INSERT") _ .Select(Function(id) DirectCast(id.GetObject(OpenMode.ForRead), BlockReference)) _ .Where(Function(br) Not layers.Contains(br.Layer)) End Function
[CommandMethod("t1")] public static void Test1() { var doc = Application.DocumentManager.MdiActiveDocument; var db = doc.Database; var ed = doc.Editor; using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable lt = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead); List<string> layers = new List<string>(); foreach (ObjectId ltrId in lt) { LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(ltrId, OpenMode.ForRead); if (ltr.IsFrozen || ltr.IsHidden || ltr.IsOff) layers.Add(ltr.Name); } SelectionFilter sf = new SelectionFilter ( new TypedValue[] { new TypedValue(0, "insert"), new TypedValue(8, string.Join(",", layers.ToArray())) } ); //ResultList rl = // new ResultList // { // {0, "insert"}, // {8, string.Join(",", layers.ToArray())} // }; var res = ed.SelectAll(sf); } }
test this code