.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Zoom the drawing after separating many objects into a new drawing.

4 REPLIES 4
SOLVED
Reply
Message 1 of 5
traiduong014969
308 Views, 4 Replies

Zoom the drawing after separating many objects into a new drawing.

Hi all,

Recently, I tried separating many objects into a new drawing. This process is done, but there is an issue that needs to be fixed. Specifically, I want my new drawing, after separating, to zoom to fit the screen. I tried using `Command("_.ZOOM", "_E")`, but the drawing does not zoom. Could someone help me fix this issue?

Thanks!

[CommandMethod("ExportBlocksToNewDrawings")]
    public void ExportBlocksToNewDrawings()
    {
        Document acDoc = Application.DocumentManager.MdiActiveDocument;
        Database acCurDb = acDoc.Database;
        Editor acEd = acDoc.Editor;

        string desktopPath = @"C:\Users\xxx\Desktop";

        using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
        {
            BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable;
            BlockTableRecord acModelSpace = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;

            foreach (ObjectId blkId in acBlkTbl)
            {
                BlockTableRecord acBlkTblRec = acTrans.GetObject(blkId, OpenMode.ForRead) as BlockTableRecord;

                if (acBlkTblRec.IsAnonymous || acBlkTblRec.IsLayout)
                    continue;

                foreach (ObjectId objId in acModelSpace)
                {
                    Entity ent = acTrans.GetObject(objId, OpenMode.ForRead) as Entity;
                    if (ent is BlockReference)
                    {
                        BlockReference blkRef = ent as BlockReference;
                        if (blkRef.BlockTableRecord == blkId)
                        {
                            string newFileName = Path.Combine(desktopPath, acBlkTblRec.Name + ".dwg");
                            Database newDb = new Database(true, true);

                            using (Transaction newTrans = newDb.TransactionManager.StartTransaction())
                            {
                                BlockTable newBlkTbl = newTrans.GetObject(newDb.BlockTableId, OpenMode.ForWrite) as BlockTable;
                                BlockTableRecord newModelSpace = newTrans.GetObject(newBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

                                IdMapping acIdMap = new IdMapping();
                                acCurDb.WblockCloneObjects(
                                    new ObjectIdCollection(new ObjectId[] { blkId }),
                                    newBlkTbl.ObjectId,
                                    acIdMap,
                                    DuplicateRecordCloning.Replace,
                                    false);

                                BlockTableRecord newBlkTblRec = newTrans.GetObject(acIdMap[blkId].Value, OpenMode.ForRead) as BlockTableRecord;

                                using (BlockReference newBlockRef = new BlockReference(blkRef.Position, newBlkTblRec.ObjectId))
                                {
                                    newModelSpace.AppendEntity(newBlockRef);
                                    newTrans.AddNewlyCreatedDBObject(newBlockRef, true);
                                }

                                newTrans.Commit();

                                newDb.SaveAs(newFileName, DwgVersion.Current);
                                newDb.Dispose();
                            }

                            ZoomExtents(newFileName, acEd);
                        }
                    }
                }
            }

            acTrans.Commit();
        }
    }

    private void ZoomExtents(string newFileName, Editor ed)
    {
        DocumentCollection acDocMgr = Application.DocumentManager;
        Document acDoc = acDocMgr.Open(newFileName, false);
        Database acDb = acDoc.Database;

        Editor newEd = acDoc.Editor;

        newEd.Command("_.ZOOM", "_E");

        acDoc.CloseAndSave(newFileName);
    }
}
4 REPLIES 4
Message 2 of 5

Since your CommandMethod attribute does not use CommandFlags argument ( CommandFlags.Session ), the drawing opened in ZoomExtents() method does not becomes MdiActiveDocument after the call acDocMgr.Open(...), thus the Command(".Zoom", ...) would not work (I was surprised that it did not raise exception when the code try to use Editor of the non-MdiActiveDocument, though).

 

Norman Yuan

Drive CAD With Code

EESignature

Message 3 of 5

Yes , I repaired it like this

 [CommandMethod("ExportBlocksToNewDrawings", CommandFlags.Session)]

However It appear an error 

trai_duongngoc_0-1718329076639.pngtrai_duongngoc_1-1718329121865.png

trai_duongngoc_2-1718329147440.pngtrai_duongngoc_3-1718329190626.png

So could you help me fix this?

 

Message 4 of 5

To run the Command() method from the application context, you must use ExecuteInCommandContextAsync(), however, I've recently discovered that this API has significant problems (related to how it deals with exceptions) that make it very easy to crash AutoCAD (any exception that's thrown by the delegate or the continuation will terminate AutoCAD).

 

I built a wrapper for ExecuteInCommandContextAsync() that mitigates the problem to some extent, which you can download from here.

 

Here's an example showing how it would be used in a use-case that's similar to yours.

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Threading.Tasks;


public static class MyCommands
{
   static DocumentCollection docs = Application.DocumentManager;
   
   /// For each open document, this command will switch to
   /// the model tab, zoom extents, and then save the file.

   [CommandMethod("ZOOMSAVECLOSEALL", CommandFlags.Session)]
   public static async void ZoomSaveCloseAll()
   {
      var documents = Application.DocumentManager;
      
      try    // This try/catch is NOT optional
      {
         int saved = 0;
         foreach(Document doc in documents)
         {
            if(doc.IsNamedDrawing && !doc.IsReadOnly)
            {
               if(!doc.IsActive)
                  documents.MdiActiveDocument = doc;

               await documents.InvokeAsCommandAsync(
                  delegate (Document doc)
                  {
                     /// this code runs in the document context:
                     var editor = doc.Editor;
                     editor.Command("._SETVAR", "TILEMODE", 1);
                     editor.Command("._ZOOM", "_E");
                     editor.Command("._QSAVE");
                     ++saved;
                  }
               );

               /// The continuation runs in 
               /// the application context:

               doc.CloseAndDiscard();
            }
         }
         Write($"Operation completed,\nProcessed {saved} documents.");
      }
      catch(System.Exception ex)
      {
         UnhandledExceptionFilter.CerOrShowExceptionDialog(ex);
         Write($"Operation was not successfully completed ({ex.Message})");

         /// Do not re-throw the exception!!!
         /// If you do, AutoCAD will terminate.
      }
   }
   
   public static void Write(string fmt, params object[] args)
   {
      docs.MdiActiveDocument?.Editor.WriteMessage("\n" + fmt, args);
   }

}

 

 

 

Message 5 of 5

Thank for your reply. It works for me

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Technology Administrators


Autodesk Design & Make Report