I have stored within an external database a handle of an entity within a drawing. If I have that drawing open and I retrieve that handle and then get the ObjectID from that Handle how do I convert that to a BlockReference so that I can then get position and attrribute values. I can get the position and attributes if I can just get the blockreference from the Object ID.
I am using the following code to get the ObjectID from the Handle:
Public Function ObjectIdFromHandle(db As Database, strHandle As String) As ObjectId Dim nHandle As Int32 = Int32.Parse(strHandle, Globalization.NumberStyles.AllowHexSpecifier) Dim handle As New Handle(nHandle) Dim ids(0) As ObjectId Try ids(0) = db.GetObjectId(False, handle, 0) Catch ex As Exception MsgBox(ex.Message.ToString, MsgBoxStyle.Exclamation, "Error in ObjectIDfromHandle") End Try Return ids(0) 'Return db.GetObjectId(False, handle, 0) End Function
I then want to use this ObjectID to get the BlockReference.
Any help is greatly appreciated!
Thanks,
Hi,
To get the BlockReference from the ObjectId, you have to open the object, maybe this can help :
PS: since A2012 (I think) there's a Database.TryGetObjectId() method
I guess I should also add that I am using code that generates an error telling me that unable to cast an object from BlockTable to BlockTableReference.
I have been taking my handles and getting the objectid and then creating a selection set from those objectids and then using selection sets to get the information I need from the entities but I thought if I did not need to convert to a selection set first I may save some overhead. But maybe this isnt possible.
Below one option I was trying to use but I get the unable to cast blocktable to blockreference error.
Using Lock As DocumentLock = myDoc.LockDocument For i As Integer = 0 To PointSSetBindingSource.Count - 1 Using trans As Transaction = db.TransactionManager.StartTransaction Dim bt As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForWrite) Dim btr As BlockTableRecord = trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite) Dim BlockObjectID As ObjectId = ObjectIdFromHandle(db, PointSSetBindingSource(i)("SelectionSetID").ToString) ' Have attempted to use the following and many many more 'Dim bref As BlockReference = trans.GetObject(BlockObjectID , OpenMode.ForRead) 'Dim bref As BlockReference = DirectCast(trans.GetObject(BlockObjectID, OpenMode.ForRead), BlockReference) 'Dim bref As BlockReference = BlockObjectID.GetObject(OpenMode.ForRead) End Using Next End Using
here my code for get a BlockReference From a Handle.
This Handle is on Cell of DatagridView.
Dim RefBloc As BlockReference = Nothing Dim Txt As String = "" Txt = DatagridVeiw1.SelectedCells.Item(0).OwningRow.Cells.Item(.ColumnCount - 1).Value.ToString() Dim db As Database = HostApplicationServices.WorkingDatabase Dim tr As Transaction = db.TransactionManager.StartTransaction() Try Dim objID As ObjectId = db.GetObjectId(False, New Handle(Int64.Parse(Txt, Globalization.NumberStyles.AllowHexSpecifier)), 0) RefBloc = tr.GetObject(objID, OpenMode.ForRead) Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument Dim acEd As Editor = acDoc.Editor Dim ext As Extents3d ext = RefBloc.GeometricExtents ext.TransformBy(acEd.CurrentUserCoordinateSystem.Inverse()) ''test affichage du carré : 'Dim Newrec As New Autodesk.AutoCAD.DatabaseServices.Polyline 'Newrec.AddVertexAt(0, New Point2d(ext.MinPoint.X, ext.MinPoint.Y), 0, 0, 0) 'Newrec.AddVertexAt(1, New Point2d(ext.MaxPoint.X, ext.MinPoint.Y), 0, 0, 0) 'Newrec.AddVertexAt(2, New Point2d(ext.MaxPoint.X, ext.MaxPoint.Y), 0, 0, 0) 'Newrec.AddVertexAt(3, New Point2d(ext.MinPoint.X, ext.MaxPoint.Y), 0, 0, 0) 'Newrec.Closed = True 'Dim btr As BlockTableRecord = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) 'btr.AppendEntity(Newrec) 'tr.AddNewlyCreatedDBObject(Newrec, True) ''GestionAUTOCAD.ZoomWin(False, acEd, ext.MinPoint, ext.MaxPoint) Catch ex As Exception 'erreur If ex.Message = "eNullExtents" Then MsgBox("Le bloc choisi n'a aucune forme visible" & _ vbCrLf & "Impossible de l'afficher !", vbOKOnly, "Erreur Système") Else MsgBox(ex.ToString, vbOKOnly, "Erreur Système") End If OkErr = True Finally RefBloc = Nothing tr.Commit() tr.Dispose() End Try
This code retrieve the blockreference from a Handle (Stored in String on a Cell)
and i zoom on the block. (in ' you have the code for create à polyligne ).
here the code for the sub ZoomWin
'********************************************************************************** 'Function de zoom ' Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument ' Dim acEd As Editor = acDoc.Editor '--> ' Entrée : ' debug : True : permet d'afficher les infos du zoom ' ed : l'editor d'autocad ' min : un point 2D min ' max onymous : un point 2D max ' Sortie ' Rien '********************************************************************************** Public Sub ZoomWin(ByVal debug As Boolean, ByVal ed As Editor, ByVal min As Point3d, ByVal max As Point3d) Dim lower As String = min.ToString().Substring(1, min.ToString().Length - 2) Dim upper As String = max.ToString().Substring(1, max.ToString().Length - 2) Dim cmd As String = "_.ZOOM _W " + lower + " " + upper + " " If debug = True Then ed.Document.SendStringToExecute(cmd, True, False, True) Else ed.Document.SendStringToExecute(cmd, True, False, False) End If End Sub
Ohh my...Sometimes I just dont see the obvious! I was using the wrong field from my binding source. All is good now.
Just a general question..is it faster to go directly to the block reference instead of creating a selection set and then getting the info...I assume it would almost have to be but just thought I would ask for general thoughts. I suppose if it is a polyline that I need to alter I would need to go with the selection set route?
Thanks,