Anyway, even if ObjectId.GetObject() is (a little) less efficient than Transaction.GetOject() (which is less efficient than OpenCloseTransaction.GetObject() or ObjectId.Open()), the goal here was more to get a succint and readable code.
since your knowledge of the API is better than mine.I'm thinking the same about you.
Extension methods are used to add methods to a predefined type (see this page (https://msdn.microsoft.com/en-us/library/bb383977.aspx)).Sorry i'm such a dummy on this but if i understand you correctly i need to add all my layers into this code like layer1,layer2,layer3,etc. Also i am not sure how to implement this. Do i compile this into a dll file? This is my template file. i want all of these layers to be unpurgeable. Do i need to run this code in side of this file?
If you add the upper "Extensions" class to your project, those method will be available for the extended type (for your purpose, the SetUnpurgeable() method extents the SymbolTableRecord abstract type which LayerTableRecord derived from).
So, in you code, open each LayerTableRecord instance you want to set unpurgeable and call the SetUnpurgeable method on it.
frustrate the bugger....place a single autocad point on those layers...then he can't purge them...pdmode=1This is what sovby did in the attached file. Anyone can set PDMODE to 3 (or whatever else to display the points), erase the points (within a block reference here) and purge all.
might it not be easier to tell people to STOP purging layers?Yeah it would be but in my case i don't think it would work. My solution was to create a block with points on every layer which i made small & put it in the bottom left corner but they found it & deleted the block. I guess i didn't hide it well enough.
and or
frustrate the bugger....place a single autocad point on those layers...then he can't purge them...pdmode=1
they wont even be able to see them.... :whistling:
sovby,I really apologize for asking this but i feel like i might need step by step directions for this. I have visual studio so would i use that to copy this code into or just notepad? What kind of file would i save it to? How do i get it to talk with Autocad? Again, i am very sorry but i have never done any thing like this before with Autocad. I have gotten a little bit more familiar with c# language but i am lost as to what the procedure would be to make this happen. Does this look at the file that i posted to get the layers or do i have to add them all in manually into this code? If so where exactly do i need to do this? You said to add the class to the projects that use it but i dont know what you mean. How do i do this?
Yes, you can compile the extension class in a dll, this is a good way to build a re-usable library, but in this case it will be a very small library...
You can also, as I said, just add this class to the project which use it, even in a separate file or in the same file as the command method which use it as shown in the following example.Code - C#: [Select]
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; using System.Linq; using AcAp = Autodesk.AutoCAD.ApplicationServices.Application; namespace SetAllLayersUnpurgeable { public class Commands { [CommandMethod("Cmd")] public void SetAllLayersUnpurgeableCmd() { var db = HostApplicationServices.WorkingDatabase; using (var tr = db.TransactionManager.StartTransaction()) { var layerTable = db.LayerTableId.GetObject<LayerTable>(); foreach (ObjectId layerId in layerTable) { if (layerId != db.LayerZero) { layerId.GetObject<LayerTableRecord>().SetUnpurgeable(); } } tr.Commit(); } } } public static class Extensions { // Opens the object for read. public static T GetObject<T>(this ObjectId id) where T : DBObject { return (T)id.GetObject(OpenMode.ForRead, false, false); } // Opens the object in the specified mode public static T GetObject<T>(this ObjectId id, OpenMode mode) where T : DBObject { return (T)id.GetObject(mode, false, false); } // Gets the object extension dictionary (returns null if not found) public static DBDictionary GetExtensionDictionary(this DBObject obj) { ObjectId dictId = obj.ExtensionDictionary; if (dictId == ObjectId.Null) { return null; } return dictId.GetObject<DBDictionary>(); } // Gets the object extension dictionary (creates it if not already exists) public static DBDictionary GetOrCreateExtensionDictionary(this DBObject obj) { if (obj.ExtensionDictionary == ObjectId.Null) { obj.UpgradeOpen(); obj.CreateExtensionDictionary(); } return obj.ExtensionDictionary.GetObject<DBDictionary>(); } // Gets the xrecord data public static ResultBuffer GetXrecordData(this DBDictionary dict, string key) { if (!dict.Contains(key)) return null; ObjectId id = (ObjectId)dict[key]; return id.GetObject<Xrecord>().Data; } // Sets the xrecord data public static void SetXrecordData(this DBDictionary dict, string key, ResultBuffer data) { Xrecord xrec; if (dict.Contains(key)) { xrec = ((ObjectId)dict[key]).GetObject<Xrecord>(OpenMode.ForWrite); } else { dict.UpgradeOpen(); dict.SetAt(key, xrec); dict.Database.TransactionManager.TopTransaction.AddNewlyCreatedDBObject(xrec, true); } xrec.Data = data; } // Sets the symbol table record unpurgeable by referencing it in its symbol table extension dictionary public static void SetUnpurgeable(this SymbolTableRecord str) { SymbolTable st = str.OwnerId.GetObject<SymbolTable>(); DBDictionary xdict = st.GetOrCreateExtensionDictionary(); xdict.SetXrecordData("GILE_UNPURGE", data); } // Resets the symbol table record purgeable by unreferencing it in its symbol table extension dictionary public static void ResetPurgeable(this SymbolTableRecord str) { SymbolTable st = str.OwnerId.GetObject<SymbolTable>(); DBDictionary xdict = st.GetExtensionDictionary(); if (xdict == null) return; ResultBuffer data = xdict.GetXrecordData("GILE_UNPURGE"); if (data == null) return; var values = data.AsArray() .Where(tv => tv.TypeCode != 340 || (ObjectId)tv.Value != st.ObjectId) .ToArray(); } } }
mjfarrell,Quotefrustrate the bugger....place a single autocad point on those layers...then he can't purge them...pdmode=1This is what sovby did in the attached file. Anyone can set PDMODE to 3 (or whatever else to display the points), erase the points (within a block reference here) and purge all.
i'm a total newbie when it comes to .net programming.
..In my defense..
Hi,Ok thanks, i have actually been looking at C# using Visual tutorial for a little while so i do understand some of it but i have a long way to go. The only reason i was looking for the wizard is because that's what the tutorial from autodesk DevTV said to do.
You can use VS 2015 to build AutoCAD .NET applications for any AutoCAD version supporting .NET (i.e. 2006 to 2017) but you probably can't get/use wizzards for all versions.
Personally, like many others, I recommend that you start by learning .NET (C #, OOP, Visual Studio, ...) without any relationship with AutoCAD. And only once the basics of .NET programming will be acquired, start learning the .NET API. At that time, you will see that you will not need (or want) to use wizzards and you should be able to start a new AutoCAD project from scratch and/or use your own project templates.
When begining with AutoCAD .NET, you should start with AutoCAD 201X .NET Training (http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=1911627) lab which shows how to start an AutoCAD project from scratch.Those are the tutorials i was watching from the Autodesk DEVTV youtube page. They tell you to install the wizards both the .NET wizard & the ObjectARX wizard. I don't speak french but i should be able to get started now although some of the videos are using an older version of visual Studio. Also i think the video was using visual basic versus the Lab word doc was using c#. Thanks for your help. I loaded your lisp routine & it worked perfectly. I wish i didnt have to even do this but not everyone pays attention to how things that they do effect other people
If you can read French (or use an online translator) you can try to build your own AutoCAD .NET project templates following "C# Tempate" tutorial on this page (http://gilecad.azurewebsites.net/tutorials.html).
sovby,I really apologize for asking this but i feel like i might need step by step directions for this. I have visual studio so would i use that to copy this code into or just notepad? What kind of file would i save it to? How do i get it to talk with Autocad? Again, i am very sorry but i have never done any thing like this before with Autocad. I have gotten a little bit more familiar with c# language but i am lost as to what the procedure would be to make this happen. Does this look at the file that i posted to get the layers or do i have to add them all in manually into this code? If so where exactly do i need to do this? You said to add the class to the projects that use it but i dont know what you mean. How do i do this?
Yes, you can compile the extension class in a dll, this is a good way to build a re-usable library, but in this case it will be a very small library...
You can also, as I said, just add this class to the project which use it, even in a separate file or in the same file as the command method which use it as shown in the following example.Code - C#: [Select]
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; using System.Linq; using AcAp = Autodesk.AutoCAD.ApplicationServices.Application; namespace SetAllLayersUnpurgeable { public class Commands { [CommandMethod("Cmd")] public void SetAllLayersUnpurgeableCmd() { var db = HostApplicationServices.WorkingDatabase; using (var tr = db.TransactionManager.StartTransaction()) { var layerTable = db.LayerTableId.GetObject<LayerTable>(); foreach (ObjectId layerId in layerTable) { if (layerId != db.LayerZero) { layerId.GetObject<LayerTableRecord>().SetUnpurgeable(); } } tr.Commit(); } } } public static class Extensions { // Opens the object for read. public static T GetObject<T>(this ObjectId id) where T : DBObject { return (T)id.GetObject(OpenMode.ForRead, false, false); } // Opens the object in the specified mode public static T GetObject<T>(this ObjectId id, OpenMode mode) where T : DBObject { return (T)id.GetObject(mode, false, false); } // Gets the object extension dictionary (returns null if not found) public static DBDictionary GetExtensionDictionary(this DBObject obj) { ObjectId dictId = obj.ExtensionDictionary; if (dictId == ObjectId.Null) { return null; } return dictId.GetObject<DBDictionary>(); } // Gets the object extension dictionary (creates it if not already exists) public static DBDictionary GetOrCreateExtensionDictionary(this DBObject obj) { if (obj.ExtensionDictionary == ObjectId.Null) { obj.UpgradeOpen(); obj.CreateExtensionDictionary(); } return obj.ExtensionDictionary.GetObject<DBDictionary>(); } // Gets the xrecord data public static ResultBuffer GetXrecordData(this DBDictionary dict, string key) { if (!dict.Contains(key)) return null; ObjectId id = (ObjectId)dict[key]; return id.GetObject<Xrecord>().Data; } // Sets the xrecord data public static void SetXrecordData(this DBDictionary dict, string key, ResultBuffer data) { Xrecord xrec; if (dict.Contains(key)) { xrec = ((ObjectId)dict[key]).GetObject<Xrecord>(OpenMode.ForWrite); } else { dict.UpgradeOpen(); dict.SetAt(key, xrec); dict.Database.TransactionManager.TopTransaction.AddNewlyCreatedDBObject(xrec, true); } xrec.Data = data; } // Sets the symbol table record unpurgeable by referencing it in its symbol table extension dictionary public static void SetUnpurgeable(this SymbolTableRecord str) { SymbolTable st = str.OwnerId.GetObject<SymbolTable>(); DBDictionary xdict = st.GetOrCreateExtensionDictionary(); xdict.SetXrecordData("GILE_UNPURGE", data); } // Resets the symbol table record purgeable by unreferencing it in its symbol table extension dictionary public static void ResetPurgeable(this SymbolTableRecord str) { SymbolTable st = str.OwnerId.GetObject<SymbolTable>(); DBDictionary xdict = st.GetExtensionDictionary(); if (xdict == null) return; ResultBuffer data = xdict.GetXrecordData("GILE_UNPURGE"); if (data == null) return; var values = data.AsArray() .Where(tv => tv.TypeCode != 340 || (ObjectId)tv.Value != st.ObjectId) .ToArray(); } } }
mjfarrell,Quotefrustrate the bugger....place a single autocad point on those layers...then he can't purge them...pdmode=1This is what sovby did in the attached file. Anyone can set PDMODE to 3 (or whatever else to display the points), erase the points (within a block reference here) and purge all.
@sovby
Assuming you know how to load and run AutoLISP code, here's a little LISP routine.Code - Auto/Visual Lisp: [Select]
;; gc:GetExtDict (gile) ;; Retourne le dictionnaire d'extension de l'entité (ou nil) ;; ;; Argument : ent (ENAME) ) ;; gc:GetOrCreateExtDict (gile) ;; Retourne le dictionnaire d'extension de l'entité ;; Le dictionnaire est créé s'il n'existe pas ;; ;; Argument : ent (ENAME) (cond '((0 . "DICTIONARY") (100 . "AcDbDictionary")) ) ) '(102 . "}") ) ) ) dict ) ) ) ;; gc:SetXrecData ;; Retourne le ENAME du xrecord auquel sont affectées mes données ;; ;; Arguments ;; dict : ENAME du dictionnaire parent ;; key : nom du Xrecord ;; data : liste de paires pointées contenant les données ) dict key '(100 . "AcDbXrecord") ) data ) ) ) ) ) ) ;;----------------------------------------------------;; ;; Commands ;; ;;----------------------------------------------------;; ;; SETALLLAYERSUNPURGEABLE command to set all layers unpurgeable ) ) (gc:SetXrecData "LAYER_UNPURGE" ptrs ) ) ;; RESETALLLAYERSPURGEABLE command to reset all layers purgeable (and ) )
(defun c:Unpurg (/ enm lst ptrs)
(setq lst '("1" "2" "3")) ; Laagnamen.
(foreach nme lst
(if (setq enm (tblobjname "LAYER" nme))
(setq ptrs (cons (cons 340 enm) ptrs))
)
)
(gc:SetXrecData
(gc:GetOrCreateExtDict (cdr (assoc 330 (entget (tblobjname "LAYER" "0")))))
"LAYER_UNPURGE"
ptrs
)
(princ)
)
(defun gc:GetOrCreateExtDict (ent / dict)
(cond
((cdadr (member '(102 . "{ACAD_XDICTIONARY") (entget ent))))
((setq dict (entmakex
'((0 . "DICTIONARY") (100 . "AcDbDictionary"))
)
)
(entmod (append (list '(102 . "{ACAD_XDICTIONARY")
(cons 360 dict)
'(102 . "}")
)
(entget ent)
)
)
dict
)
)
)