Getting access to an entity from its handle in AutoCAD .NET
This comment came in overnight from Brian:
I was hoping to work out how to get the Entity from the handle and then erase it, from your posts, I've learned a lot but not found the answer to this one yet, I still have a mountain to climb. (I'm using VB.NET, I've done it in VB6 +COM, even in Lisp but .NET ....)
As it's such a good question, I'm making a post out of it...
The trick is to go from a hexadecimal string to a 64-bit integer (using System.Convert.ToInt64(str,16); which specifies the string as being "base-16" or hexadecimal).
From there you simply use the long integer to create a Handle, which you pass into Database.GetObjectId(): you should specify false for the first argument, as we don't want to create a new ObjectId if one does not exist, and pass 0 into the third argument (which is reserved for future use).
From there you should have a valid ObjectId that can be opened and erased. If the handle entered doesn't exist, then GetObjectId() will throw an exception - I'll leave it to the user to catch this exception more elegantly (i.e. with a nicer error message).
Here's the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
namespace HandleTest
{
public class HandleCommands
{
[CommandMethod("EH")]
public void EraseObjectFromHandle()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
try
{
// Ask for a string representing the handle
PromptResult pr =
ed.GetString("\nEnter handle of object to erase: ");
if (pr.Status == PromptStatus.OK)
{
// Convert hexadecimal string to 64-bit integer
long ln = Convert.ToInt64(pr.StringResult, 16);
// Not create a Handle from the long integer
Handle hn = new Handle(ln);
// And attempt to get an ObjectId for the Handle
ObjectId id = db.GetObjectId(false,hn,0);
// Finally let's open the object and erase it
Transaction tr =
doc.TransactionManager.StartTransaction();
using (tr)
{
DBObject obj =
tr.GetObject(id, OpenMode.ForWrite);
obj.Erase();
tr.Commit();
}
}
}
catch (System.Exception ex)
{
ed.WriteMessage(
"Exception: " + ex
);
}
}
}
}
And as Brian specifed VB.NET, here's that, too:
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.Runtime
Imports System
Namespace HandleTest
Public Class HandleCommands
<CommandMethod("EH")> _
Public Sub EraseObjectFromHandle()
Dim doc As Document = _
Application.DocumentManager.MdiActiveDocument
Dim ed As Editor = doc.Editor
Dim db As Database = doc.Database
Try
' Ask for a string representing the handle
Dim pr As PromptResult = _
ed.GetString( _
vbLf + _
"Enter handle of object to erase: ")
If (pr.Status = PromptStatus.OK) Then
' Convert hexadecimal string to 64-bit integer
Dim ln As Long = _
Convert.ToInt64(pr.StringResult, 16)
' Not create a Handle from the long integer
Dim hn As Handle = New Handle(ln)
' And attempt to get an ObjectId for the Handle
Dim id As ObjectId = _
db.GetObjectId(False, hn, 0)
' Finally let's open the object and erase it
Dim tr As Transaction = _
doc.TransactionManager.StartTransaction
Dim obj As DBObject = _
tr.GetObject(id, OpenMode.ForWrite)
obj.Erase()
tr.Commit()
tr.Dispose()
End If
Catch ex As System.Exception
ed.WriteMessage("Exception: " + ex.ToString)
End Try
End Sub
End Class
End Namespace