Hi,
Finally I’ve had chance to test our old routines in AutoCAD 2015 and have found one problem with getting current layout. To get current layout we use below code.
//identify viewport LayoutManager ltman = LayoutManager.Current; Layout activeLayout; activeLayout = (Layout)tr.GetObject(ltman.GetLayoutId(ltman.CurentLayout), OpenMode.ForRead);
It works with autocad 2012 to 2014 but in 2015 if one of layout is active (say Layout1) and user is within viewport then part GetLayoutId return ObjectId=0 therefore no layout.
Can anyone confirm this or eventually show some different way how to get current layout.
Thanks,
Richard
Solved! Go to Solution.
Solved by RichardCammeray. Go to Solution.
Hi,
I cannot reproduce the issue you describe, but you can try to get the current layout from the layout dictionary:
LayoutManager ltman = LayoutManager.Current; // open the named object dictionary DBDictionary NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead); // open the layout dictionary DBDictionary layoutDict = (DBDictionary)tr.GetObject(NOD.GetAt("ACAD_LAYOUT"), OpenMode.ForRead); // open the current layout Layout activeLayout = (Layout)tr.GetObject(layoutDict.GetAt(ltman.CurrentLayout), OpenMode.ForRead);
Thank you for testing and providing the alternative method. Probably I have found what is a issue. If the CommandMethod attribute has CommandFlag.Session then function has error. Can I ask you to test below code with acad 2015 with both options (with CommandFlag and without) what result you get
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.Geometry; using System; namespace TestLayout { public class TestCommand { [CommandMethod("TESTLAYOUT")] //[CommandMethod("TESTLAYOUT", CommandFlags.Session)] public void MainCommand() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; using (Transaction tr = doc.Database.TransactionManager.StartTransaction()) { LayoutManager ltman = LayoutManager.Current; Layout activeLayout = (Layout)tr.GetObject(ltman.GetLayoutId(ltman.CurrentLayout), OpenMode.ForRead); ObjectIdCollection viewportColl = activeLayout.GetViewports(); }//trans } } }
While you are in Layout please do not forget go inside of the viewport.
Thank you,
Richard
You forgot the tr.Commit().
Also becarefull with the layout.GetViewport() when it's not the active Layout, probably because Ps is not the active space in those cases.
I'll use y own:
public static ObjectIdCollection GetViewports(ObjectId layoutId) { ObjectIdCollection vpIds = new ObjectIdCollection(); Database db = layoutId.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { Layout layout = (Layout)tr.GetObject(layoutId, OpenMode.ForRead); BlockTableRecord btr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead); //If you want to skip the PaperSpace Viewport: //foreach (ObjectId id in btr.Cast<ObjectId>().Skip(1)) foreach (ObjectId id in btr.Cast<ObjectId>()) { if (id.ObjectClass.DxfName == "VIEWPORT") vpIds.Add(id); } tr.Commit(); } return vpIds; }
Note: theoretical the first viewport might not be the Paperspace viewport, but haven't seen that happening.
Tested the code and found no problems running the code without CommandFlags.Session
Command: Command: NETLOAD Command: TESTLAYOUT AcadVer==20.0s (LMS Tech)(20 is Acadxxx 2015) CTAB==Model TileMode==1 (0==Paperspace) CVPORT==2(>1 && TILEMODE==0:: MSPACE==true) Layout==Model TabSelected==True NrOfViewports==0 Command: *Cancel* Command: *Cancel* Command: <Switching to: Layout1> Regenerating layout. Regenerating model - caching viewports. Command: TESTLAYOUT AcadVer==20.0s (LMS Tech)(20 is Acadxxx 2015) CTAB==Layout1 TileMode==0 (0==Paperspace) CVPORT==1(>1 && TILEMODE==0:: MSPACE==true) Layout==Layout1 TabSelected==True NrOfViewports==2 Command: *Cancel* Command: _.MSPACE Command: TESTLAYOUT AcadVer==20.0s (LMS Tech)(20 is Acadxxx 2015) CTAB==Layout1 TileMode==0 (0==Paperspace) CVPORT==2(>1 && TILEMODE==0:: MSPACE==true) Layout==Layout1 TabSelected==True NrOfViewports==2
[CommandMethod("TESTLAYOUT")] //[CommandMethod("TESTLAYOUT", CommandFlags.Session)] public void MainCommand() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; ed.WriteMessage("\n AcadVer=={0}(20 is Acadxxx 2015)", Application.GetSystemVariable("ACADVER")); if (doc.IsNamedDrawing) ed.WriteMessage("\n Drawing=={0}", db.Filename); ed.WriteMessage("\n CTAB=={0}", Application.GetSystemVariable("CTAB")); ed.WriteMessage("\n TileMode=={0} (0==Paperspace)", Application.GetSystemVariable("TILEMODE")); ed.WriteMessage("\n CVPORT=={0}(>1 && TILEMODE==0:: MSPACE==true)", Application.GetSystemVariable("CVPORT")); LayoutManager ltman = LayoutManager.Current; ed.WriteMessage("\n Layout=={0}", ltman.CurrentLayout); using (Transaction tr = doc.Database.TransactionManager.StartTransaction()) { Layout activeLayout = (Layout)tr.GetObject(ltman.GetLayoutId(ltman.CurrentLayout), OpenMode.ForRead); ed.WriteMessage("\n TabSelected=={0}", activeLayout.TabSelected); ObjectIdCollection viewportColl = activeLayout.GetViewports(); if (viewportColl != null) ed.WriteMessage("\n NrOfViewports=={0}", viewportColl.Count); tr.Commit(); }//trans } }
And now for something completely different: Get Viewports for another not active layout: no problems found as well.
[CommandMethod("TESTLAYOUT")] //[CommandMethod("TESTLAYOUT", CommandFlags.Session)] public void MainCommand() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; ed.WriteMessage("\n AcadVer=={0}(20 is Acadxxx 2015)", Application.GetSystemVariable("ACADVER")); if (doc.IsNamedDrawing) ed.WriteMessage("\n Drawing=={0}", db.Filename); ed.WriteMessage("\n CTAB=={0}", Application.GetSystemVariable("CTAB")); ed.WriteMessage("\n TileMode=={0} (0==Paperspace)", Application.GetSystemVariable("TILEMODE")); ed.WriteMessage("\n CVPORT=={0}(>1 && TILEMODE==0:: MSPACE==true)", Application.GetSystemVariable("CVPORT")); LayoutManager ltman = LayoutManager.Current; ed.WriteMessage("\n Current Layout=={0}", ltman.CurrentLayout); string layoutName = null; PromptStringOptions pso = new PromptStringOptions("\n Enter LayoutName: "); pso.AllowSpaces = false; PromptResult pr = ed.GetString(pso); if (pr.Status != PromptStatus.OK) return; layoutName = pr.StringResult; ObjectId layoutId = ltman.GetLayoutId(layoutName); if (layoutId.IsNull) throw new System.Exception(string.Format("Error no such Layout: {0}", layoutName)); using (Transaction tr = doc.Database.TransactionManager.StartTransaction()) { Layout layout = (Layout)tr.GetObject(layoutId, OpenMode.ForRead); ed.WriteMessage("\n Selected Layout=={0}", layout.LayoutName); ed.WriteMessage("\n TabSelected=={0}", layout.TabSelected); ObjectIdCollection viewportColl = layout.GetViewports(); if (viewportColl != null) ed.WriteMessage("\n NrOfViewports=={0}", viewportColl.Count); tr.Commit(); }//trans }
Command: TESTLAYOUT AcadVer==20.0s (LMS Tech)(20 is Acadxxx 2015) CTAB==Layout1 TileMode==0 (0==Paperspace) CVPORT==1(>1 && TILEMODE==0:: MSPACE==true) Current Layout==Layout1 Enter LayoutName: layout1 Selected Layout==Layout1 TabSelected==True NrOfViewports==2 Command: *Cancel* Command: *Cancel* Command: <Switching to: Layout2> Regenerating layout. Regenerating model - caching viewports. Command: TESTLAYOUT AcadVer==20.0s (LMS Tech)(20 is Acadxxx 2015) CTAB==Layout2 TileMode==0 (0==Paperspace) CVPORT==1(>1 && TILEMODE==0:: MSPACE==true) Current Layout==Layout2 Enter LayoutName: layout1 Selected Layout==Layout1 TabSelected==False NrOfViewports==2
Thank you to both SENL1362 and _gile for alternative codes. All works well.
But I was still puzzled why my original code did not work in autocad 2015. Then when I found out that CommandFlags.Session is making problem, that reminded me to lock document. That was a problem.
Thanks,
Richard