Autocad Object Types in Visual Studio

The basic object, then AcadObject, then AcadEntity, then the specialized specific top objects. This is the object inheritance hierarchy in autocad. Most objects contained by the document derive from the most general AcadObject. Hence most objects have those basic properties, which include Handle, ObjectName, ObjectID and OwnerID. All the graphic elements, things you can see, like lines and circles, further derive from the AcadEntity object. The quickest way to survey this in the ActiveX Reference Guide clicking on the graphical Object Model. The dwg document object itself does not inherit from AcadObject, but most of what it contains does.

TreeView and ListView controls in Visual Studio are a little changed in Visual Studio from VB6. TreeView no longer uses a key or a relationship parameter in the argument list. There is a tag property that takes the place of key. Building a hierarchy is done by saving the node to a variable, then using its Nodes.Add method to create a new node directly as a child node.

To connect TreeView click event to the ListView display, MS uses the tag property, illustrated in this link.

The handle property of all AcadObjects is a string. It is permanent from session to session. The ObjectID serves the same purpose, (perhaps it preceded the handle historically) but its a Long integer, and it may change from session to session. OwnerID is the long integer container object. There is no owner handle. Once you have the handle captured to a string, or the ID to a long integer, you convert the string or long to an object with a method from AcadDocument, HandleToObject(string) or ObjectIDToObject(long). I keep Option Strict On to be constantly reminded when I am trying to pass variables from one type to another.

HandleToObject returns a generic object. But if it has a handle, its an AcadObject. So it can be immediately converted to AcadObject. In general, non-graphic elements derive from AcadObject only, and graphic elements derive from both AcadObject and AcadEntity. Everything in the drawing including Blocks collection and ModelSpace derive from AcadObject.

To further identify what type of object you have, use VB method TypeName and TypeOf

Dim obj As Object
Dim acad_obj As AcadObject
obj = acadDoc.HandleToObject(strhandle)
acad_obj = CType(obj, AcadObject)

Debug.Print(TypeName(obj))

Will return the typename and

  Case TypeOf acad_obj Is AcadBlock
  MsgBox("AcadBlock")
  blk = CType(obj, AcadBlock)
  Debug.Print(blk.Name & " " & blk.Count.ToString)

TypeOf will provide a boolean true or false to convert obj to its most specific type so you can use those methods, such as Name of the Block.

To populate a TreeView with an unknown number of levels, a recursive function is made with the parent node passed as one of the parameters.

If you are looking at a Block structure, the top level is a Block, and the embedded blocks are BlockReference.

ModelSpace and PaperSpace are blocks in the Blocks collection, they are also provided as shortcut properties of the Document, so they can be found either way, but usually using the property of the Document.

Button6 is the Block button on the form, it should say Blocks, it gets the entire Blocks collection. clicking on a node in the tree loads one level into ListView.

    Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
        Connect_acad()
        ListView1.Clear()
        Dim acadblks As AcadBlocks
        Dim blk As AcadBlock
        acadblks = acadDoc.Blocks

        Dim strhandle As String
        strhandle = acadblks.Handle
        listview_by_handle(strhandle)

        'start treeview
        TreeView1.Nodes.Clear()

        Dim rootnode As TreeNode
        rootnode = New TreeNode(acadblks.ObjectName)
        rootnode.Tag = acadblks.Handle
        TreeView1.Nodes.Add(rootnode)

        For Each blk In acadblks
            pop_tree(blk, rootnode)
        Next
    End Sub

ListViewByHandle is used to get the whole Blocks collection but its also called by a click event in the Tree to load the item selected. It has to have a fairly comprehensive Select Case to handle entities, blocks, blockrefs and block collection. I don’t try to do any levels in the ListView, so for instance, if you click on a block, it writes the block handle, name etc on the first line, then all the first level constituents under it.

