下面我将从基本用法、高级技巧、最佳实践和常见问题四个方面,详细讲解如何在LISP中调用CAD命令。

基本用法:command 函数
command 函数是LISP与CAD进行交互式操作的主要桥梁,它的基本语法是:
(command "命令名" "选项" "点1" "点2" ... "回车")
工作原理:
- 参数类型:
command函数的参数必须是字符串类型。 - 参数传递:LISP将字符串参数按顺序传递给CAD的命令行。
- 命令执行:CAD接收到这些参数后,就像你在命令行手动输入一样,依次执行命令的各个步骤。
- 回车键:当命令需要确认或结束一个输入步骤时,LISP需要传递一个空字符串 来模拟按回车键,这是最关键也最容易出错的地方。
简单示例:画一条直线
(defun c:DrawLine () (command "._line" "0,0" "100,100" "") ; 画一条从(0,0)到(100,100)的直线 (princ) ; 静默退出,防止返回函数名 )
代码解释:
(defun c:DrawLine ...): 定义一个名为DrawLine的LISP函数,c:前缀使其成为一个可以直接在CAD命令行输入的命令。(command "._line" "0,0" "100,100" ""):"._line":调用LINE命令。_前缀可以确保调用的是英文版命令,这对于在不同语言版本的CAD中保持兼容性非常重要。"0,0":指定直线的起点。"100,100":指定直线的终点。- 模拟按回车,结束
LINE命令。
(princ):这是一个好习惯,它返回nil并且在CAD命令行上不打印任何东西,使得调用该LISP命令后,命令行保持干净。
高级技巧与常用模式
在实际应用中,我们很少使用固定的坐标,而是需要动态获取数据,如用户输入、选择对象、获取系统变量等。
获取用户输入(点、距离、角度等)
使用 getpoint, getdist, getangle 等函数获取用户输入,然后传递给 command。

示例:让用户指定起点和终点画线
(defun c:DrawLine2 ()
(setq p1 (getpoint "\n请指定起点: ")) ; 获取一个点
(if p1 ; 如果用户确实指定了一个点
(progn
(setq p2 (getpoint p1 "\n请指定终点: ")) ; 获取第二个点,并显示橡皮筋线
(command "._line" p1 p2 "") ; 使用变量画线
)
)
(princ)
)
代码解释:
(getpoint ...): 暂停程序,等待用户在屏幕上拾取一个点或输入坐标。(setq p1 ...): 将用户拾取的点存储到变量p1中。(if p1 ...): 检查用户是否按了ESC键取消。p1为nil,则if判断为假,跳过后续代码。(getpoint p1 ...): 传递一个点作为基点,CAD会从该点出发显示一条橡皮筋线,帮助用户预览。(progn ...): 当if的条件为真时,progn会将其中的多个表达式作为一个整体来执行。
处理对象选择
使用 ssget 函数让用户选择对象,然后将选择集传递给需要对象的命令(如 ERASE, MOVE)。
示例:删除用户选择的对象

