Warm tip: This article is reproduced from serverfault.com, please click

Why do viewports created using commands in ObjectARX not save to the database?

发布于 2021-01-11 19:45:00

Summary

I'm trying to write a C# ObjectARX script to create a viewport that fits the extents of the layout using the -VPORTS Fit command, but for some reason the new viewport shows in AutoCAD but is never saved to the output drawing.

Some things I've tried

  • Using acDoc.SendStringToExecute() instead of acDoc.Editor.Command()
  • Using -VPORTS instead of ._VIEWPORTS
  • Running the commands before commiting the transaction
    • Caused AutoCAD to freeze and crash. I think I have to commit the new layout before I can make the viewport

Code Snippet

[CommandMethod("CreateViewport")]
public static void CreateViewport()
{
    // Get the current document and database, and start a transaction
    Document acDoc = Application.DocumentManager.MdiActiveDocument;
    Database acCurDb = acDoc.Database;

    try
    {
        Entity acObj = null;

        using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
        {
            // Omitted code for opening block record ...

            // Switch to the previous Paper space layout
            Application.SetSystemVariable("TILEMODE", 0);
            acDoc.Editor.SwitchToPaperSpace();

            // Omitted code for creating a polyline in model space to focus on (acObj) ...
            // Omitted code for creating a new layout ...

            // Save the new objects to the database
            acTrans.Commit();
        }

        // This is the part that shows in AutoCAD but doesn't save
        acDoc.Editor.Command("._VIEWPORTS", "Fit");
        acDoc.Editor.Command("._MSPACE");
        acDoc.Editor.Command("._ZOOM", "_O", SelectionSet.FromObjectIds(new ObjectId[] { acObj.ObjectId }), "");
        acDoc.Editor.Command("._PSPACE");
        acDoc.Editor.Command("._ZOOM", "E");

        acCurDb.SaveAs("OutputDrawing.dwg", DwgVersion.AC1027);
    }
    catch (Exception ex)
    {
        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.ToString());
    }
}
Questioner
Wesley Reed
Viewed
0
Wesley Reed 2021-03-09 05:58:59

I have spoken directly with Autodesk on this, and it looks like my issue was the way I was deleting old viewports and creating a new one. They provided the following change to my code with works as intended

[CommandMethod("CreateViewport")]
public static void CreateViewport()
{
    // Get the current document and database, and start a transaction
    Document acDoc = Application.DocumentManager.MdiActiveDocument;
    Database acCurDb = acDoc.Database;
    try
    {
        Entity acObj = null;
        using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
        {
            // Open the Block table for read
            BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
            // Open the Block table record Model space for write
            BlockTableRecord acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
            // Draw the desired viewport on the default layer
            // Create a circle that is at 2,3 with a radius of 4.25
            Circle acCirc = new Circle();
            acCirc.SetDatabaseDefaults();
            acCirc.Center = new Point3d(2, 3, 0);
            acCirc.Radius = 4.25;
            acObj = acCirc;
            acBlkTblRec.AppendEntity(acObj);
            acTrans.AddNewlyCreatedDBObject(acObj, true);
            // Set current layer to 0
            acCurDb.Clayer = acObj.LayerId;
            // Switch to the previous Paper space layout
            Application.SetSystemVariable("TILEMODE", 0);
            acDoc.Editor.SwitchToPaperSpace();
            // List Layouts
            DBDictionary layoutDic = acTrans.GetObject(acCurDb.LayoutDictionaryId, OpenMode.ForRead, false) as DBDictionary;
            LayoutManager acLayoutMgr = LayoutManager.Current;
            Layout acLayout = null;
            foreach (DBDictionaryEntry entry in layoutDic)
            {
                ObjectId layoutId = entry.Value;
                Layout currentLayout = acTrans.GetObject(layoutId, OpenMode.ForRead) as Layout;
                if (currentLayout.LayoutName == "Layout1")
                {
                    acLayout = acTrans.GetObject(layoutId, OpenMode.ForWrite) as Layout;
                    // Delete any existing view ports
                    ObjectIdCollection acViewports = acLayout.GetViewports();
                    foreach (ObjectId acViewportID in acViewports)
                    {
                        Viewport acVport = acTrans.GetObject(acViewportID, OpenMode.ForWrite) as Viewport;
                        acVport.Erase();
                    }
                    //create a blank viewport, we need at least one viewport
                    var btr = (BlockTableRecord)acTrans.GetObject(acLayout.BlockTableRecordId, OpenMode.ForWrite);
                    var vp = new Viewport();
                    btr.AppendEntity(vp);
                    acTrans.AddNewlyCreatedDBObject(vp, true);
                    break;
                }
            }
            // If layout wasn't found, make it
            if (acLayout == null)
            {
                ObjectId objID = acLayoutMgr.CreateLayout("Layout1");
                acLayout = acTrans.GetObject(objID, OpenMode.ForWrite) as Layout;
            }

            // Set the layout current if it is not already
            if (acLayout.TabSelected == false)
            {
                acLayoutMgr.CurrentLayout = acLayout.LayoutName;
            }
            PlotSettings acPlSet = new PlotSettings(acLayout.ModelType);
            acPlSet.CopyFrom(acLayout);
            // Update the PlotConfigurationName property of the PlotSettings object
            PlotSettingsValidator acPlSetVdr = PlotSettingsValidator.Current;
            acPlSetVdr.SetPlotConfigurationName(acPlSet, "DWG To PDF.pc3", "ANSI_B_(11.00_x_17.00_Inches)");
            // Zoom to show the whole paper
            acPlSetVdr.SetZoomToPaperOnUpdate(acPlSet, true);
            // Update the layout
            if (!acLayout.IsWriteEnabled)
            {
                acLayout.UpgradeOpen();
            }                    

            acLayout.CopyFrom(acPlSet);
            // Save the new objects to the database
            acTrans.Commit();
        }
        acDoc.Editor.Command("._VIEWPORTS", "Fit");
        acDoc.Editor.Command("._MSPACE");
        acDoc.Editor.Command("._ZOOM", "_O", SelectionSet.FromObjectIds(new ObjectId[] { acObj.ObjectId }), "");
        acDoc.Editor.Command("._PSPACE");
        acDoc.Editor.Command("._ZOOM", "E");
        string dwgPath = @"D:\Work\Cases\8360\OutputDrawing_.dwg";
        dwgPath = dwgPath.Insert(dwgPath.IndexOf(".dwg"), DateTime.Now.ToString("yyyyMMddHHmmssffff"));
        acCurDb.SaveAs(dwgPath, DwgVersion.AC1032);
    }
    catch (System.Exception ex)
    {
        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.ToString());
    }
}