A big thanks to Holger Seidel from CADsys for proposing this topic and providing the bulk of the code. My main contribution - aside from some minor edits - was to implement the logic in the "BJIG" command to allow selection of the block and then loop to multiply insert it. The jig definition is almost entirely Holger's.
The below C# code essentially implements a streamlined "multiple insert" command, without the options to scale or rotate the block (this would be very simple to add, of course).
The code was written for AutoCAD 2007-2008. The only change you should need for AutoCAD 2006 is to change JigPromptPointOptions to JigPromptOptions (which was changed to an abstract class in AutoCAD 2007, so you now need to use one of the derived concrete classes).
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
namespace BlockJigTest
{
class BlockJig : EntityJig
{
Point3d mCenterPt, mActualPoint;
public BlockJig(BlockReference br)
: base(br)
{
mCenterPt = br.Position;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
JigPromptPointOptions jigOpts =
new JigPromptPointOptions();
jigOpts.UserInputControls =
(UserInputControls.Accept3dCoordinates
| UserInputControls.NoZeroResponseAccepted
| UserInputControls.NoNegativeResponseAccepted);
jigOpts.Message =
"\nEnter insert point: ";
PromptPointResult dres =
prompts.AcquirePoint(jigOpts);
if (mActualPoint == dres.Value)
{
return SamplerStatus.NoChange;
}
else
{
mActualPoint = dres.Value;
}
return SamplerStatus.OK;
}
protected override bool Update()
{
mCenterPt = mActualPoint;
try
{
((BlockReference)Entity).Position = mCenterPt;
}
catch (System.Exception)
{
return false;
}
return true;
}
public Entity GetEntity()
{
return Entity;
}
}
public class Commands
{
[CommandMethod("BJIG")]
public void CreateBlockWithJig()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// First let's get the name of the block
PromptStringOptions opts =
new PromptStringOptions("\nEnter block name: ");
PromptResult pr = ed.GetString(opts);
if (pr.Status == PromptStatus.OK)
{
Transaction tr =
doc.TransactionManager.StartTransaction();
using (tr)
{
// Then open the block table and check the
// block definition exists
BlockTable bt =
(BlockTable)tr.GetObject(
db.BlockTableId,
OpenMode.ForRead
);
if (!bt.Has(pr.StringResult))
{
ed.WriteMessage("\nBlock not found.");
}
else
{
ObjectId blockId = bt[pr.StringResult];
// We loop until the jig is cancelled
while (pr.Status == PromptStatus.OK)
{
// Create the block reference and
// add it to the jig
Point3d pt = new Point3d(0, 0, 0);
BlockReference br =
new BlockReference(pt, blockId);
BlockJig entJig = new BlockJig(br);
// Perform the jig operation
pr = ed.Drag(entJig);
if (pr.Status == PromptStatus.OK)
{
// If all is OK, let's go and add the
// entity to the modelspace
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
);
btr.AppendEntity(
entJig.GetEntity()
);
tr.AddNewlyCreatedDBObject(
entJig.GetEntity(),
true
);
// Call a function to make the graphics display
// (otherwise it will only do so when we Commit)
doc.TransactionManager.QueueForGraphicsFlush();
}
}
}
tr.Commit();
}
}
}
}
}
A follow-up to this post, showing how to support attributes and annotation scaling, is available here.