Problem with getting XData between VB6 and .NET

Problem with getting XData between VB6 and .NET

Anonymous
Not applicable
1,386 Views
4 Replies
Message 1 of 5

Problem with getting XData between VB6 and .NET

Anonymous
Not applicable

In my application we have a hidden block in the drawing with the name MyCAD.Info

 

The XData stores information that pertains to the entire drawing. The most import of which is a unique Drawing ID.

 

WIth the VBA interface I get the XData easily both under VB6 and using interop under .NET.

 

            Dim mApp As AcadApplication = CType(Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication, Autodesk.AutoCAD.Interop.AcadApplication)
            Dim mDoc As AcadDocument = mApp.ActiveDocument
            Dim mDocBlock As AcadBlock = mDoc.Blocks.Item("MyCAD.Info")

            Dim xDataType As Object = Nothing
            Dim xData As Object = Nothing

mDocBlock.GetXData("MyCAD", xDataType, xData)

xData returns all the data that I expected.

 

But when  when I try using the .NET API I get nothing

 

 

            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database


            Using tr As Transaction = db.TransactionManager.StartTransaction 'OpenTransaction()

                Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
                Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForRead), BlockTableRecord)
                Dim it As BlockTableRecordEnumerator = btr.GetEnumerator()

                While it.MoveNext()
                    Dim obj As DBObject = GetObject(it.Current, OpenMode.ForRead, tr)
                    If obj IsNot Nothing Then
                        Dim br As BlockReference = TryCast(obj, BlockReference)
                        If br IsNot Nothing Then
                            Dim TempS As String = br.Name
                            If br.Name = "MyCAD.Info" Then
                                Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(vbNewLine + TempS + vbNewLine)
                                TempS = "=================================================="
                                Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(vbNewLine + TempS + vbNewLine)
                                Dim rb As ResultBuffer = obj.XData()
                                If rb IsNot Nothing Then
                                    For Each tv As TypedValue In rb
                                        TempS = tv.Value.ToString
                                        Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(vbNewLine + TempS + vbNewLine)
                                    Next
                                End If
                                TempS = "=================================================="
                                Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(vbNewLine + TempS + vbNewLine)
                            End If

                        End If
                    End If
                End While
            End Using

 

 

Tracing through this, it finds the block but the XData is empty. I wonder is the place that GetXData of VBA is pulling from the same place as the XData method.

 

 

0 Likes
1,387 Views
4 Replies
Replies (4)
Message 2 of 5

Anonymous
Not applicable

Give DBObject.GetXDataForApplication(string) a try for retrieving the XData.  

 

 

0 Likes
Message 3 of 5

chiefbraincloud
Collaborator
Collaborator

First, I agree with Dan, using GetXdataForApplication would be appropriate, though I could see how it might not affect you if you can be sure that only your xdata is present.

 

Second, since that would not have any effect on your functions ability to get the XData, I looked it over, and noticed this line:

 

Dim obj As DBObject = GetObject(it.Current, OpenMode.ForRead, tr)

 

I can not find that particular GetObject Function in the object browser, so, is it a function you have written?

 

I pasted your code into a test function, and in order to keep everything equivalent, I did not mess with the code, except to comment out the IF statement that checks for your block name, and changing the aforementioned GetObject line to this:

Dim obj As DBObject = tr.GetObject(it.Current, OpenMode.ForRead)

 

The code works for me.

 

For what it's worth, I worked up an example in the attached text file, pointing out some things I would change about your code, and commenting briefly about why.

 

 

Dave O.                                                                  Sig-Logos32.png
0 Likes
Message 4 of 5

Anonymous
Not applicable

ChiefBrainCloud,

 

Thanks although it still didn't work the solution was helpful in learning about the AutoCAD API. Yes GetObject was my own funciton.  All it did different than tr.GetObject was check to see if the object is erased, returning nothing if it was.

 

I made use of GetXDataForApplication and it didn't work. I tried the attached code and it still didn't work although it did find the block in question. I also played around with select all trying different filters including using New typedValue(1001, "MyCAD") which picked up all the other block that represent the shaps our application drew. So that was good.

 

Digging around in the original VBA the original Block xData was set using SetxData("MyCAD", blah, blah). Do we know when we used the VBA Setxdata where the data actually goes and as a consquence where Getxdata retrieves from. And is there an independent command we can use to see the data behind an object after using Setxdata? Could it have something to do with the dictonary associated with the drawing? I am an experienced programmer of nearly 30 years but fairly new to the AutoCAD api so I hope my questions make sense.

 

Thanks

 

 

 

0 Likes
Message 5 of 5

chiefbraincloud
Collaborator
Collaborator

Good to know.  I am a self taught programmer, only getting paid to do it since 2005, and have about 20 years experience with AutoCAD.

 

For what it's worth, your problem is strange to me, as I have been working with a particular program that I originally wrote in LSP in 2002, then in 2005, upgraded it to VBA and added some improvements, then in 2007 upgraded it to .NET. (more improvements).  I never had any problems with my Xdata when I made the translations.

 

The Xdata is stored right along with the rest of the entity's data in the database.  You can print it to the command line with a little LSP.  Paste this line to your command line and hit enter, then pick an object.

 

(setq e (car (entsel)) ent (entget e '("*")))

 

That will print the entity's data to the command line.  The Xdata is at the end in the -3 group.

 

example:

((-1 . <Entity name: -4022b9e8>)
 (0 . "INSERT")
 (330 . <Entity name: -402a6308>)
 (5 . "383")
 (100 . "AcDbEntity")
 (67 . 0)
 (410 . "Model")
 (8 . "0")
 (100 . "AcDbBlockReference")
 (66 . 1)
 (2 . "BLOCKNAME")
 (10 220.577 64.0514 24.0)
 (41 . 1.0)
 (42 . 1.0)
 (43 . 1.0)
 (50 . 0.275099)
 (70 . 0)
 (71 . 0)
 (44 . 0.0)
 (45 . 0.0)
 (210 0.0 0.0 1.0)
 (-3 ("AppName1" (1010 54.0 0.0 0.0))
     ("AppName2" (1005 . "36E") (1005 . "377") (1005 . "37D") (1005 . "3A9"))
 )
)

 

As it occurs to me that your info block may be invisible and therefore not selectable, (I did something like that before), you could do something like this:

 

(setq SS (ssget "X" '((0 . "INSERT") (2 . "MyCAD.Info"))) elst (acet-ss-to-list ss))
(foreach e elst (print (entget e '("*"))) (print))

 

And just so you know, the asterisk in the entget call says print all xdata.  You could put "MyCAD" in there and it would only print your Xdata (along with the regular entity data).

 

If you only want the XData to print, not the entity data, use (print (assoc -3 (entget e '("*"))))

Dave O.                                                                  Sig-Logos32.png
0 Likes