目录
一、文件操作
1.1 选择文件
- 代码示例
;getfiled函数:对话框的名称,默认文件夹路径,过滤后缀名,flag(1是创建、4是选择) (getfiled "" "" "" 1) (getfiled "" "" "" 4) (setq filepath (getfiled "选择文件" "C:\\Users\\Administrator\\Desktop\\" "dwg" 4))
返回值:仅返回绝对路径的字符串,没做其他任何操作,需配合open函数使用
- 对话框效果
1.1 写文件
- 代码示例
(defun c:writefile() ;getfiled函数:对话框的名称,默认文件夹路径,过滤后缀名,flag(1是创建、4是选择) ;getfiled返回的是文件的绝对路径,是字符串 (setq filepath (getfiled "选择要预览的对话框所在的文件" "C:\\Users\\" "txt" 4)) ;返回文件的操作符 ;w:有则覆盖,没有则新建。a:有则追加,无则新建 (setq file (open filepath "w")) (write-line "0,0" file) (write-line "100,0" file) (close file) )
- 对话框选择
1.2 读文件
- 代码示例
(defun c:readfile() ;getfiled返回的是文件的绝对路径,是字符串 (setq filepath (getfiled "选择要预览的对话框所在的文件" "C:\\Users\\" "txt" 2)) ;返回文件的操作符 (setq file (open filepath "r")) ;操作文件操作符 (setq fdata (read-line file)) ;注意:这里演示可以把一个命令拆分成几块 (command "pline") (while fdata (command fdata) (setq fdata (rade-line file)) ) (command "") (close file) (print) )
- 对话框选择
1.3 查找文件、目录
1.3.1 函数说明
- 在搜索目录下检索并返回文件或目录全路径
; 查找已有系统级文件 命令: (findfile "dim.shx") "C:\\program files\\autodesk\\autocad 2014\\fonts\\dim.shx" ; 查找已有系统级目录 命令: (findfile "fonts") "C:\\Program Files\\Autodesk\\AutoCAD 2014\\fonts" ; 查找自己新建的配置或中间临时文件 命令: (findfile "配置文件.ini") "C:\\tangent\\tarcht20v6\\sys\\配置文件.ini"
搜索目录:
(getenv "ACAD")
,命令可查看,
功能:返回值可用于open函数调用
1.3.2 应用举例
- 代码示例
(defun C:demo () (setq path (getfiled "new" "1" "txt" 1)) ; 存在则追加,不存在则创建 (if (findfile path) (setq file (open path "a")) (setq file (open path "w")) ) (write-line "123" file) (close file) (princ) )
1.4 删除文件
- 代码示例
(defun c:demo () (setq filepath (getfiled "选择文件" "C:\\Users\\Administrator\\Desktop\\" "txt" 4 ) ) ; 删除成功返回T,否则返回nil,如只读,打开 (setq res (vl-file-delete filepath)) (princ) )
1.5 与Excel文件交互
-
代码示例
(defun c:demo () (setq str_list nil) ; 选择文件 (if (setq filepath (getfiled "选择文件" "C:\\Users\\Administrator\\Desktop\\" "csv" 4 ) ) (progn (setq file (open filepath "r")) ; 循环读取每一行并存储在表中 (while (setq str (read-line file)) (setq str_list (append str_list (list str))) ) (print str_list) ) (print "未选择文件") ) (princ) )
-
准备被读取文件:工作簿1.csv
-
csv文件用记事本打开
csv文件:即逗号分隔值(Comma-Separated Values)文件,是一种常见的数据交换格式,它以纯文本形式存储表格数据
-
输出
( "序号,项目,坐标,备注" "1,纽约帝国大厦,\"(1000,1000,0)\",炸了" "2,华盛顿白宫,\"(2000,2000,0)\",轰了" )
二、对话框DCL
- DCL:Dialog Control Language,对话框控制语言,后缀名dcl,定义对话框样式布局。
- 重点:一定别忘了
分号
,一定要用英文标点
2.1 初识对话框
- 显示效果
按确认:会在命令行输出“确认”,temp.lsp中定义
- temp.dcl
// 冒号后面为控件名字 // 对话框的名字:demo1_dcl demo1_dcl:dialog{ // 中括号内为属性 label="对话框名"; // 中括号内也可以包含空间 :text{ // 控件中的属性 label="对话框内容"; } // cad封装好的控件 ok_cancel; }
- temp.lsp(完全版,可以作为模版)
(defun C:demo1 () ;选择dcl对话框文件:一个对话框文件中可以包含多个对话框 (setq dlg_file (getfiled "选择要预览的对话框所在的文件" "C:\\Users\\" "dcl" 2)) (if (= dlg_file nil) (exit)) ;选择对话框文件中的demo1_dcl命名的对话框:有此提示时候输入demo1_dcl (setq dlg_name (getstring "\n输入对话框名称:")) (if (= dlg_name "") (exit)) ;加载dcl对话框文件:返回加载标识符,如果只有文件名,则搜索默认路径,见代码下注释 (setq dlg_id (load_dialog dlg_file)) ;加载失败退出 (if (< dlg_id 0) (exit)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;用于保存对话框操作状态 (setq std 0) ;创建对话框对象,此时还没显示对话框,可以向对话框中添加东西 (if (not (new_dialog dlg_name dlg_id))(exit)) ;此处有两个key值:accept,cancel,是系统封装的确定取消按钮控件的key名 ;确认是accept,取消是cancel ;done_dialog函数:结束当前对话框并指定一个结束码, ;通常用来判断用户点击了哪个控件 (action_tile "accept" "(done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") ;启动对话框:开始接受使用者输入,对话框获得控制权 (setq std (start_dialog)) ;卸载对话框:控制权还给cad主程序 (unload_dialog dlg_id) ;根据std做相应动作 (if (= std 1) (print "确定")) (if (= std 0) (print "取消")) (print) )
- 默认搜索路径:通过(getvar “acadprefix”)
C:\Users\Administrator\appdata\roaming\autodesk\autocad 2014\r19.1\chs\support;
C:\program files\autodesk\autocad 2014\support;
C:\program files\autodesk\autocad 2014\fonts;
C:\program files\autodesk\autocad 2014\help;
C:\program files\autodesk\autocad 2014\support\zh-cn;
C:\Program Files\Autodesk\AutoCAD 2014\drv;
- 默认搜索路径:通过(getvar “acadprefix”)
- temp.lsp(精简版)
(defun C:demo1 () (setq dlg_file "C:\\Users\\Administrator\\Desktop\\code\\temp.dcl") (setq std 0) (setq dlg_id (load_dialog dlg_file)) (new_dialog "demo1_dcl" dlg_id) (action_tile "accept" "(done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq std (start_dialog)) (unload_dialog dlg_id) (if (= std 1)(print "确定")) (if (= std 0)(print "取消")) (print) )
2.2 常用对话框界面
2.2.1 复选框、列表框
- temp.dcl
demo1_dcl:dialog{ label="带边框的单复选框"; // row控件中的元素都在一行 // boxed_row带边框的行 :row{ //带外边框的列 :boxed_column{ label="水果"; // 复选框 :toggle{ label="苹果"; } // value=1默认选中,预设值 :toggle{ label="香蕉"; value=1; } :toggle{ label="石榴"; } } // 清单选框 :list_box{ label="蔬菜"; // 直接换行分割 list="西红柿\n黄瓜\n金针菇"; // 默认选择第三个,从0开始 value=2; // 开启多选(按住shift),没有则是单选 multiple_select=true; } } ok_cancel; }
- 效果
加载:temp.lsp及调出对话框同2.1
- 列表框以lisp驱动
(defun C:demo1 () (setq dlg_id (load_dialog "D:\\code\\autolisp\\code\\temp.dcl" ) ) (if (< dlg_id 0) (exit) ) (if (not (new_dialog "demo1_dcl" dlg_id)) (exit) ) ;;; 重点是start~end之间的语句 (start_list "list1") ;;; add_list是系统函数,将表添加进控件里 (mapcar 'add_list (list "包菜" "土豆" "玉米")) ;;; 效果同上面一句话 ;;; (add_list "西红柿") ;;; (add_list "黄瓜") ;;; (add_list "西蓝花") (end_list) (action_tile "accept" " (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq std (start_dialog)) (unload_dialog dlg_id) (if (= std 1) (print "确认") ) (if (= std 0) (print "取消") ) (print) )
- 对应temp.dcl
demo1_dcl:dialog{ label="带边框的单复选框"; :row{ // 清单选框 :list_box{ key="list1"; width="10.8333"; height="8.333"; multiple_select=true; } } ok_cancel; }
2.2.2 下拉框
- temp.dcl
demo1_dcl:dialog{ label="带边框的单复选框"; spacer_1; :row{ :popup_list{ label="干果"; list="核桃\n夏威夷果\n杏仁"; // 默认选择第三个 value=2; // 右侧下拉框的宽度 edit_width=10; } } //加一个空行 spacer_1; ok_cancel; }
- 效果
2.2.3 文字输入框、单选点框
- temp.dcl
demo1_dcl:dialog{ label="对话框名"; :row{ // 带边框的列,排版用 :boxed_column{ label="坐标"; :edit_box{ // &后的字母会有下划线,对应键盘快捷键 label="&X 坐标:"; // 输入框宽度 edit_width=10; } } :boxed_radio_row{ label="性别"; :radio_button{ label="male"; } :radio_button{ label="female"; } :radio_button{ label="middle"; value=1; } } } ok_cancel; }
- 效果
2.2.4 action_tile函数
- 功能:将控件和处理函数进行绑定并传参
- temp.lsp
(defun C:demo () (setq dlg_id (load_dialog "D:\\code\\autolisp\\code\\temp.dcl")) (if (< dlg_id 0) (exit)) (if (not (new_dialog "demo_dcl" dlg_id)) (exit)) (start_list "list1") (mapcar 'add_list (list "包菜" "土豆" "玉米")) (end_list) ; action_tile函数:传三个参数,控件Key值,value值,触发原因(单击,双击) (action_tile "list1" "(getdata $key $value $reason)") (action_tile "accept" " (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq std (start_dialog)) (unload_dialog dlg_id) (if (= std 1) (print "确认")) (if (= std 0) (print "取消")) (princ) ) ; 回调函数:接收上面三个参数,也可以选择性接收 (defun getdata (key value reason) (print "***当前点击***") (print (list "key值:" key)) (print (list "value值:" value)) (print (list "reason值:" reason)) (princ "\n") )
- temp.dcl
demo_dcl:dialog{ label="带边框的单复选框"; :row{ :list_box{ key="list1"; width="10.8333"; height="8.333"; multiple_select=true; } } ok_cancel; }
- 输出
2.3 Lisp对dcl的驱动
- temp.lsp精简模式
(defun C:demo1 () (setq dlg_file "C:\\Users\\Administrator\\Desktop\\code\\temp.dcl") (setq std 0) ;加载对话框文件 (setq dlg_id (load_dialog dlg_file)) ;创建对话框对象,此时可以向里面加东西 (new_dialog "demo1_dcl" dlg_id) ;设置对应key值的value (setdata) ;设置对应两个按钮控件的回调函数,此处有两个 (action_tile "accept" "(getdata) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") ;显示对话框,同时控制权从cad主程序转给对话框 (setq std (start_dialog)) ;卸载对话框 (unload_dialog dlg_id) ;点确定做相应动作 (if (= std 1) (command "circle" (list x y) r) ) (if (= std 0) (print "取消") ) (command "zoom" "e") (print) ) ;获得控件对应key值的value:其是字符串 (defun getdata () (setq x (atof (get_tile "cir_x"))) (setq y (atof (get_tile "cir_y"))) (setq r (atof (get_tile "cir_r"))) ) ;设置控件对应key值的默认value:其是字符串 ;如果是radio等类型控件,则其value值是真假"0"、"1" ;如果是list等类型控件,则其value值是序号“0”、“1”、“2” (defun setdata () (set_tile "cir_x" "200.00") (set_tile "cir_y" "200.00") (set_tile "cir_r" "200.00") )
- temp.dcl
demo1_dcl:dialog{ label="对话框名"; :boxed_row{ label="画圆"; :edit_box{ label="&X 坐标:"; edit_width=10; // 设置控件的key值 key="cir_x"; } :edit_box{ label="&Y 坐标:"; edit_width=10; // 设置控件的key值 key="cir_y"; } :edit_box{ label="&R 半径:"; edit_width=10; // 设置控件的key值 key="cir_r"; } } ok_cancel; }
- 显示效果
2.4 对话框按钮实现拾取
-
效果图
-
temp.dcl
demo1_dcl:dialog{ label="绘制圆"; :column{ :edit_box{ label="&R 半径:"; edit_width=10; key="cir_r"; } :boxed_column{ label="中心"; :button{ label="拾取中心点"; key="but_cir"; } :edit_box{ label="&X 坐标:"; edit_width=10; key="cir_x"; } :edit_box{ label="&Y 坐标:"; edit_width=10; key="cir_y"; } } } spacer_1; ok_cancel; }
-
temp.lsp
(defun C:demo1 () (setq dlg_id (load_dialog "C:\\Users\\Administrator\\Desktop\\code\\temp.dcl" ) ) (if (< dlg_id 0) (exit)) ;为了使下面while启动,此处设置大于1的整型 (setq r 200 x 200 y 200 std 2) ;只要没点确认或取消,就一直循环 (while (> std 1) ;注意:每次循环都用相同的dcl文件创建一个新的对话框对象 (if (not (new_dialog "demo1_dcl" dlg_id))(exit)) ;设置控件value值 (setdata "cir_r" r "cir_x" x "cir_y" y) ;设置按钮动作,done_dialog函数可以关闭对话框 (action_tile "but_cir" "(getdata) (done_dialog 2)") (action_tile "accept" "(getdata) (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") ;上面三个的done_dialog函数可以关闭对话框并返回std (setq std (start_dialog)) (if (= std 2) (progn (initget 1) (setq p (getpoint "\n请选择圆心")) (setq x (car p) y (cadr p)) ) ) ) ;跳出循环,卸载对话框 (unload_dialog dlg_id) ;针对确定、取消做动作 (if (= std 1)(command "circle" (list x y) r)) (if (= std 0)(print "取消")) ;退出前做了一次缩放 (command "zoom" "e") (print) ) ;;;获取当前控件key值对应的value,并设置x y r:dcl-》lisp ;;;用于计算 (defun getdata () (setq x (atof (get_tile "cir_x"))) (setq y (atof (get_tile "cir_y"))) (setq r (atof (get_tile "cir_r"))) ) ;;;设置当前控件key值对应的value:lisp -》dcl ;;;用于展示 (defun setdata (key_r r1 key_x x1 key_y y1) (set_tile key_r (rtos r1 2 2)) (set_tile key_x (rtos x1 2 2)) (set_tile key_y (rtos y1 2 2)) )
2.5 对话框加载图片
2.5.1 幻灯片图片制作
- 步骤:
- 新建cad绘制想展示的图片
- 将cad窗口缩放到想在对话框展示的长宽比(否则图像真实展示时会偏)
- 命令行输入:
mslide
,make slide的意思,制作幻灯片,保存即可
- 图示
2.5.2 仅展示幻灯片
-
效果
-
temp.lsp
(defun C:demo1 () (setq dlg_id (load_dialog "C:\\Users\\Administrator\\Desktop\\code\\temp.dcl") ) (if (< dlg_id 0) (exit)) (if (not (new_dialog "demo1_dcl" dlg_id)) (exit)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;只有此区间新增 (start_image "img_1") (slide_image 0 -20 (dimx_tile "img_1")(dimy_tile "img_1") "C:\\Users\\Administrator\\Desktop\\code\\img_1.sld") (end_image) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (action_tile "accept" " (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq std (start_dialog)) (unload_dialog dlg_id) (if (= std 1) (print "确认")) (if (= std 0) (print "取消")) (print) )
-
temp.dcl
demo1_dcl:dialog{ label="image展示"; :row{ :column{ :image{ //先确定宽度,调整高度时不要同时调宽度 width=30; //通过调整高度,使图像显示在中间,需要一点点试 height=10; // 使背景色同主窗口 color=-2; key="img_1"; } } } ok_cancel; }
2.5.3 图片按钮
-
效果
-
temp.lsp
(defun C:demo1 () (setq dlg_id (load_dialog "D:\\code\\autolisp\\code\\temp.dcl" ) ) (if (< dlg_id 0) (exit)) (if (not (new_dialog "demo1_dcl" dlg_id)) (exit)) ; 给key为Picture1的控件绑定图片 (start_image "Picture1") ; 将背景色填充为黑色 (fill_image 0 0 (dimx_tile "Picture1") (dimy_tile "Picture1") 0) ; 给key为Picture1的控件绑定图片,同图片展示做法 (slide_image 0 0 (dimx_tile "Picture1") (dimy_tile "Picture1") "D:\\code\\autolisp\\code\\img_1.sld" ) (end_image) ; 给信号Picture1绑定处理函数printdata (action_tile "Picture1" "(printdata)") (action_tile "accept" " (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq std (start_dialog)) (unload_dialog dlg_id) (if (= std 1) (print "确认") ) (if (= std 0) (print "取消") ) (print) ) (defun printdata () (print "点击了图像按钮"))
-
temp.dcl
demo1_dcl:dialog{ label="图像按钮"; :boxed_column { label = "图像按钮"; :image_button { key = "Picture1"; width = 12.15; height = 7.275; } } ok_cancel; }
2.6 官方dcl范例
- 位置:
C:\Program Files\Autodesk\AutoCAD 2014\UserDataCache\zh-CN\Support
下的acad.dcl、base.dcl - acad.dcl 系统功能对话框
- temp.lsp
(defun C:demo () ; 系统acad.dcl别动,拷贝到桌面再测试 (setq dlg_id (load_dialog "C:\\Users\\Administrator\\Desktop\\acad.dcl")) (if (< dlg_id 0) (exit)) ; 只需要改写此处 (if (not (new_dialog "acad_snap" dlg_id)) (exit)) (action_tile "accept" " (done_dialog 1)") (action_tile "cancel" "(done_dialog 0)") (setq std (start_dialog)) (unload_dialog dlg_id) (if (= std 1) (print "确认")) (if (= std 0) (print "取消")) (print) )
- base.dcl 对话框零部件合集
2.7 lsp模板
-
效果(每次新开图中数据都是上次输入的值)
-
temp.dcl
demo_dcl:dialog{ label="绘制圆"; :column{ :edit_box{ label="&R 半径:"; edit_width=10; key="cir_r"; } :boxed_column{ label="中心"; :button{ label="拾取中心点"; key="but_cir"; } :edit_box{ label="&X 坐标:"; edit_width=10; key="cir_x"; } :edit_box{ label="&Y 坐标:"; edit_width=10; key="cir_y"; } } } spacer_1; ok_cancel; }
-
test.lsp
(defun C:demo (/ Dialog_Return dlg_id key keys cen_pt) ;;;初始变量设置区 (setq dlg_id (load_dialog "D:\\code\\autolisp\\code\\temp.dcl")) (if (< dlg_id 0) (exit) ) (setq Dialog_Return 2) (while (> Dialog_Return 1) ;;; 对话框初始化区 (if (not (new_dialog "demo_dcl" dlg_id)) (exit)) ;此三行第一次运行后会被foreach语句覆盖 (set_tile "cir_r" "100") (set_tile "cir_x" "100") (set_tile "cir_y" "100") ;;;全部控件的初始化 (setq keys (list "accept" "cancel" "cir_r" "but_cir" "cir_x" "cir_y") ) (foreach key keys ;如果后缀_bak变量有值,则给控件赋值,否则不动作 (if (eval (read (strcat key "_bak"))) (set_tile key (eval (read (strcat key "_bak")))) ) ;做控件和处理函数的绑定 (action_tile key "(Action_keys $key $value $reason)") ) ;;; 对话框初始化完成,开启对话框 (setq Dialog_Return (start_dialog)) ;;; 根据对话框的返回值进行相应响应 (Action_of_return_code Dialog_Return) ) (unload_dialog dlg_id) (Clear_data) (princ) ) ;;; 全部控件的点击动作触发 (defun Action_Keys (key value reason) (cond ((= key "accept") ;确认按钮 (Get_data) (done_dialog 1) ;对话框退出返回主函数,传递给Dialog_Return值为1 ) ((= key "cancel") ;取消按钮 (done_dialog 0) ;对话框退出返回主函数,传递给Dialog_Return值为0 ) ((= key "but_cir") ;but_cir控件 (Get_data) ;保存当前对话框内的控件值 (done_dialog 2) ;对话框退出返回主函数,传递给Dialog_Return值为2 ) ) ) ;;; 根据对话框的返回值进行相应响应 (defun Action_of_return_code (Dialog_Return) (cond ((= Dialog_Return 0) (print "取消") ) ((= Dialog_Return 1) (command "circle" (list (atof cir_x_bak) (atof cir_y_bak)) (atof cir_r_bak) ) (command "zoom" "e") (print "确认") ) ((= Dialog_Return 2) (initget 1) (setq cen_pt (getpoint)) ;此处_bak变量是主函数中eval函数生成的 (setq cir_x_bak (rtos (car cen_pt) 2 3)) (setq cir_y_bak (rtos (cadr cen_pt) 2 3)) ) ) (princ) ) ;;; 保存当前对话框内的控件值 (defun Get_data (/ key) (foreach key keys ; 例(set cir_x_bak (get_tile "cir_x")) (set (read (strcat key "_bak")) (get_tile key)) ) ) ;;; 清空当前对话框内的控件值(若注释set语句,只要cad没关,则保存上次数据) (defun Clear_data (/ key) (foreach key keys ; accept_bak、cir_x_bak、but_cir_bak等 (set (read (strcat key "_bak")) nil) ) )