Code Red > .NET
Select on layer .. ensure thawed layer
(1/1)
kdub_nz:
Anyone care to break this.
Select objects on a specific layer. Ensure the layer is Thawed.
Sample Drawing attached.
Comments welcome.
added: EDIT Code style changes as per Gilles comments.
--- Code - C#: ---// (C) Codehimbelonga kdub 2019-07-14 //using System;using Autodesk.AutoCAD.ApplicationServices;using Autodesk.AutoCAD.DatabaseServices;using Autodesk.AutoCAD.EditorInput;using Autodesk.AutoCAD.Geometry;using Autodesk.AutoCAD.Runtime;using cadApp = Autodesk.AutoCAD.ApplicationServices.Application; [assembly: CommandClass(typeof(Test190714.MyCommands))] namespace Test190714{ public class MyCommands { [CommandMethod("Doit", CommandFlags.Modal)] public void MyCommand() { var layerName = "Cabling"; var isLayerThawed = FreezeLayer(layerName, freeze: false); SelectionSet selectedLines; if (isLayerThawed) { selectedLines = GrabLines(layerName); } else { Active.WriteMessage($"Layer '{layerName}' is not accessable"); return; } if (selectedLines != null && selectedLines.Count > 0) { OutputLineData(selectedLines); } else { Active.WriteMessage("Nothing to report"); } } /// <summary>Freezes the layer.</summary> /// <param name="layerName">Name of the layer.</param> /// <param name="freeze">if set to <c>true</c> [freeze].</param> /// <returns></returns> private bool FreezeLayer(string layerName, bool freeze) { using (var tr = Active.Database.TransactionManager.StartTransaction()) { var layerTable = (LayerTable)tr.GetObject(Active.Database.LayerTableId, OpenMode.ForRead); if (!layerTable.Has(layerName)) { // No Layer, So can't be frozen or thawed return false; } var layerRecord = (LayerTableRecord)tr.GetObject(layerTable[layerName], OpenMode.ForWrite); if (layerRecord.Id != Active.Database.Clayer) { layerRecord.IsFrozen = freeze; } tr.Commit(); Active.Editor.Regen(); } return true; } /// <summary>Grabs the lines.</summary> /// <param name="layerName">Name of the layer.</param> /// <returns></returns> public SelectionSet GrabLines(string layerName) { TypedValue[] filterValues = new[] { new TypedValue((int)DxfCode.Start, "LINE"), new TypedValue((int)DxfCode.LayerName, layerName) }; var selectionFilter = new SelectionFilter(filterValues); var selectionOptions = new PromptSelectionOptions { MessageForAdding = $"Select Lines on Layer {layerName}", AllowDuplicates = true }; var selectionResult = Active.Editor.GetSelection(selectionOptions, selectionFilter); if (!(selectionResult.Status == PromptStatus.OK)) { return null; } return selectionResult.Value; } /// <summary>Outputs the line data.</summary> /// <param name="ss">The ss.</param> private void OutputLineData(SelectionSet ss) { ObjectId[] idarray = ss.GetObjectIds(); using (Transaction tr = Active.Database.TransactionManager.StartTransaction()) { foreach (var id in idarray) { var line = (Line)tr.GetObject(id, OpenMode.ForRead, true); Active.WriteMessage( $"\nYou selected: {line.GetType().Name} with Length = {line.Length }"); } } } } /// <summary> /// Provides easy access to several "active" objects in the /// AutoCAD runtime environment. /// Thanks to : Scott McFarlane - Programming AutoCAD with C#: Best Practices /// </summary> public static class Active { public static Document Document => cadApp.DocumentManager.MdiActiveDocument; public static Database Database => Document.Database; public static Editor Editor => Document.Editor; public static void WriteMessage( string message) => Editor.WriteMessage(message); public static void WriteMessage( string message, params object[] parameter) => Editor.WriteMessage(message, parameter); }}
gile:
Hi,
Nice code Kerry.
Just 2 things about coding style:
--- Code - C#: ---if (layerTable.Has(layerName) == false)reminds me of the verbose VB style.
You'd never write:
--- Code - C#: ---if (layerTable.Has(layerName) == true) so why not simply write:
--- Code - C#: ---if (!layerTable.Has(layerName))
--- Code - C#: --- using (Transaction tr = Active.Database.TransactionManager.StartTransaction()) { try { foreach (var id in idarray) { var line = (Line)tr.GetObject(id, OpenMode.ForRead, true); Active.WriteMessage( $"\nYou selected: {line.GetType().Name} with Length = {line.Length }"); } } finally { tr.Dispose(); } } It seems to me the finally block is useless.
The using statement will take care of disposing of the transaction even if an exception occured. So, as you neither have a catch block, the try{...} also is useless.
kdub_nz:
Yes, you are correct :)
Thanks for the scan Gilles
Edit: Code revised as commented.
kdub_nz:
@gile
I liked your option of using an OpenCloseTransaction with this :
--- Code - C#: --- var layer = (LayerTableRecord)tr.GetObject(layerTable["Cabling"], OpenMode.ForRead); if (layer.IsFrozen) { layer.UpgradeOpen(); layer.IsFrozen = false; }
Very clean !
gile:
Thanks Kerry.
Clean, this is the way I try to write.
Navigation
[0] Message Index
Go to full version