Jump to content

Making Text Style Annotative


ksperopoulos

Recommended Posts

I am trying to find a way to create a text style that is annotative. When I do a vlax-dump-object on a style that is already annotative, there is nothing showing that as an Active X property. It also shows the annotative style as having an extension dictionary key value of 0. Where is this property stored?

Link to comment
Share on other sites

Why would Autodesk put the mleader style annotative setting as a property that is easily accessed by the vlax-put-property function and not make it that easy for text styles? How is one expected to learn this stuff if they put one thing in a particular place for one item and then puts the same thing in a different place for another item?:reallymad:

 

Thank you Lee! Maybe you should work for Autodesk and rewrite this stuff so it's a little more logical. You probably know more than they do about their product anyway. :notworthy:

Link to comment
Share on other sites

The annotative flag is set within the acadannotative xdata attached to the STYLE entity.

 

Thank you Lee. I got this return:

 

("AcadAnnotative" (1000 . "AnnotativeData") (1002 . "{") (1070 . 1) (1070 . 1) (1002 . "}"))

 

By process of elimination, I think it's safe to assume the annotative flag is dxf code 1070 - but which one? Is it both, first, or last?

 

Also, is there a way to do it with visual lisp? I have searched the help file and it seems text styles are able to retrieve and set the xdata. I think I would have to make a safe array before doing this though. Is that correct or do you have any experience with this method?

Link to comment
Share on other sites

Thank you Lee. I got this return:

 

("AcadAnnotative" (1000 . "AnnotativeData") (1002 . "{") (1070 . 1) (1070 . 1) (1002 . "}"))

By process of elimination, I think it's safe to assume the annotative flag is dxf code 1070 - but which one? Is it both, first, or last?

 

Also, is there a way to do it with visual lisp? I have searched the help file and it seems text styles are able to retrieve and set the xdata. I think I would have to make a safe array before doing this though. Is that correct or do you have any experience with this method?

 

See this thread for examples of how to determine whether a Text Style is annotative, with both Vanilla AutoLISP & Visual LISP examples. These examples show which item of xdata controls the annotative flag.

 

I hope this helps!

Link to comment
Share on other sites

It kind of does Lee. Just at a quick glance, I can definitely see the annotative flag is the second 1070 dxf code. Any ideas what the first one is for?

 

I can also see there is a lot more coding involved by going down the VL path.

 

When attempting the AutoLISP method, I think that I have successfully modified the entity's list and made (1070 . 0) , but when I try to update it, it reverts back to the original setting of (1070 . 1) - see below.

 

