TheSwamp
Code Red => .NET => Topic started by: Kerry on January 27, 2010, 03:03:52 AM
-
LIBRARY THREAD for AutoCAD LAYERS
Members are encouraged to post any functions, methods, snips regarding
AutoCAD LAYERS in .NET : C# , VB , F# , Python , etc
Feel free to include comments, descriptive notes, limitations, and images to document your post.
Please post questions in a regular thread.
-
I use this to find the layer picked for isolating, freezing, turning off.
It works better than the acad versions as you end up turning off the layer you see not the layer of the block.
public string GetSubEntityLayer(string Msg )
//1)Layer "0" and defpoints may be in a standard block
//2) in an x-ref or within a block within an x-ref
//layer "0" and defpoints in an x-ref dont get "|"
//3) blocks within an x-ref have the name x-ref.name | blockname
//4) owner doesnt have a layer property
{
Document doc=acadApp.DocumentManager.MdiActiveDocument;
Editor ed=doc.Editor;
PromptNestedEntityOptions pno=new PromptNestedEntityOptions ("\n" + Msg);
PromptNestedEntityResult pnr=ed.GetNestedEntity(pno);
if(pnr.Status!=PromptStatus.OK) return "";
ObjectId[] cons= pnr.GetContainers();
using (Transaction tr=doc.TransactionManager.StartTransaction())
{
Entity ent=tr.GetObject( pnr.ObjectId,OpenMode.ForRead) as Entity;
if(Msg =="Select objects")ent.Highlight ();
string sLayer = ent.Layer;
if(string.Compare(sLayer,"0",false)==0
|string.Compare(sLayer,"defpoints",false)==0)
{
if(cons.Length==0) return ent.Layer;
//ent is not nested, user wanted this layer
Entity owner=tr.GetObject(cons[0],OpenMode.ForRead) as Entity;
if(owner.GetType()==typeof(BlockReference))
{
if(owner.Layer!="0")
return owner.Layer;
else
{
for (int i = 0; i < cons.Length; i++)
{
owner=tr.GetObject(cons[i],OpenMode.ForRead)as Entity;
if(owner.GetType()==typeof(BlockReference))
{
sLayer = owner.Layer;
if( sLayer!= "0") break;
}
}
}
}
}
return sLayer;
}
} //end GetSubEntityLayer
-
A function to return Current Layer in VB:
' A function to return the current Layer, you can get properties as name and id from the returned object.
' Ex: hzGetCurrentLayer.Name
Shared Function hzGetCurrentLayer() As LayerTableRecord
' Get the current document and database
Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
Dim acCurDb As Database = acDoc.Database
Dim acLayer As LayerTableRecord
' Start a transaction
Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
acLayer = CType(acTrans.GetObject(acCurDb.Clayer, OpenMode.ForRead), LayerTableRecord)
' Close transaction
acTrans.Dispose()
End Using
Return acLayer
End Function
-
getting the Current Layer from System Variables < similar to lisp statement (getvar "CLAYER") >
string m_layer = (string)Application.GetSystemVariable("clayer");
This method is applicable to all Autocad System variables.
-
^ Great idea!
-
My edit layer by selection code is here.
[ http://www.theswamp.org/index.php?topic=25698.0 ]
-
Indeed and I'll keep this in mind, but with my code you get the layer object instead of just a string.
But it is refreshing to see a very simple method I didn't think of, and if I only need a string, I'll use your solution :-)
getting the Current Layer from System Variables < similar to lisp statement (getvar "CLAYER") >
string m_layer = (string)Application.GetSystemVariable("clayer");
This method is applicable to all Autocad System variables.
-
Standard layer functions C#
public static void setCurrentLayer(string sLayer)
{//Kerry Brown http://www.theswamp.org/index.php?topic=7766.msg98575#msg98575
if (sLayer == "") return;
Database db=HostApplicationServices.WorkingDatabase;
ObjectId layerId=ObjectId.Null;
using(Transaction tr=db.TransactionManager.StartTransaction())
{
LayerTable pLayerTable = (LayerTable)tr.GetObject
(db.LayerTableId, OpenMode.ForRead);
if (pLayerTable.Has(sLayer))
{
layerId = pLayerTable[sLayer];
if (layerId.IsErased)
{
LayerTableRecord pExLtr = (LayerTableRecord)tr.GetObject
(layerId, OpenMode.ForWrite, true);
pExLtr.Erase(false);
}
}
else // create it...
{
LayerTableRecord pNewLTR = new LayerTableRecord();
pNewLTR.Name = sLayer;
pLayerTable.UpgradeOpen();
layerId = pLayerTable.Add(pNewLTR);
tr.AddNewlyCreatedDBObject(pNewLTR, true);
}
db.Clayer = layerId;
db.Cecolor = Color.FromColorIndex(ColorMethod.ByLayer, 256);//Added
db.Celtype = db.ByLayerLinetype; //Added
}
}
public static void setCurrentLayer(ObjectId layerId)
{
if (layerId == ObjectId.Null) return;
Database db = HostApplicationServices.WorkingDatabase;
db.Clayer = layerId;
db.Cecolor = Color.FromColorIndex(ColorMethod.ByLayer, 256);
db.Celtype = db.ByLayerLinetype;
}
[CommandMethod("SetObjLayerCurrent")]
public void SetObjLayerCurrent()
{
string sLayer = GetSubEntityLayer("Pick an object on the layer you want to make current:");
if( sLayer.Contains("|"))
{
MessageBox.Show("You can not make the x-ref layer " + sLayer +" current");
return;
}
setCurrentLayer(sLayer);
Print (sLayer + " is now the current layer. ");
}
[CommandMethod("IsolateLayer")]
public void IsolateLayer()
{
Print("Select object(s) on the layer(s) to be isolated:");
string Msg = "Select objects", sLayer;
StringCollection layerset = new StringCollection();
do
{
sLayer = GetSubEntityLayer(Msg);
if (sLayer != "")
layerset.Add(sLayer);
} while (sLayer != "");
for (int i = 0; i < layerset.Count; i++)
{
if (!layerset[i].Contains("|"))
{
setCurrentLayer(layerset[i]);
break;
}
}
Database db = HostApplicationServices.WorkingDatabase;
LayerTableRecord layer;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
foreach (ObjectId layerId in lt)
{
layer = tr.GetObject
(layerId, OpenMode.ForWrite) as LayerTableRecord;
layer.IsOff = true;
}
for (int i = 0; i < layerset.Count; i++)
{
sLayer = layerset[i];
layer = tr.GetObject
(lt[sLayer], OpenMode.ForWrite) as LayerTableRecord;
layer.IsOff = false;
if (i == 0) Msg = sLayer;
else Msg = Msg + " and " + sLayer;
}
tr.Commit();
acadApp.DocumentManager.MdiActiveDocument.Editor.Regen();
Print("The isolated layer names are " + Msg);
}
}
[CommandMethod("Layerson")]
public void Layerson()
{
Database db = HostApplicationServices.WorkingDatabase;
LayerTableRecord layer;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
foreach (ObjectId layerId in lt)
{
layer = tr.GetObject
(layerId, OpenMode.ForWrite) as LayerTableRecord;
layer.IsOff = false;
}
tr.Commit();
}
}
[CommandMethod("Layeroff")]
public void LayerOff()
{
Database db=HostApplicationServices.WorkingDatabase;
string msg, sLayer;
do
{
sLayer = GetSubEntityLayer("Pick an object on the layer you want to turn off:");
if (sLayer == "") return;
if(sLayer ==(string) acadApp.GetSystemVariable("CLayer"))
{
msg="\nDo you really want to turn the current layer off?";
MessageBox.Show(msg,"Layer off",MessageBoxButtons.YesNo);
}
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
LayerTableRecord ltr = tr.GetObject
(lt[sLayer], OpenMode.ForWrite) as LayerTableRecord;
ltr.IsOff = true;
Print(sLayer + " is turned off. ");
tr.Commit();
}
} while (sLayer != "");
}
[CommandMethod("Layerfreeze")]
public void Layerfreeze()
{
Database db = HostApplicationServices.WorkingDatabase;
string msg, sLayer, curLayer = (string)acadApp.GetSystemVariable("CLayer");
do
{
sLayer = GetSubEntityLayer("Pick an object on the layer you want to freeze:");
if (sLayer == "") return;
if (sLayer ==curLayer)
{
msg = "\nDo can not freeze the current layer?";
MessageBox.Show(msg, "Freeze");
}
else
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
LayerTableRecord ltr = tr.GetObject
(lt[sLayer], OpenMode.ForWrite) as LayerTableRecord;
ltr.IsFrozen = true;
Print(sLayer + " is frozen. ");
tr.Commit();
}
}
} while (sLayer != "");
}
[CommandMethod("Thaw")]
public void ThawAll()
{
Database db = HostApplicationServices.WorkingDatabase;
LayerTableRecord layer;
string curLayer = (string)acadApp.GetSystemVariable("CLayer");
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
foreach (ObjectId layerId in lt)
{
layer = tr.GetObject
(layerId, OpenMode.ForWrite) as LayerTableRecord;
if(layer.Name!=curLayer)
layer.IsFrozen = false;
}
tr.Commit();
acadApp.DocumentManager.MdiActiveDocument.Editor.Regen();
}
}
static public void Print(string sMsg)
{
Document Doc = acadApp.DocumentManager.MdiActiveDocument;
Editor ed = Doc.Editor;
ed.WriteMessage("\n" + sMsg );
}
-
Save each layers in separate files
~'J'~
-
Save each layers in separate files
Hi Oleg, that's very nice!
My question: whence the necessity to open (and lock) all those documents if one is able to write directly to a new Database? I do see that the easy way has its problems, my test run wasn't entirely successful because the new drawings aren't in metric but imperial units.
F# alarm! Confer:
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.EditorInput
open Autodesk.AutoCAD.Runtime
type acApp = Autodesk.AutoCAD.ApplicationServices.Application
let selectOnLayer lrname =
let res =
new SelectionFilter[| new TypedValue(int DxfCode.LayerName, lrname) |]
|> acApp.DocumentManager.MdiActiveDocument.Editor.SelectAll
if res.Status <> PromptStatus.OK then null
else new ObjectIdCollection(res.Value.GetObjectIds())
[<CommandMethod "WBL">]
let copyObjectsOnLayers() =
// Get the current document and database
let doc = acApp.DocumentManager.MdiActiveDocument
let ed = doc.Editor
let db = doc.Database
// Get the current document's path and name without extension
let currRoot = acApp.GetSystemVariable "DWGPREFIX" :?> string
let currName = acApp.GetSystemVariable "DWGNAME" :?> string
let currName = System.IO.Path.GetFileNameWithoutExtension currName
let lrcoll = new System.Collections.Generic.List<string>()
// Start a transaction
use tr = db.TransactionManager.StartTransaction()
let lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) :?> LayerTable
for lrid in lt do
let ltr = tr.GetObject(lrid, OpenMode.ForRead, false) :?> LayerTableRecord
if not ltr.IsLocked && not(ltr.Name.Contains "|") then
lrcoll.Add ltr.Name |> ignore
for lrname in lrcoll do
let objcoll = selectOnLayer lrname
if objcoll <> null then
let strFilename =
System.IO.Path.Combine(
currRoot, currName + @"_" + lrname + @".dwg" ) //<-- build filename as you need here
ed.WriteMessage("\n" + strFilename)
// Create a new database to copy the objects to
use newdb = new Database(true, true)
use newtr = newdb.TransactionManager.StartTransaction()
// Open the Block table record Model space for read
let newbtr =
newtr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId newdb, OpenMode.ForRead) :?> BlockTableRecord
// Clone the objects to the new database
let idmap = new IdMapping()
db.WblockCloneObjects(objcoll, newbtr.ObjectId, idmap, DuplicateRecordCloning.Ignore, false)
newdb.SaveAs(strFilename, DwgVersion.Current)
newtr.Commit()
tr.Commit()
Have fun, Thorsten
-
Thanks, Thorsten!
I will check it on my machine
Not sure about that it is needs to LockDocument (old one)
as well as the new documents, I think you're right if
your code is working good without it
But it's my thoughts...
Probably, better yet to create a new topic with question about LockDocument,
because in ObjectARX docs is poor explanation about this thing?
Keep firing :)
Regards,
Oleg
-
because in ObjectARX docs is poor explanation about this thing?
Keep firing :)
Regards,
Oleg
Have looked in the arxdoc.chm?
I use to use the arxmgd.chm but arxdoc.chm is alot better.
If you have not looked open the arxdoc.chm and on the index tab type in "locking" and double that and read all entries that come up. It gives a pretty good explanation.
This is what the developers guide says
•Interacts with AutoCAD from a modeless dialog box
•Accesses a loaded document other than the current document
•Used as a COM server
•Registers a command with the Session command flag
-
Hi,
Can any one provide me a sample code to copy all objects from layer1 to layer 2, also i want to union all object in layer 2.
Thanks & Regards