Author Topic: Aligning attributes in a blocks  (Read 8606 times)

0 Members and 1 Guest are viewing this topic.

cannorth

  • Guest
Aligning attributes in a blocks
« on: May 06, 2011, 11:42:39 AM »
Hello,

  I'd like to know how to set the alignment for the attribute in a block.  In COM, you use to be able to do this by setting the Alignment property to something like Autodesk.AutoCAD.Interop.Common.AcAlignment.acAlignmentLeft.  How can this be accomplished in VB.Net ObjectARX?  I'm trying to align the text in an attribute subentity of a block.

Thanks,

cannorth

kaefer

  • Guest
Re: Aligning attributes in a blocks
« Reply #1 on: May 06, 2011, 01:20:44 PM »
  I'd like to know how to set the alignment for the attribute in a block.  In COM, you use to be able to do this by setting the Alignment property to something like Autodesk.AutoCAD.Interop.Common.AcAlignment.acAlignmentLeft.  How can this be accomplished in VB.Net ObjectARX?  I'm trying to align the text in an attribute subentity of a block.

Your port of call is the DatabaseServices namespace, specifically the Justify property of the DBText class and the AttachmentPoint enumeration.

Minimal F# sample (I know, you asked for VB, but I don't know)
Code: [Select]
[<CommandMethod("JUST")>]
let just() =
       
    let doc = acApp.DocumentManager.MdiActiveDocument
    let ed = doc.Editor
    let db = doc.Database

    let pner =
        new PromptNestedEntityOptions("Select Text or Attribute")
        |> ed.GetNestedEntity
    if pner.Status = PromptStatus.OK then
        use tr = db.TransactionManager.StartTransaction()
        match tr.GetObject(pner.ObjectId, OpenMode.ForWrite) with
        | :? MText as mt ->
            mt.Attachment <- AttachmentPoint.TopLeft
        | :? DBText as dt ->
            dt.Justify <- AttachmentPoint.TopLeft
            dt.AlignmentPoint <- dt.Position
        | _ -> ()

        tr.Commit()

cannorth

  • Guest
Re: Aligning attributes in a blocks
« Reply #2 on: May 09, 2011, 11:34:39 AM »
Hi,

  Thanks for the response.  This is what I've written in VB.Net;

 
Code: [Select]
            Dim cur_doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = cur_doc.Database
            Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = db.TransactionManager
            Dim ed As Autodesk.AutoCAD.EditorInput.Editor
            Dim filList() As TypedValue = {New TypedValue(DxfCode.BlockName, "RWLabel")}
            Dim cur_filter = New Autodesk.AutoCAD.EditorInput.SelectionFilter(filList)
            Dim id As ObjectId, ent1 As Autodesk.AutoCAD.DatabaseServices.BlockReference
            Dim attrib As AttributeReference, attribdef As AttributeDefinition
            Dim bt As BlockTable


            Using docLock As DocumentLock = cur_doc.LockDocument
                Using trans As Transaction = tm.StartTransaction

                    bt = trans.GetObject(cur_doc.Database.BlockTableId,Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead)

                   
                    Dim bd As BlockTableRecord = tm.GetObject(bt("RWLabel"), Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite)

                    For Each adId As ObjectId In bd
                        Dim adObj As DBObject = trans.GetObject(adId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite)

                        ' For each attribute definition we find...

                        If TypeOf adObj Is AttributeDefinition Then
                            attribdef = adObj

                            If Not attribdef Is Nothing Then
                                If newjust = "ML" Then
                                    Dim pos As New Autodesk.AutoCAD.Geometry.Point3d(attribdef.Position.X, attribdef.Position.Y, attribdef.Position.Z)

                                    attribdef.Justify = AttachmentPoint.BaseLeft
                                    attribdef.AlignmentPoint = pos
                                Else
                                    Dim pos As New Autodesk.AutoCAD.Geometry.Point3d(attribdef.Position.X, attribdef.Position.Y, attribdef.Position.Z)

                                    attribdef.Justify = AttachmentPoint.BaseRight
                                    attribdef.AlignmentPoint = attribdef.Position
                                End If
                            End If
                        End If
                    Next

  The problem with this code is when it tries to set the ALignmentPoint.  I get the error: eNotApplicable.

cannorth

kaefer

  • Guest
Re: Aligning attributes in a blocks
« Reply #3 on: May 09, 2011, 01:11:58 PM »
  The problem with this code is when it tries to set the ALignmentPoint.  I get the error: eNotApplicable.

Uh, sorry for that. You need to set the AlignmentPoint only when Justify isn't AttachmentPoint.BaseLeft. That's basically the same story as in Lisp or VBA.

Besides, there is another issue with setting the AlignmentPoint to Position: It ensures only that the DBText stays in the general vicinity as before. I'm lost for a more precise calculation, for example, like the JUSTIFYTEXT command does.

