【问题标题】:How to insert a block with custom properties using AutoLISP?如何使用 AutoLISP 插入具有自定义属性的块?
【发布时间】:2019-09-19 05:26:30
【问题描述】:

我正在尝试插入具有自定义属性的块。如何设置这些变量?

在落叶块中有一个名为“可见性”的自定义属性,具有各种不同的样式(可见性 1、可见性 2、可见性 3,...)。

例如,我将如何插入具有可见性 3 的落叶块。

(DEFUN C:TREE ( / DECIDUOUS CONIFER SHRUBMEDIUM SHRUBSMALL)
  (INITGET 1 "DECIDUOUS CONIFER SHRUBMEDIUM SHRUBSMALL")
  (OR
    (SETQ RETKWORD (GETKWORD "\nSpecify tree type: [DECIDUOUS/CONIFER/SHRUBMEDIUM/SHRUBSMALL]:"))
    (SETQ RETKWORD "DECIDUOUS")
    )
  (IF (= RETKWORD "DECIDUOUS")
    (PROGN
      (SETQ OLDLAYER (GETVAR "CLAYER"))
      (SETQ FLAG (TBLSEARCH "LAYER" "L-PLNT-DECD"))
      (IF FLAG
    (SETVAR "CLAYER" "L-PLNT-DECD")
    )
      (INITGET 1 "Visibility1 Visibility2 Visibility3")
      (OR
    (SETQ CMDKWORD (GETKWORD "\nPick a command: [Visibility1/Visibility2/Visibility3]:"))
    )
      (IF (= CMDKWORD "Visibility3")
    (PROGN
      (COMMAND "INSERT"
           "TT-L-TREE-DECIDUOUS"
           )
      )
    )
      (PRINC)
      )
    )
  )

