using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcGi = Autodesk.AutoCAD.GraphicsInterface;
using System.Collections.Generic;
using System;
namespace MyInsert
{
public class MyInsertCommand
{
// The command MyInsert displays the transient entity
// in all viewports (IntegerCollection is always empty)
[CommandMethod("MyInsert")]
public void MyInsert()
{
MyInsertCmd(new int[] { });
}
// The command MyInsertVP tries to be sensible: it
// shows the transient entity in all viewports only
// when TILEMODE = 1; in the paper space viewport
// alone when CVPORT = 1; else in the active floating
// viewports
[CommandMethod("MyInsertVP")]
public void MyInsertVP()
{
MyInsertCmd(ViewportNumbers());
}
// Naive implementation of block insert to demonstrate
// the display of a transient entity
void MyInsertCmd(int[] vps)
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = HostApplicationServices.WorkingDatabase;
// Ask user for a block name and check if it's in
// the BlockTable
PromptStringOptions pso =
new PromptStringOptions("Block name")
{
AllowSpaces = true
};
PromptResult psr = ed.GetString(pso);
if (psr.Status != PromptStatus.OK)
return;
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
BlockTable bt =
(BlockTable)tr.GetObject(
db.BlockTableId, OpenMode.ForRead
);
if (!bt.Has(psr.StringResult))
ed.WriteMessage(
"\nBlock {0} not found.", psr.StringResult
);
else
{
// Set up the BlockReference to draw as transient
AcGi.TransientManager ctm =
AcGi.TransientManager.CurrentTransientManager;
IntegerCollection ints = new IntegerCollection(vps);
BlockReference br =
new BlockReference(
Point3d.Origin, bt[psr.StringResult]
);
ctm.AddTransient(
br, AcGi.TransientDrawingMode.DirectShortTerm,
128, ints
);
// Add event handler for PointMonitor event, then
// let user select an insertion point, afterwards
// ensure removal of event handler and transient
PointMonitorEventHandler handler =
delegate(object sender, PointMonitorEventArgs e)
{
br.Position = e.Context.RawPoint;
ctm.UpdateTransient(br, ints);
};
ed.PointMonitor += handler;
PromptPointResult ppr;
try
{
ppr = ed.GetPoint("Select insertion point");
}
finally
{
ed.PointMonitor -= handler;
ctm.EraseTransient(br, ints);
}
// If insertion point selection was
// successfull, add BlockReference to
// current space
if (ppr.Status == PromptStatus.OK)
{
BlockTableRecord cs =
(BlockTableRecord)tr.GetObject(
db.CurrentSpaceId, OpenMode.ForWrite
);
cs.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
}
}
// Common exit point for all code paths inside
// using statement
tr.Commit();
}
}
// Determines which viewports will display the transient
int[] ViewportNumbers()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = HostApplicationServices.WorkingDatabase;
// Are we in model space outside floating viewports?
// Then we'll initalize an empty IntegerCollection
if (db.TileMode)
return new int[] {};
IList<int> vps = new List<int>();
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
Viewport vp =
tr.GetObject(ed.ActiveViewportId, OpenMode.ForRead)
as Viewport;
// Are we in paper space and not inside a floating
// viewport? Then only the paper space viewport itself
// is of interest
if (vp != null && vp.Number == 1)
vps.Add(1);
else
// Now we're inside a floating viewport and
// will display transients in active viewports
foreach (ObjectId vpId in db.GetViewports(false))
{
vp = (Viewport)tr.GetObject(vpId, OpenMode.ForRead);
vps.Add(vp.Number);
};
tr.Commit();
}
int[] ints = new int[vps.Count];
vps.CopyTo(ints, 0);
return ints;
}
}
}
To demonstrate the problem with the first approach, let’s take a paperspace view with two floating viewports:
When we make the larger viewport active and start the MYINSERT command to insert a block, we sometimes see unwanted graphics in the top-level paperspace view:
Many thanks, Thorsten, for highlighting this issue and providing a solution for it! :-)