Cheers

cannorth

  • Guest
Re: Aligning attributes in a blocks
« Reply #4 on: May 09, 2011, 04:15:17 PM »
Hi,

  Thanks for the help.  My code runs, but it still doesn't align the text.  Your example shows how to do it when the block is selected by the user.  My question is how it could be done with a block existing in the drawing without a user selecting it.  I think there is some bug with my code, but I'm not sure what it could be.

Thanks,

cannorth

kaefer

  • Guest
Re: Aligning attributes in a blocks
« Reply #5 on: May 10, 2011, 04:10:44 AM »
My code runs, but it still doesn't align the text.

Are you committing the transaction?

cannorth

  • Guest
Re: Aligning attributes in a blocks
« Reply #6 on: May 10, 2011, 10:14:31 AM »
I added:
                    trans.Commit()
                    ed.Regen()
before the end using statement and it still doesn't work.  This is what my code looks like now:

Code: [Select]
   
            Dim cur_doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = cur_doc.Database
            Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = db.TransactionManager
            Dim ed As Autodesk.AutoCAD.EditorInput.Editor = cur_doc.Editor
            Dim filList() As TypedValue = {New TypedValue(DxfCode.BlockName, "RWLabel")}
            Dim cur_filter = New Autodesk.AutoCAD.EditorInput.SelectionFilter(filList)
            Dim id As ObjectId, ent1 As Autodesk.AutoCAD.DatabaseServices.BlockReference
            Dim attrib As AttributeReference, attribdef As AttributeDefinition
            Dim bt As BlockTable


            Using docLock As DocumentLock = cur_doc.LockDocument
                Using trans As Transaction = tm.StartTransaction
                    bt = trans.GetObject(cur_doc.Database.BlockTableId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead)

                    '                    ent1 = tm.GetObject(id, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite, True)

                    '                   For i = 0 To (ent1.AttributeCollection.Count - 1)


                    Dim bd As BlockTableRecord = tm.GetObject(bt("RWLabel"), Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite)

                    For Each adId As ObjectId In bd
                        Dim adObj As DBObject = trans.GetObject(adId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite)

                        ' For each attribute definition we find...

                        If TypeOf adObj Is AttributeDefinition Then
                            attribdef = adObj

                            If Not attribdef Is Nothing Then
                                If newjust = "ML" Then
                                    Dim pos As New Autodesk.AutoCAD.Geometry.Point3d(attribdef.Position.X, attribdef.Position.Y, attribdef.Position.Z)

                                    attribdef.Justify = AttachmentPoint.BaseLeft
                                    '   attribdef.AlignmentPoint = pos
                                Else
                                    Dim pos As New Autodesk.AutoCAD.Geometry.Point3d(attribdef.Position.X, attribdef.Position.Y, attribdef.Position.Z)

                                    attribdef.Justify = AttachmentPoint.BaseRight
                                    '  attribdef.AlignmentPoint = attribdef.Position
                                End If
                            End If
                        End If
                    Next

                    trans.Commit()
                    ed.Regen()
                End Using
            End Using

mohnston

  • Bull Frog
  • Posts: 305
  • CAD Programmer
Re: Aligning attributes in a blocks
« Reply #7 on: May 10, 2011, 11:21:23 AM »
Attribute alignment is tricky.
Here is a link to a blog article on the subject (sort of)
http://through-the-interface.typepad.com/through_the_interface/2007/07/updating-a-sp-1.html
It's in C# but the idea is the same.
Look at "Update 2" at the bottom of the article.
Quote
if your attributes are anything other than left-justified, you will need to make a call to AdjustAlignment on the attribute reference after editing it.

There's a trick to this: you need to make sure the working database is set to the drawing you're working on, as well as passing it as an argument to the function.

Another post that addresses the same issue is
http://through-the-interface.typepad.com/through_the_interface/2009/03/jigging-an-autocad-block-with-attributes-using-net.html

Like I said, tricky.

It's amazing what you can do when you don't know what you can't do.
CAD Programming Solutions

kaefer

  • Guest
Re: Aligning attributes in a blocks
« Reply #8 on: May 10, 2011, 12:56:44 PM »
Code: [Select]
                        If TypeOf adObj Is AttributeDefinition Then
                            attribdef = adObj

Are you quite sure that your code does nothing? Hint: Changing the AttributeDefinition won't change the AttributeReferences of the blocks already inserted into the drawing.

http://through-the-interface.typepad.com/through_the_interface/2007/07/updating-a-sp-1.html
Quote
if your attributes are anything other than left-justified, you will need to make a call to AdjustAlignment on the attribute reference after editing it.

I'd say, it wouldn't hurt, but isn't really applicable, since you're still required to set the AlignmentPoint to a sensible value. As per arxmgd.chm:
Quote
This method allows a way to cause the text to be adjusted on non-database resident text entities or text entities within transactions.