【问题讨论】:

    标签: lisp autocad autolisp


    【解决方案1】:

    这个问题的答案最终取决于您是否需要 AutoCAD INSERT 命令提供的插入块参照的视觉预览

    由于标准 AutoCAD INSERT 命令在插入块期间不会提示输入动态块参数值,因此您需要插入块,然后使用插入的动态块参照的 ActiveX 属性和方法来操作可见性状态,具体来说,使用getdynamicblockproperties 方法。


    如果不需要插入块的视觉预览...

    ...那么您可以完全放弃INSERT 命令,而使用目标容器对象(模型空间/图纸空间/块定义)的insertblock 方法,该方法将返回块引用vla-object。

    这是一个基本示例,演示如何使用insertblock 方法:

    (defun c:test ( / dwg ins )
        (if
            (and
                (setq dwg (getfiled "Select Block" "" "dwg" 16))
                (setq ins (getpoint "\nSpecify insertion point: "))
            )
            (vla-insertblock
                (vlax-get-property
                    (vla-get-activedocument (vlax-get-acad-object))
                    (if (= 1 (getvar 'cvport))
                        'paperspace
                        'modelspace
                    )
                )
                (vlax-3D-point (trans ins 1 0))
                dwg
                1.0 1.0 1.0 0.0
            )
        )
        (princ)
    )
    (vl-load-com) (princ)
    

    此方法将返回一个块引用 vla-object,然后您可以使用 getdynamicblockproperties 方法返回的动态块属性数组来操作其动态块属性。

    由于您特别希望修改可见性状态,您可能希望考虑我在dynamic block library 中开发的以下一组函数来修改提供的块引用对象的可见性状态:

    ;; Set Dynamic Block Visibility State  -  Lee Mac
    ;; Sets the Visibility Parameter of a Dynamic Block (if present) to a specific value (if allowed)
    ;; blk - [vla] VLA Dynamic Block Reference object
    ;; val - [str] Visibility State Parameter value
    ;; Returns: [str] New value of Visibility Parameter, else nil
    
    (defun LM:SetVisibilityState ( blk val / vis )
        (if
            (and
                (setq vis (LM:getvisibilityparametername blk))
                (member (strcase val) (mapcar 'strcase (LM:getdynpropallowedvalues blk vis)))
            )
            (LM:setdynpropvalue blk vis val)
        )
    )
    
    ;; Get Visibility Parameter Name  -  Lee Mac
    ;; Returns the name of the Visibility Parameter of a Dynamic Block (if present)
    ;; blk - [vla] VLA Dynamic Block Reference object
    ;; Returns: [str] Name of Visibility Parameter, else nil
    
    (defun LM:getvisibilityparametername ( blk / vis )  
        (if
            (and
                (vlax-property-available-p blk 'effectivename)
                (setq blk
                    (vla-item
                        (vla-get-blocks (vla-get-document blk))
                        (vla-get-effectivename blk)
                    )
                )
                (= :vlax-true (vla-get-isdynamicblock blk))
                (= :vlax-true (vla-get-hasextensiondictionary blk))
                (setq vis
                    (vl-some
                       '(lambda ( pair )
                            (if
                                (and
                                    (= 360 (car pair))
                                    (= "BLOCKVISIBILITYPARAMETER" (cdr (assoc 0 (entget (cdr pair)))))
                                )
                                (cdr pair)
                            )
                        )
                        (dictsearch
                            (vlax-vla-object->ename (vla-getextensiondictionary blk))
                            "ACAD_ENHANCEDBLOCK"
                        )
                    )
                )
            )
            (cdr (assoc 301 (entget vis)))
        )
    )
    
    ;; Get Dynamic Block Property Allowed Values  -  Lee Mac
    ;; Returns the allowed values for a specific Dynamic Block property.
    ;; blk - [vla] VLA Dynamic Block Reference object
    ;; prp - [str] Dynamic Block property name (case-insensitive)
    ;; Returns: [lst] List of allowed values for property, else nil if no restrictions
    
    (defun LM:getdynpropallowedvalues ( blk prp )
        (setq prp (strcase prp))
        (vl-some '(lambda ( x ) (if (= prp (strcase (vla-get-propertyname x))) (vlax-get x 'allowedvalues)))
            (vlax-invoke blk 'getdynamicblockproperties)
        )
    )
    
    ;; Set Dynamic Block Property Value  -  Lee Mac
    ;; Modifies the value of a Dynamic Block property (if present)
    ;; blk - [vla] VLA Dynamic Block Reference object
    ;; prp - [str] Dynamic Block property name (case-insensitive)
    ;; val - [any] New value for property
    ;; Returns: [any] New value if successful, else nil
    
    (defun LM:setdynpropvalue ( blk prp val )
        (setq prp (strcase prp))
        (vl-some
           '(lambda ( x )
                (if (= prp (strcase (vla-get-propertyname x)))
                    (progn
                        (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
                        (cond (val) (t))
                    )
                )
            )
            (vlax-invoke blk 'getdynamicblockproperties)
        )
    )
    

    您可以通过以下方式调用我之前提供的示例中的上述函数(当然,更改可见性状态的名称以适合您的块):

    (defun c:test ( / dwg ins )
        (if
            (and
                (setq dwg (getfiled "Select Block" "" "dwg" 16))
                (setq ins (getpoint "\nSpecify insertion point: "))
            )
            (LM:SetVisibilityState
                (vla-insertblock
                    (vlax-get-property
                        (vla-get-activedocument (vlax-get-acad-object))
                        (if (= 1 (getvar 'cvport))
                            'paperspace
                            'modelspace
                        )
                    )
                    (vlax-3D-point (trans ins 1 0))
                    dwg
                    1.0 1.0 1.0 0.0
                )
                "YourVisibilityState"
            )
        )
        (princ)
    )
    (vl-load-com) (princ)
    

    如果需要插入块的视觉预览...

    ...然后,除了使用grread 循环滚动您自己版本的标准INSERT 命令(还需要模仿所有绘图辅助工具,例如Object SnapOrthomode),您需要使用INSERT 命令。

    但是,由于块的可见性状态只能在在插入块引用之后更改,因此向用户显示的视觉预览将是不准确的。

    为了两全其美,我之前提出了以下可能的解决方案(以及发布的随附功能here):

    ;; Example demonstrating a method to insert a Dynamic Block with a Visibility State already set.
    ;; Lee Mac  -  2013-12-24
    
    (defun c:test ( / *error* att blk def doc ent new obj par spc tmp vis )
    
        (defun *error* ( msg )
            (if (= 'int (type att))
                (setvar 'attreq att)
            )
            (foreach obj (list new def)
                (if (and (= 'vla-object (type obj)) (not (vlax-erased-p obj)))
                    (vl-catch-all-apply 'vla-delete (list obj))
                )
            )
            (if (not (wcmatch (strcase msg t) "*break,*cancel*,*exit*"))
                (princ (strcat "\nError: " msg))
            )
            (princ)
        )
        
        (cond
            (   (= 4 (logand 4 (cdr (assoc 70 (tblsearch "layer" (getvar 'clayer))))))
                (princ "\nCurrent layer locked.")
            )
            (   (null (setq blk (getfiled "Select Dynamic Block with Visibility States" "" "dwg" 16)))
                (princ "\n*Cancel*")
            )
            (   (progn
                    (setq doc (vla-get-activedocument (vlax-get-acad-object))
                          spc (vlax-get-property doc (if (= 1 (getvar 'cvport)) 'paperspace 'modelspace))
                          obj (vlax-invoke spc 'insertblock '(0.0 0.0 0.0) blk 1.0 1.0 1.0 0.0)
                    )
                    (vla-put-visible obj :vlax-false)
                    (= :vlax-false (vla-get-isdynamicblock obj))
                )
                (princ "\nSelected block is not dynamic.")
                (vla-delete obj)
            )
            (   (null (setq par (LM:getvisibilityparametername obj)))
                (princ "\nSelected block does not have a visibility parameter.")
                (vla-delete obj)
            )
            (   (null (setq vis (car (LM:listbox "Choose a Visibility State" (acad_strlsort (LM:getdynpropallowedvalues obj par)) 0))))
                (princ "\n*Cancel*")
                (vla-delete obj)
            )
            (   t
                (LM:setdynpropvalue obj par vis)
                (setq tmp 0)
                (while (tblsearch "block" (setq blk (strcat "tmp" (itoa (setq tmp (1+ tmp)))))))
                (vla-put-visible
                    (car
                        (vlax-invoke doc
                            'copyobjects
                            (list obj)
                            (setq def (vlax-invoke (vla-get-blocks doc) 'add '(0.0 0.0 0.0) blk))
                        )
                    )
                    :vlax-true
                )
                (vla-delete obj)
                (setq ent (entlast)
                      att (getvar 'attreq)
                )
                (setvar 'attreq 0)
                (if
                    (and
                        (vl-cmdf "_.-insert" blk "_S" 1.0 "_R" 0.0 "\\")
                        (not (eq ent (setq ent (entlast))))
                        (= "AcDbBlockReference" (vla-get-objectname (setq new (vlax-ename->vla-object ent))))
                    )
                    (progn
                        (vla-explode new)
                        (vla-delete  new)
                    )
                )
                (vl-catch-all-apply 'vla-delete (list def))
            )
        )
        (princ)
    )
    
    ;; Get Visibility Parameter Name  -  Lee Mac
    ;; Returns the name of the Visibility Parameter of a Dynamic Block (if present)
    ;; blk - [vla] VLA Dynamic Block Reference object
    ;; Returns: [str] Name of Visibility Parameter, else nil
    
    (defun LM:getvisibilityparametername ( blk / vis )  
        (if
            (and
                (vlax-property-available-p blk 'effectivename)
                (setq blk
                    (vla-item
                        (vla-get-blocks (vla-get-document blk))
                        (vla-get-effectivename blk)
                    )
                )
                (= :vlax-true (vla-get-isdynamicblock blk))
                (= :vlax-true (vla-get-hasextensiondictionary blk))
                (setq vis
                    (vl-some
                       '(lambda ( pair )
                            (if
                                (and
                                    (= 360 (car pair))
                                    (= "BLOCKVISIBILITYPARAMETER" (cdr (assoc 0 (entget (cdr pair)))))
                                )
                                (cdr pair)
                            )
                        )
                        (dictsearch
                            (vlax-vla-object->ename (vla-getextensiondictionary blk))
                            "acad_enhancedblock"
                        )
                    )
                )
            )
            (cdr (assoc 301 (entget vis)))
        )
    )
    
    ;; Get Dynamic Block Property Allowed Values  -  Lee Mac
    ;; Returns the allowed values for a specific Dynamic Block property.
    ;; blk - [vla] VLA Dynamic Block Reference object
    ;; prp - [str] Dynamic Block property name (case-insensitive)
    ;; Returns: [lst] List of allowed values for property, else nil if no restrictions
    
    (defun LM:getdynpropallowedvalues ( blk prp )
        (setq prp (strcase prp))
        (vl-some '(lambda ( x ) (if (= prp (strcase (vla-get-propertyname x))) (vlax-get x 'allowedvalues)))
            (vlax-invoke blk 'getdynamicblockproperties)
        )
    )
    
    ;; Set Dynamic Block Property Value  -  Lee Mac
    ;; Modifies the value of a Dynamic Block property (if present)
    ;; blk - [vla] VLA Dynamic Block Reference object
    ;; prp - [str] Dynamic Block property name (case-insensitive)
    ;; val - [any] New value for property
    ;; Returns: [any] New value if successful, else nil
    
    (defun LM:setdynpropvalue ( blk prp val )
        (setq prp (strcase prp))
        (vl-some
           '(lambda ( x )
                (if (= prp (strcase (vla-get-propertyname x)))
                    (progn
                        (vla-put-value x (vlax-make-variant val (vlax-variant-type (vla-get-value x))))
                        (cond (val) (t))
                    )
                )
            )
            (vlax-invoke blk 'getdynamicblockproperties)
        )
    )
    
    ;; List Box  -  Lee Mac
    ;; Displays a DCL list box allowing the user to make a selection from the supplied data.
    ;; msg - [str] Dialog label
    ;; lst - [lst] List of strings to display
    ;; bit - [int] 1=allow multiple; 2=return indexes
    ;; Returns: [lst] List of selected items/indexes, else nil
    
    (defun LM:listbox ( msg lst bit / dch des tmp rtn )
        (cond
            (   (not
                    (and
                        (setq tmp (vl-filename-mktemp nil nil ".dcl"))
                        (setq des (open tmp "w"))
                        (write-line
                            (strcat "listbox:dialog{label=\"" msg "\";spacer;:list_box{key=\"list\";multiple_select="
                                (if (= 1 (logand 1 bit)) "true" "false") ";width=50;height=15;}spacer;ok_cancel;}"
                            )
                            des
                        )
                        (not (close des))
                        (< 0 (setq dch (load_dialog tmp)))
                        (new_dialog "listbox" dch)
                    )
                )
                (prompt "\nError Loading List Box Dialog.")
            )
            (   t     
                (start_list "list")
                (foreach itm lst (add_list itm))
                (end_list)
                (setq rtn (set_tile "list" "0"))
                (action_tile "list" "(setq rtn $value)")
                (setq rtn
                    (if (= 1 (start_dialog))
                        (if (= 2 (logand 2 bit))
                            (read (strcat "(" rtn ")"))
                            (mapcar '(lambda ( x ) (nth x lst)) (read (strcat "(" rtn ")")))
                        )
                    )
                )
            )
        )
        (if (< 0 dch)
            (unload_dialog dch)
        )
        (if (and tmp (setq tmp (findfile tmp)))
            (vl-file-delete tmp)
        )
        rtn
    )
    (vl-load-com) (princ)
    

    我的解决方案主要涉及临时插入块引用,适当配置可见性状态,创建包含配置的动态块的临时块定义,然后利用标准 INSERT 命令提供的视觉预览插入临时块引用,然后将其从绘图中分解并清除。

    【讨论】:

      【解决方案2】:

      具有自定义属性的块称为动态块。 详情及样品可以找here

      附言 谢谢@LeeMac

      【讨论】:

      • 谢谢!过去几个小时我一直在尝试解决这个问题,但尝试设置 Visibility 参数时仍然遇到很多麻烦。你能帮助指导我下一步可能做什么吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-09
      • 2022-07-07
      • 2012-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-10
      相关资源
      最近更新 更多