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);
}
}
Solved! Go to Solution.
Solved by ActivistInvestor. Go to Solution.
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
Yes , I repaired it like this
[CommandMethod("ExportBlocksToNewDrawings", CommandFlags.Session)]
However It appear an error
So could you help me fix this?
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);
}
}
Can't find what you're looking for? Ask the community or share your knowledge.