lisp - 设置和重置系统变量 - AutoCAD LISP

标签 lisp autocad autocad-plugin autolisp

我正在尝试在 AutoCAD 中非常轻松地绘制接线图,除了我的预编程按钮外,几乎不需要按下任何按钮。

一个涉及 LISP,它不能很好地处理设置系统变量,然后将它们重置为以前的状态。该程序似乎执行了预期的功能,但没有达到预期的结果。

一旦我的 PLINE 命令启动,变量就会被重置。我需要 PLINE 来开始、结束,然后重置变量。

我已经尝试在 LISP 的命令中设置 OrthoMode 和 SnapMode,以及通过 (setvar (getvar ...)) 命令。

(defun varget ()
    (setq lis '("orthomode" "snapmode"))
    (setq var (mapcar 'getvar lis))
    (setq var1 '(1 1))
    (setq no 0)
    (repeat (length lis)
        (setvar (nth no lis) (nth no var1))
        (setq no (1+ no))
    )
    (princ)
 )

(defun varset ()
    (setq no 0)
    (repeat (length lis)
        (setvar (nth no lis) (nth no var))
        (setq no (1+ no))
    )
(princ)
)

(princ)

(defun C:wire ()
(progn
(varget)
(setq prevlayer (getvar "clayer"))
(setq P (getstring "Audio(A)/Video(V)/Comm(CO)/Coax(R)/Control(C)/(N)etwork/(P)ower:"))
(IF (= P "V")(command "-LAYER" "M" "VIDEO" "C" "150" "" "" "PLINE" PAUSE))
(IF (= P "A")(command "-LAYER" "M" "AUDIO" "C" "94" "" "" "PLINE" PAUSE))
(IF (= P "CO")(command "-LAYER" "M" "COMM" "C" "206" "" "" "PLINE" PAUSE))
(IF (= P "R")(command "-LAYER" "M" "COAX" "C" "44" "" "" "PLINE" PAUSE))
(IF (= P "C")(command "-LAYER" "M" "CONTROL" "C" "10" "" "" "PLINE" PAUSE))
(IF (= P "N")(command "-LAYER" "M" "NETWORK" "C" "210" "" "" "PLINE" PAUSE))
(IF (= P "P")(command "-LAYER" "M" "POWER" "C" "7" "" "" "PLINE" PAUSE))
(setvar "clayer" prevlayer)
(varset)
(princ)
);Progn
);defun

没有错误信息。

我希望在执行 PLINE 命令后 重置变量。

最佳答案

您的代码的问题在于,您只是在尝试重置系统变量和完成程序评估之前暂停单个用户输入。

相反,在继续程序评估之前,您将需要使用循环不断暂停以等待用户输入。

例如:

;; Define function, declare local symbols
(defun c:wire ( / col lay opt val var )

    ;; System variables to be modified within the program
    (setq var '(clayer orthomode snapmode cmdecho)
    ;; Retrieve current sys var values
          val  (mapcar 'getvar var)                
    ) ;; end setq

    ;; Predefine the getkword options
    (initget "Audio Video COmm R Control Network Power")
    ;; Prompt the user for input, default to "Audio" on null input
    (setq opt (cond ((getkword "\n[Audio/Video/COmm/Coax(R)/Control/Network/Power] <Audio>: ")) ("Audio")))

    ;; Define the layer & colour based on the option returned
    (cond
        (   (= opt "Audio")   (setq lay "AUDIO"    col  94))
        (   (= opt "Video")   (setq lay "VIDEO"    col 150))
        (   (= opt "COmm")    (setq lay "COMM"     col 206))
        (   (= opt "R")       (setq lay "COAX"     col  44))
        (   (= opt "Control") (setq lay "CONTROL"  col  10))
        (   (= opt "Network") (setq lay "NETWORK"  col 210))
        (   (= opt "Power")   (setq lay "POWER"    col   7))
    ) ;; end cond

    ;; Suppress command-line output for the -LAYER command
    (setvar 'cmdecho 0)
    ;; Create & set the layer & layer colour
    (command "_.-layer" "_M" lay "_C" col "" "")

    ;; Set everything except the first sys var
    (mapcar 'setvar (cdr var) '(1 1 1))
    ;; Initiate the PLINE command
    (command "_.pline")
    ;; Continuously pause for user input
    (while (= 1 (logand 1 (getvar 'cmdactive))) (command "\\"))

    ;; Reset system variables
    (mapcar 'setvar var val)

    ;; Suppress the value returned by the last evaluated expression
    (princ) 
) ;; end defun

注意几点:

  • 始终声明您的局部变量以避免与文档命名空间中的同名变量发生冲突。看我的教程here了解有关如何以及为何这样做的更多信息。

  • 使用 getkword代替 getstring控制和验证用户的输入。

  • 使用 "\\" 代替 pause 符号,因为 pause 符号是不 protected 全局变量,可以很容易在你的程序之外无意中被重新定义,导致你的程序中断。由于 pause 符号的计算结果为 "\\",因此您也可以使用文字反斜杠。

作为扩展,您可能还需要考虑实现一个本地错误处理程序来处理用户在程序评估期间不可避免地按下 Esc 的情况(否则系统变量在这种情况下不会被重置).我在教程 here 中描述了如何执行此操作.

这是一个基本示例,演示了包含本地错误处理程序:

;; Define function, declare local symbols
(defun c:wire ( / *error* col lay opt val var )

    ;; Define local error handler
    (defun *error* ( msg )
        ;; Reset system variables
        (mapcar 'setvar var val)
        ;; Suppress the output of standard cancellation messages
        (if (not (wcmatch (strcase msg t) "*break,*cancel*,*exit*"))
            ;; Print critical errors
            (princ (strcat "\nError: " msg))
        ) ;; end if
        (princ) ;; Suppress the value returned by the last evaluated expression
    ) ;; end defun

    ;; System variables to be modified within the program
    (setq var '(clayer orthomode snapmode cmdecho)
    ;; Retrieve current sys var values
          val  (mapcar 'getvar var)                
    ) ;; end setq

    ;; Predefine the getkword options
    (initget "Audio Video COmm R Control Network Power")
    ;; Prompt the user for input, default to "Audio" on null input
    (setq opt (cond ((getkword "\n[Audio/Video/COmm/Coax(R)/Control/Network/Power] <Audio>: ")) ("Audio")))

    ;; Define the layer & colour based on the option returned
    (cond
        (   (= opt "Audio")   (setq lay "AUDIO"    col  94))
        (   (= opt "Video")   (setq lay "VIDEO"    col 150))
        (   (= opt "COmm")    (setq lay "COMM"     col 206))
        (   (= opt "R")       (setq lay "COAX"     col  44))
        (   (= opt "Control") (setq lay "CONTROL"  col  10))
        (   (= opt "Network") (setq lay "NETWORK"  col 210))
        (   (= opt "Power")   (setq lay "POWER"    col   7))
    ) ;; end cond

    ;; Suppress command-line output for the -LAYER command
    (setvar 'cmdecho 0)
    ;; Create & set the layer & layer colour
    (command "_.-layer" "_M" lay "_C" col "" "")

    ;; Set everything except the first sys var
    (mapcar 'setvar (cdr var) '(1 1 1))
    ;; Initiate the PLINE command
    (command "_.pline")
    ;; Continuously pause for user input
    (while (= 1 (logand 1 (getvar 'cmdactive))) (command "\\"))

    ;; Reset system variables
    (mapcar 'setvar var val)

    ;; Suppress the value returned by the last evaluated expression
    (princ) 
) ;; end defun

关于lisp - 设置和重置系统变量 - AutoCAD LISP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56954725/

相关文章:

recursion - 用尾递归解决 "n-rooks"

lisp - AutoCAD 将文件另存为另一个路径中的同名副本 : "Object reference not set to an instance of an object"

excel - 将 Autocad/Maps 中的 block 导入 Excel

c# - 如何在 C# 中将列表中的项目添加到 AutoCAD 文件?

python - 元组解包类似于 Python,但在 Common Lisp 中

lisp - elisp 中的 Y 组合器

arrays - 从 Common Lisp 中的文本文件中读取数组

excel - 需要使用 VBA 从 AutoCAD 将值写入 Excel 工作表

c# - 提示用户选择一个组并获取该组 ID 的方法

c# - 如何通过 Lambda 表达式创建 AutoCAD 对象并返回它