2007年2月19日

Getting access to an entity from its handle in AutoCAD .NET

Getting access to an entity from its handle in AutoCAD .NET

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

留下您的评论