Программное создание поля.
В AutoCAD 2005 появился очень интересный объект - поле. Что это такое и с чем его едят, описывать не буду, все это есть в справке. Но вот про создание поля как-то не очень все понятно. Попробую заполнить этот пробел (может, и сам чего еще пойму ;))
Известно, что поле может располагаться в однострочном или многострочном тексте, в атрибуте, а также в ячейке таблицы. Короче, в любом текстоподобном примитиве.
Создадим в пространстве модели всего 3 примитива: отрезок, обычный однострочный текст и однострочник, хранящий в себе поле - длину отрезка. Запустим теперь код, который будет просто печатать в консоли значение текстовой строки и FieldCode:
1 2 3 4 5 6 7 8 9 10 | (defun test (/ ent) (setq ent (vlax-ename->vla-object (car (entsel)))) (princ (strcat "\nTextString : " (vla-get-textstring ent) "\nFieldCode : " (vla-fieldcode ent) ) ;_ end of strcat ) ;_ end of princ (princ) ) ;_ end of defun |
Простой текст | Поле |
_$ (test)
TextString : Простой текст |
_$ (test)
TextString : 10.2855 |
Казалось бы, все просто: в качестве текстовой строки надо просто задавать формулу поля, которая определяется как:
%<\AcObjProp Object(%<\_ObjId 'ObjectID объекта'>%).'Свойство объекта' 'Ключи форматирования'>
И все хорошо, пока не встает вопрос об использовании готового и отлаженного lisp'а в AutoCAD другой разрядности. Например, сделали код в 32-разрядной системе, а в 64-разрядном AutoCAD он работать не будет. Все дело именно в ObjectID объекта.
Спасибо Александру Ривилису, он привел решение:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ;;-------------------------------------------------------- ;; Функция получает строковое представление ObjectID ;; вне зависимости от того AutoCAD x86 или x64 ;; Источник: https://discussion.autodesk.com/forums/message.jspa?messageID=6172961 ;;-------------------------------------------------------- (defun get-objectid-x86-x64 (obj / util) (setq util (vla-get-utility (vla-get-activedocument (vlax-get-acad-object)))) (if (= (type obj) 'ename) (setq obj (vlax-ename->vla-object obj)) ) ;_ end of if (if (= (type obj) 'vla-object) (if (> (vl-string-search "x64" (getvar "platform")) 0) (vlax-invoke-method util "GetObjectIdString" obj :vlax-false) (rtos (vla-get-objectid obj) 2 0) ) ;_ end of if ) ;_ end of if ) ;_ end of defun |
Теперь для программного создания поля, отображающего, например, длину указанного отрезка, можно сделать такое:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | (vl-load-com) (defun c:insfld (/ adoc ent pt) (vla-startundomark (setq adoc (vla-get-activedocument (vlax-get-acad-object)))) (if (and (= (type (setq ent (vl-catch-all-apply (function (lambda () (vlax-ename->vla-object (car (entsel "\nУкажите отрезок, полилинию или сплайн <Отмена> : ") ) ;_ end of car ) ;_ end of vlax-ename->vla-object ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of setq ) ;_ end of type 'vla-object ) ;_ end of = (vlax-property-available-p ent 'length) (= (type (setq pt (vl-catch-all-apply (function (lambda () (getpoint "\nУкажите точку для простановки поля <Отмена> : ") ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of setq ) ;_ end of type 'list ) ;_ end of = pt ) ;_ end of and (vla-addtext (vla-objectidtoobject adoc (vla-get-ownerid ent) ) ;_ end of vla-ObjectIDToObject (strcat "%<\\AcObjProp Object(%<\\_ObjId " (vl-princ-to-string (get-objectid-x86-x64 ent)) ">%).Length \\f \\"%lu6\\">%" ) ;_ end of strcat (vlax-3d-point pt) 2.5 ) ;_ end of vla-addtext ) ;_ end of if (vla-endundomark adoc) (princ) ) ;_ end of defun |
Спасибо Александру
[cc lang="lisp"]
нужно поставить экранирующий обратный слеш (\) перед (") которая должна войти в строковую переменную "как есть", т.е. фрагмент строки ..."%lu6"... нужно заменить на ...\"%lu6\"...
Спасибо, исправил (кажется).