(setq ename (tblobjname "style" "MMC"))
[i]<Entity name: 7ff621807540>
[/i]
(setq elist (entget ename '("acadannotative")))
[i]((-1 . <Entity name: 7ff621807540>) (0 . "STYLE") (330 . <Entity name: 7ff621803830>) (5 . "2FBC") (100 . "AcDbSymbolTableRecord") (100 . "AcDbTextStyleTableRecord") (2 . "MMC") (70 . 0) (40 . 0.09375) (41 . 0.75) (50 . 0.0) (71 . 0) (42 . 0.09375) (3 . "simplex.shx") (4 . "") (-3 ("AcadAnnotative" (1000 . "AnnotativeData") (1002 . "{") (1070 . 1) (1070 . 1) (1002 . "}"))))
[/i]
(setq newelist (subst (list (list '-3 (subst (cons 1070 0) (cons 1070 1) (cadr (assoc -3 elist))))) (assoc -3 elist) elist))
[i]((-1 . <Entity name: 7ff621807540>) (0 . "STYLE") (330 . <Entity name: 7ff621803830>) (5 . "2FBC") (100 . "AcDbSymbolTableRecord") (100 . "AcDbTextStyleTableRecord") (2 . "MMC") (70 . 0) (40 . 0.09375) (41 . 0.75) (50 . 0.0) (71 . 0) (42 . 0.09375) (3 . "simplex.shx") (4 . "") ((-3 ("AcadAnnotative" (1000 . "AnnotativeData") (1002 . "{") (1070 . 0) (1070 . 0) (1002 . "}")))))[/i]

(entmod elist)
[i]((-1 . <Entity name: 7ff621807540>) (0 . "STYLE") (330 . <Entity name: 7ff621803830>) (5 . "2FBC") (100 . "AcDbSymbolTableRecord") (100 . "AcDbTextStyleTableRecord") (2 . "MMC") (70 . 0) (40 . 0.09375) (41 . 0.75) (50 . 0.0) (71 . 0) (42 . 0.09375) (3 . "simplex.shx") (4 . "") (-3 ("AcadAnnotative" (1000 . "AnnotativeData") (1002 . "{") (1070 . 1) (1070 . 1) (1002 . "}"))))[/i]

(entupd ename)
[i]nil[/i]

 

What am I doing wrong?

 

 

Nevermind - I found my mistake. I should have updated the entity with the new list instead of the old. So the code should look like this for the entmod function:

 

(entmod newelist)

Edited by ksperopoulos
Found my mistake.
Link to comment
Share on other sites

Any ideas what the first one is for?

 

I'm not sure; there is also no documentation as far as I am aware.

 

When attempting the AutoLISP method, I think that I have successfully modified the entity's list and made (1070 . 0) ...
(setq newelist (subst (list (list '-3 (subst (cons 1070 0) (cons 1070 1) (cadr (assoc -3 elist))))) (assoc -3 elist) elist))

 

Note that subst will substitute all occurrences of an item for another in a given list, therefore, your subst expression will substitute the values for both 1070 DXF groups. I don't know whether this will have unintended consequences in the long term, but nevetheless, I would always advise retaining the same data format as used by AutoCAD to avoid the potential for drawing corruption.

Link to comment
Share on other sites

Note that subst will substitute all occurrences of an item for another in a given list, therefore, your subst expression will substitute the values for both 1070 DXF groups. I don't know whether this will have unintended consequences in the long term, but nevetheless, I would always advise retaining the same data format as used by AutoCAD to avoid the potential for drawing corruption.

 

I knew that it would do that, but during my testing, I didn't see that it made any unwanted changes. So I was ok with it. But I went on to realize that the -3 DXF code does not exist with a non-annotative text style. Since the statement I am putting together is saying "if the text style doesn't exist, then create it", and the text style we always use is annotative, I ended up doing this instead:

 

    (if (vl-catch-all-error-p (vl-catch-all-apply 'vla-Item (list txtcoll txtname)))
       (progn
           (setq txtobj (vla-Add txtcoll txtname))
           (vla-SetFont txtobj "Arial Narrow" :vlax-false :vlax-false 0 34)
           (vla-put-Height txtobj 0.09375)
           (vla-put-ObliqueAngle txtobj 0.0)
           (vla-put-TextGenerationFlag txtobj 0)
           (vla-put-Width txtobj 1.0)
           (setq txtname (vlax-vla-object->ename txtobj)
                 txtlist (entget txtname '("AcadAnnotative"))
                annolist (list '(-3 ("AcadAnnotative" (1000 . "AnnotativeData") (1002 . "{") (1070 . 1) (1070 . 1) (1002 . "}"))))
                 newlist (append txtlist annolist)
           )
           (entmod newlist)
       )
   )

 

Two questions with this code though:

  1. Would there ever be a reason to include the regapp function in this?
  2. Why is it when I use the entmod function, the true type font is not recognized as one that already exists in the file?

TextStyleFont.png

Link to comment
Share on other sites

I ended up sticking with Visual LISP and using a safearray to attach the xdata. Everything works like it should now. Here is the code in case other run into the same issue:

 

    (setq oldtxt (vlax-variant-value (vla-GetVariable doc "textstyle"))
        txtcoll (vla-get-TextStyles doc)
        txtname "[i][color="red"]Your Text Style Name[/color][/i]"
   )
   (if (vl-catch-all-error-p (vl-catch-all-apply 'vla-Item (list txtcoll txtname)))
       (progn
           (setq txtobj (vla-Add txtcoll txtname))
           (vla-SetFont txtobj "Arial Narrow" :vlax-false :vlax-false 0 34)
           (vla-put-Height txtobj 0.09375)
           (vla-put-ObliqueAngle txtobj 0.0)
           (vla-put-TextGenerationFlag txtobj 0)
           (vla-put-Width txtobj 1.0)
           (setq xtype (vlax-make-safearray vlax-vbInteger '(0 . 5))
                 xdata (vlax-make-safearray vlax-vbVariant '(0 . 5))
           )
           (vlax-safearray-put-element xtype 0 1001)
           (vlax-safearray-put-element xdata 0 "AcadAnnotative")
           (vlax-safearray-put-element xtype 1 1000)
           (vlax-safearray-put-element xdata 1 "AnnotativeData")
           (vlax-safearray-put-element xtype 2 1002)
           (vlax-safearray-put-element xdata 2 "{")
           (vlax-safearray-put-element xtype 3 1070)
           (vlax-safearray-put-element xdata 3 1)
           (vlax-safearray-put-element xtype 4 1070)
           (vlax-safearray-put-element xdata 4 1)
           (vlax-safearray-put-element xtype 5 1002)
           (vlax-safearray-put-element xdata 5 "}")
           (vla-SetXData txtobj xtype xdata)
       )
   )

Link to comment
Share on other sites

  • 6 years later...
On 2/8/2016 at 8:44 AM, ksperopoulos said:

 

I knew that it would do that, but during my testing, I didn't see that it made any unwanted changes. So I was ok with it. But I went on to realize that the -3 DXF code does not exist with a non-annotative text style. Since the statement I am putting together is saying "if the text style doesn't exist, then create it", and the text style we always use is annotative, I ended up doing this instead:

 

 

    (if (vl-catch-all-error-p (vl-catch-all-apply 'vla-Item (list txtcoll txtname)))
       (progn
           (setq txtobj (vla-Add txtcoll txtname))
           (vla-SetFont txtobj "Arial Narrow" :vlax-false :vlax-false 0 34)
           (vla-put-Height txtobj 0.09375)
           (vla-put-ObliqueAngle txtobj 0.0)
           (vla-put-TextGenerationFlag txtobj 0)
           (vla-put-Width txtobj 1.0)
           (setq txtname (vlax-vla-object->ename txtobj)
                 txtlist (entget txtname '("AcadAnnotative"))
                annolist (list '(-3 ("AcadAnnotative" (1000 . "AnnotativeData") (1002 . "{") (1070 . 1) (1070 . 1) (1002 . "}"))))
                 newlist (append txtlist annolist)
           )
           (entmod newlist)
       )
   )
 

 

 

Two questions with this code though:

 

  1. Would there ever be a reason to include the regapp function in this?
  2. Why is it when I use the entmod function, the true type font is not recognized as one that already exists in the file?

 

TextStyleFont.png

 

I know this is old, but AutoCAD 2023 just updated the documentation to explain why the issue you are seeing is happening. You have to use vla-put-fontfile immediately after vla-setfont.

    (if (vl-catch-all-error-p (vl-catch-all-apply 'vla-Item (list txtcoll txtname)))
       (progn
           (setq txtobj (vla-Add txtcoll txtname))
           (vla-SetFont txtobj "Arial Narrow" :vlax-false :vlax-false 0 34)
		   (vla-put-fontfile txtobj Full_Font_Path);You have to use vla-put-fontfile immediately after using vla-setfont and you need the full windows path to the font file, for exampe: C:\\WinNT\\Fonts\\Arial.TTF

           (vla-put-Height txtobj 0.09375)
           (vla-put-ObliqueAngle txtobj 0.0)
           (vla-put-TextGenerationFlag txtobj 0)
           (vla-put-Width txtobj 1.0)
           (setq txtname (vlax-vla-object->ename txtobj)
                 txtlist (entget txtname '("AcadAnnotative"))
                annolist (list '(-3 ("AcadAnnotative" (1000 . "AnnotativeData") (1002 . "{") (1070 . 1) (1070 . 1) (1002 . "}"))))
                 newlist (append txtlist annolist)
           )
           (entmod newlist)
       )
   )

 

Above is your code modified, but you do need to get the full path to the font file, which can be a little tricky to do, so here is my full code:

(defun CW:CreateTextStyle (StyleName Font Annotative Height WidthFactor MakeActive / *ThisDrawing* *Styles* Obj DestinationTypeFace Font_Path xtype xdata TypeFace Bold Italic charSet PitchandFamily)
  ;Create Text Style
  ;2022-04-11 - Chris Wade - cmwade77 on cadtutor.net and theswamp.org
  (vl-load-com)  
  (setq *ThisDrawing* (vla-get-activedocument (vlax-get-acad-object))
        *Styles* (vla-get-textstyles *ThisDrawing*)
        Obj (vla-add *Styles* StyleName)
  )
  (if Obj
    (progn
      (if (= (strcase (vl-filename-extension Font)) (strcase ".ttf"))
        (progn
          (if (not (setq Font_Path (findfile (strcat (getenv "WINDIR") "\\fonts\\" Font))))
            (progn
              (setq Font_Path (findfile Font))
              (setq Font_Path (getfiled "Select Font File" "ttf"))
            )
          )          
        )
      )
      (if Font_Path        
        (setq DestinationTypeFace (vl-filename-base Font))        
        (progn
          (alert "Couldn't find font path, exiting!")
          (repeat 3
            (vla-purgeall *ThisDrawing*)
          )
          (exit)
        )
      )      
      (vla-GetFont Obj 'typeFace 'Bold 'Italic 'charSet 'PitchandFamily)      
      (vla-put-fontfile Obj Font_Path)
      (vla-SetFont Obj DestinationTypeFace Bold Italic charSet PitchandFamily)      
      (vla-put-height Obj Height)
      (vla-put-width Obj WidthFactor)
      (vla-put-ObliqueAngle Obj 0.0)
      (vla-put-TextGenerationFlag Obj 0)
      ;Code to make Annotative adapted from codw by ksperopoulos at https://www.cadtutor.net/forum/topic/59375-making-text-style-annotative/?do=findComment&comment=491676
      (if Annotative
        (progn
          (setq xtype (vlax-make-safearray vlax-vbInteger '(0 . 5))
                 xdata (vlax-make-safearray vlax-vbVariant '(0 . 5))
          )
          (vlax-safearray-put-element xtype 0 1001)
          (vlax-safearray-put-element xdata 0 "AcadAnnotative")
          (vlax-safearray-put-element xtype 1 1000)
          (vlax-safearray-put-element xdata 1 "AnnotativeData")
          (vlax-safearray-put-element xtype 2 1002)
          (vlax-safearray-put-element xdata 2 "{")
          (vlax-safearray-put-element xtype 3 1070)
          (vlax-safearray-put-element xdata 3 1)
          (vlax-safearray-put-element xtype 4 1070)
          (vlax-safearray-put-element xdata 4 1)
          (vlax-safearray-put-element xtype 5 1002)
          (vlax-safearray-put-element xdata 5 "}")
          (vla-SetXData Obj xtype xdata)
        )
      )
      (if MakeActive
        (vla-put-activetextstyle *ThisDrawing* Obj)
      )
    )
  )
  Obj
)

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...