Here's a command example which mimics the -BLOCK command.
// Mimics the native -BLOCK command
[CommandMethod("CREATEBLOCK")]
public void CreateBlock()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
using (var tr = db.TransactionManager.StartTransaction())
{
var blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
string blockName;
while (true)
{
var promptResult = ed.GetString("\nEnter block name: ");
if (promptResult.Status != PromptStatus.OK) return;
blockName = promptResult.StringResult;
if (string.IsNullOrWhiteSpace(blockName)) return;
if (!blockTable.Has(blockName)) break;
ed.WriteMessage($"Block \"{blockName}\" already exists");
}
var promptPointResult = ed.GetPoint("\nSpecify the base point: ");
if (promptPointResult.Status != PromptStatus.OK) return;
var selection = ed.GetSelection();
if (selection.Status != PromptStatus.OK) return;
var blockDefinition = new BlockTableRecord();
blockDefinition.Name = blockName;
tr.GetObject(db.BlockTableId, OpenMode.ForWrite);
var blockId = blockTable.Add(blockDefinition);
tr.AddNewlyCreatedDBObject(blockDefinition, true);
var mapping = new IdMapping();
var identifiers = new ObjectIdCollection(selection.Value.GetObjectIds());
db.DeepCloneObjects(identifiers, blockId, mapping, false);
var xform = Matrix3d.Displacement(
promptPointResult.Value
.TransformBy(ed.CurrentUserCoordinateSystem)
.GetAsVector()
.Negate());
foreach (IdPair pair in mapping)
{
if (pair.IsCloned && pair.IsPrimary)
{
var entity = (Entity)tr.GetObject(pair.Value, OpenMode.ForWrite);
entity.TransformBy(xform);
}
}
tr.Commit();
}
}
}