Author Topic: Entity IDs and .NET Languages  (Read 1143 times)

DrollTroll

  • Kindly Curmudgeon
  • Administrator
  • *****
  • Posts: 4091
Entity IDs and .NET Languages
« on: June 11, 2013, 09:41:04 AM »
VB 6 had no 64-bit integer, so we chose to pass entity ids (which are 64-bit integers) to COM programs as a CURRENCY type of Variant. However, .NET no longer has a CURRENCY type; the incoming currency values are simply objects, and are implicitly converted to a DECIMAL type instead. When these values are passed directly back to DesignCAD, they may not be interpreted correctly -- trailing zeros are dropped, causing DesignCAD to use the wrong entity id in, for example, SelectByID.
For example, a Currency value of .0004 (which has a 64-bit integer value of 4) will be converted back and forth ok. However, a Currency value of .0010 (64-bit integer value of 10), converts correctly to a DECIMAL value of .0010, but when passed back to DesignCAD it somehow becomes .0001 (64-bit value of 1, not 10). Similarly, 20 becomes 2, 30 becomes 3, 110 becomes 11.

Fortunately there's a fairly simple workaround. Use the Decimal.ToOACurrency(object_id) to convert the decimal back to the appropriate currency value.

VB2005 example:

Code: [Select]
DcSel.SelectByID(object_id) ' may select wrong object due to conversion
DcSel.SelectByID(Decimal.ToOACurrency(object_id)) ' selects correct object

2016 marks my 24th year in DesignCAD-Land!

DrollTroll

  • Kindly Curmudgeon
  • Administrator
  • *****
  • Posts: 4091
Re: Entity IDs and .NET Languages
« Reply #1 on: July 28, 2014, 10:24:15 AM »
For convenient reference, I'll repeat a post I made in a different thread:

Here's a simple "one-button project" to demonstrate the Decimal vs. Currency problem. The subroutine  draws 100 lines. It then tries to use GetEntityByID using the original returned entity id, and that same id converted to OACurrency. If both ids were equivalent, it'd get the same object every time, but it fails about 10% of the time. The attached image shows what happens at the tenth entity. It's entity id should be 10 (or as a currency value, 0.0010) but when obtained using the Draw command's returned, unconverted ID, GetEntityByID returns entity id 1 (currency 0.0001).

Imagine then that you're trying to use GetEntityByID with the wrong, unconverted value in a frequently-edited drawing. If you've been creating and deleting objects during the drawing's lifetime, using the unconverted Draw() return value in GetEntityByID or SelectByID or similar methods may point to an entity that no longer exists, thus giving you a NULL or NOTHING entity. Even if it does successfully retrieve SOME object, there's a chance it could retrieve the WRONG object.

Moral of this story: For DotNet, always convert your returned entity ids to LONG values using Decimal.ToOACurrency, and use these converted values to pass back to your *ByID methods.

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        ' This project demonstrates that the value returned by the Draw() functions must be converted
        ' to OACurrency before passing back to DesignCAD via GetEntityByID or SelectByID, or other
        ' methods that require an entity id as an object.


        Dim DcApp As DesignCAD.Application
        Dim DcDocs As DesignCAD.Documents
        Dim DcDoc As DesignCAD.Document
        Dim DcPts As DesignCAD.CmdPoints
        Dim DcCurve As DesignCAD.Curve
        Dim DcEnts As DesignCAD.Entities
        Dim DcEnt1 As DesignCAD.Entity
        Dim DcEnt2 As DesignCAD.Entity
        Dim RID As Decimal 'ID returned from Draw(). DotNet sees DesignCAD's currency values as Decimal instead. So type it explicitly.
        Dim EID As Long ' We will convert the Decimal entity ID to a 64-bit integer Entity ID (essentially the same as Currency)

        On Error Resume Next
        DcApp = GetObject(, "DesignCAD.Application")
        If DcApp Is Nothing Then
            DcApp = New DesignCAD.Application
        End If
        If DcApp Is Nothing Then
            MessageBox.Show("Can't connect to DesignCAD. Exiting...")
            Close()
            Exit Sub
        End If
        DcDocs = DcApp.Documents
        DcDoc = DcDocs.Add
        DcCurve = DcDoc.Curve
        DcPts = DcDoc.CmdPoints
        Dim i As Integer
        For i = 0 To 100
            DcPts.SetCommandPoint(0.0, 5.0 * i, 0.0)
            DcPts.SetCommandPoint(5.0, 5.0 * i + 2.0, 0.0)
            DcPts.SetCommandPoint(10.0, 5.0 * i, 0.0)
            RID = DcCurve.Draw ' seen as a Decimal value by DotNet, not a Currency value
            EID = Decimal.ToOACurrency(RID) ' convert it to an actual Currency value
            DcEnts = DcDoc.Entities
            Err.Clear()
            DcEnt1 = DcEnts.GetEntityByID(EID) 'try getting the entity by the corrected ID
            If Err.Number <> 0 Then
                Me.BringToFront()
                MessageBox.Show("Error 0x" & Hex(Err.Number) & ": " & Err.Description & " while attempting to retrieve entity id " & EID.ToString())
                Err.Clear()
                Continue For
            End If
            DcEnt2 = DcEnts.GetEntityByID(RID) 'try getting the entity by the Decimal ID -- sometimes it's right, sometimes it's wrong
            If Err.Number <> 0 Then
                Me.BringToFront()
                MessageBox.Show("Error 0x" & Hex(Err.Number) & ": " & Err.Description & " while attempting to retrieve entity id " & RID.ToString())
                Err.Clear()
                Continue For
            End If
            If DcEnt1.EntityID <> DcEnt2.EntityID Then
                Me.BringToFront()
                MessageBox.Show("Mismatched entity ids -- EID entity=" & DcEnt1.EntityID.ToString() & ", RID entity=" & DcEnt2.EntityID.ToString())
            End If
        Next
        DcEnt1 = Nothing
        DcEnt2 = Nothing
        DcEnts = Nothing
        DcPts = Nothing
        DcCurve = Nothing
        DcDoc = Nothing
        DcDocs = Nothing
        DcApp = Nothing
        Close()
    End Sub
« Last Edit: July 28, 2014, 10:26:03 AM by DrollTroll »
2016 marks my 24th year in DesignCAD-Land!