(defun c:MyErase ()
(setq sset (ssget '((0 . "CIRCLE,LINE")))) ; 选择所有圆和直线
(if sset
(command "._erase" sset "") ; 将选择集传递给ERASE命令
)
(princ)
)
代码解释:
(ssget ...): 暂停程序,让用户选择对象。ssget:不带参数,让用户自由选择。ssget '((0 . "CIRCLE,LINE")):使用过滤列表只选择图层为0且类型为圆或直线的对象。0是DXF组码,代表对象类型。
(if sset ...): 检查用户是否选择了对象(即sset不为nil)。(command "._erase" sset ""): 将选择集sset作为ERASE命令的参数,然后按回车执行。
处理透明命令和嵌套命令
一些命令需要在其他命令执行过程中使用,ZOOM (缩放) 或 PAN (平移),这些被称为透明命令。
在LISP中,调用透明命令需要在命令名前加一个单引号 。
示例:在画线过程中进行缩放
(defun c:DrawLineWithZoom ()
(command "._line")
(while (= 1 (getvar "CMDACTIVE")) ; 检查LINE命令是否仍在活动状态
(if (= (car (grread)) 11) ; 如果用户在屏幕上移动鼠标
(progn
(command "._zoom" 'W) ; 调用透明命令 'ZOOM Window
(princ "\n指定缩放窗口的第一个角点.")
(command (cadr (grread))) ; 获取窗口的第一个角点
(princ "\n指定缩放窗口的第二个角点.")
(command (cadr (grread))) ; 获取窗口的第二个角点
(command "") ; 结束ZOOM命令
)
)
)
(princ)
)
注意:这个例子比较复杂,展示了
grread函数的用法,更常见的做法是直接使用ZOOM命令,或者在主命令开始前让用户先缩放视图。
使用系统变量
可以使用 setvar 和 getvar 函数来读取和设置CAD的系统变量,这些变量会影响 command 的行为。
示例:临时关闭对象捕捉,画一条线,然后恢复
(defun c:DrawLineWithoutOsnap () (setq old_osmode (getvar "OSMODE")) ; 保存当前的OSMODE值 (setvar "OSMODE" 0) ; 关闭所有对象捕捉 (command "._line" "0,0" "10,10" "") ; 现在画线不会捕捉到任何东西 (setvar "OSMODE" old_osmode) ; 恢复原来的对象捕捉设置 (princ) )
最佳实践与注意事项
- 始终使用
princ结束函数:(princ)是LISP函数的“礼仪”,可以防止在命令行打印不必要的返回值,保持界面整洁。 - 使用
_前缀:为了代码的国际化,请始终在命令前加上下划线 或_,如"_line"或".line",这可以强制CAD使用英文命令,避免在不同语言版本的CAD中出错。 - 检查返回值:对于
getpoint,ssget,getvar等函数,它们的返回值可能是nil(当用户取消操作时),使用if或when来检查返回值,可以防止程序因nil值而出错。 - 避免过度依赖
command:- 优点:简单直观,可以快速实现几乎所有手动能做的操作。
- 缺点:速度相对较慢,与CAD的数据库交互不直接,程序运行时无法中断(除非按ESC),且无法获取命令执行后的详细信息(如创建的对象ID)。
- 替代方案:ActiveX/VLISP:对于更复杂、更高效的应用,建议使用 Visual LISP (VLISP) 的ActiveX功能,它可以直接操作CAD的数据库,速度更快,更稳定,功能更强大。
ActiveX示例(对比 command 画线):
;; 使用ActiveX/VLISP画线,效率更高,且能获得对象
(defun c:DrawLineWithActiveX ()
(setq p1 (getpoint "\n起点: "))
(setq p2 (getpoint p1 "\n终点: "))
(if (and p1 p2)
(vla-addLine
(vla-get-ModelSpace (vla-get-ActiveDocument (vlax-get-acad-object))) ; 获取当前文档的模型空间
(vlax-3d-point p1) ; 将LISP点列表转换为ActiveX点
(vlax-3d-point p2)
)
)
(princ)
)
可以看到,ActiveX方式不依赖 command,而是直接在CAD内部创建几何对象,性能和可控性都更好。
常见问题
Q: 为什么我的LISP运行后,CAD命令行提示“未知命令”?
A: 最常见的原因是 command 函数中的参数不是字符串。(command line "0,0" "10,10") 是错误的,line 必须写成 "line"。
Q: 为什么我的LISP画完线后,命令行还卡在 LINE 命令?
A: 几乎可以肯定是你忘记在最后加一个空字符串 来模拟回车,检查你的 command 调用,确保它以
Q: 如何在LISP中调用带“/”选项的命令,如 CIRCLE 的 2P (两点) 选项?
A: 将选项也作为字符串传递,并在选项和后续参数之间加一个空字符串 。
示例:使用 2P 选项画圆
(defun c:Circle2P ()
(setq p1 (getpoint "\n指定圆直径的第一个端点: "))
(setq p2 (getpoint p1 "\n指定圆直径的第二个端点: "))
(if (and p1 p2)
(command "._circle" "_2P" p1 p2 "") ; 注意 "_2P" 和 p1, p2 之间的 ""
)
(princ)
)
注意:对于带
_前缀的命令,其子选项通常也加_,如"_2P"。
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
command 函数 |
简单、直观,与手动操作模式一致 | 速度慢,无法中断,无法直接获取对象信息,依赖命令行状态 | 快速编写脚本、自动化重复性手动操作、学习LISP的入门方法 |
| ActiveX/VLISP | 速度快,稳定,可中断,能直接操作对象和数据,功能强大 | 语法相对复杂,需要理解对象模型 | 开发专业、高效、复杂的CAD应用程序和插件 |
对于初学者和大多数日常任务,熟练掌握 command 函数是必不可少的,当你需要更高级的功能时,再深入学习 ActiveX/VLISP。