Sub listview_by_handle(strhandle As String)
        ListView1.Clear()
        Dim item As ListViewItem
        Dim obj As Object
        Dim acad_obj As AcadObject
        Dim blk As AcadBlock
        Dim blkref As AcadBlockReference
        Dim acadblks As AcadBlocks

        With ListView1
            .Size = New Size(850, 500)
            .Columns.Add("ObjectName", 180)
            .Columns.Add("TypeName", 180)
            .Columns.Add("ObjectID", 100)
            .Columns.Add("OwnerID", 100)
            .Columns.Add("Handle", 100)
            .Columns.Add("NAME", 180)
            .View = View.Details
        End With

        obj = acadDoc.HandleToObject(strhandle)
        ' Debug.Print(TypeName(obj))
        acad_obj = CType(obj, AcadObject)

        item = New ListViewItem(acad_obj.ObjectName)
        item.SubItems.Add(TypeName(acad_obj))
        item.SubItems.Add(CType(acad_obj.ObjectID, String))
        item.SubItems.Add(CType(acad_obj.OwnerID, String))
        item.SubItems.Add(acad_obj.Handle)

        Select Case True
            Case TypeOf acad_obj Is AcadBlocks
                ' MsgBox("AcadBlocks")
                acadblks = acadDoc.Blocks
                item.SubItems.Add("")
                ListView1.Items.Add(item)

                For Each blk In acadblks
                    item = New ListViewItem(blk.ObjectName)
                    item.SubItems.Add(TypeName(blk))
                    item.SubItems.Add(CType(blk.ObjectID, String))
                    item.SubItems.Add(CType(blk.OwnerID, String))
                    item.SubItems.Add(blk.Handle)
                    item.SubItems.Add(blk.Name)
                    ListView1.Items.Add(item)
                Next

            Case TypeOf acad_obj Is AcadBlock
                'MsgBox("AcadBlock")
                blk = CType(obj, AcadBlock)
                Debug.Print(blk.Name & " " & blk.Count.ToString)

                item.SubItems.Add(blk.Name)
                ListView1.Items.Add(item)

                For Each acad_obj In blk
                    item = New ListViewItem(acad_obj.ObjectName)
                    item.SubItems.Add(TypeName(acad_obj))
                    item.SubItems.Add(CType(acad_obj.ObjectID, String))
                    item.SubItems.Add(CType(acad_obj.OwnerID, String))
                    item.SubItems.Add(acad_obj.Handle)
                    If TypeOf acad_obj Is AcadBlockReference Then
                        blkref = CType(acad_obj, AcadBlockReference)
                        item.SubItems.Add(blkref.Name)
                    Else
                        item.SubItems.Add("")
                    End If
                    ListView1.Items.Add(item)
                Next

            Case TypeOf acad_obj Is AcadBlockReference
                'MsgBox("AcadBlockReference")
                blkref = CType(obj, AcadBlockReference)
                Debug.Print("blkreference " & blkref.Name)

                item.SubItems.Add(blkref.Name)
                ListView1.Items.Add(item)

            Case TypeOf acad_obj Is AcadEntity
                'MsgBox("AcadEntity")
                ListView1.Items.Add(item)

        End Select
    End Sub

pop_tree is the recursive routine that makes the tree. It passes a block type parameter and the node that is parent to the block. It immediately adds a node for the block, then it surveys the block and if the constituent is a blockreference, it recurses using the new node as parent. if the constituent is not a block, it creates a new node and makes the entry. it uses the tag to save the handle so when the tree is clicked, the handle is retrieved, and the listview can be populated from the handle.

    Sub pop_tree(ByVal blk As AcadBlock, ByVal parentnode As TreeNode)
        Dim acad_ent As AcadEntity
        Dim anode As New TreeNode
        anode = parentnode.Nodes.Add(blk.Name)
        anode.Tag = blk.Handle

        For Each acad_ent In blk
            If TypeOf acad_ent Is AcadBlockReference Then
                Dim blkref As AcadBlockReference
                blkref = CType(acad_ent, AcadBlockReference)
                blk = acadDoc.Blocks.Item(blkref.Name)
                pop_tree(blk, anode)
            Else
                Dim newnode As New TreeNode
                newnode = anode.Nodes.Add(acad_ent.ObjectName)
                newnode.Tag = acad_ent.Handle
            End If
        Next
    End Sub

the treeview mouseclick event

    Private Sub TreeView1_NodeMouseClick(sender As Object, e As TreeNodeMouseClickEventArgs) Handles TreeView1.NodeMouseClick
        Dim newSelected As TreeNode = e.Node
        'Dim newSelected As TreeNode = TreeView1.SelectedNode
        Dim strhandle As String
        strhandle = CType(newSelected.Tag, String)
        listview_by_handle(strhandle)
    End Sub
End Class

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.