Creating an AutoCAD leader with a different arrowhead using .NET
Most of this week I've spent catching up after a nice, long break, as well as spending a few days in Prague helping interview potential recruits for our European team. Now it's finally time for me to climb back into the blogging saddle...
This first entry of 2007 is based on some code provided by Viru Aithal, a member of our team based in Bangalore. The code demonstrates how to create a leader using an arrowhead other than the current default (the one referred to by the DIMBLK system variable).
Here's the C# code:
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using System;
[assembly:
CommandClass(
typeof(
DimensionLibrary.DimensionCommands
)
)
]
namespace DimensionLibrary
{
public class DimensionCommands
{
static ObjectId GetArrowObjectId(string newArrName)
{
ObjectId arrObjId = ObjectId.Null;
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
// Get the current value of DIMBLK
string oldArrName =
Application.GetSystemVariable(
"DIMBLK"
) as string;
// Set DIMBLK to the new style
// (this action may create a new block)
Application.SetSystemVariable(
"DIMBLK",
newArrName
);
// Reset the previous value of DIMBLK
if (oldArrName.Length != 0)
Application.SetSystemVariable(
"DIMBLK",
oldArrName
);
// Now get the objectId of the block
Transaction tr =
db.TransactionManager.StartTransaction();
using(tr)
{
BlockTable bt =
(BlockTable)tr.GetObject(
db.BlockTableId,
OpenMode.ForRead
);
arrObjId = bt[newArrName];
tr.Commit();
}
return arrObjId;
}
// Define Command "ld"
[CommandMethod("ld")]
static public void CreateLeader()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
const string arrowName = "_DOT";
ObjectId arrId = GetArrowObjectId(arrowName);
// Get the start point of the leader
PromptPointResult result =
ed.GetPoint(
"\nSpecify leader start point: "
);
if (result.Status != PromptStatus.OK)
return;
Point3d startPt = result.Value;
// Get the end point of the leader
PromptPointOptions opts =
new PromptPointOptions(
"\nSpecify end point: "
);
opts.BasePoint = startPt;
opts.UseBasePoint = true;
result = ed.GetPoint(opts);
if (result.Status != PromptStatus.OK)
return;
Point3d endPt = result.Value;
// Now let's create the leader itself
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
try
{
BlockTable bt =
(BlockTable)tr.GetObject(
db.BlockTableId,
OpenMode.ForRead
);
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
);
// Add the MText
MText mt = new MText();
mt.Contents =
"Leader with the \"" +
arrowName +
"\" arrow head";
mt.Location = endPt;
ObjectId mtId = btr.AppendEntity(mt);
tr.AddNewlyCreatedDBObject(mt, true);
// Add the Leader
Leader ld = new Leader();
ld.AppendVertex(startPt);
ld.AppendVertex(endPt);
btr.AppendEntity(ld);
tr.AddNewlyCreatedDBObject(ld, true);
ld.Annotation = mtId;
ld.Dimldrblk = arrId;
tr.Commit();
}
catch
{
tr.Abort();
}
}
}
}
}
Some comments on the technique used:
A helper function (GetArrowObjectId(arrowName)) is used to get the ObjectID of the block of our arrow head. To make sure this block exists, the function sets the value of DIMBLK to the arrowhead name, which - assuming the name is valid - will create the block in the block table. Then we simply have to get its ID and return it.
Once you've built the code, simply run the "LD" command, and select two points defining your leader (the code can easily be extended to allow selection of additional points and entry of a user-defined annotation string, of course).
Here's what you should see: