September
1st,
2011
工作中经常在 AutoCAD 中原位粘贴各种零碎图形,而且会用到许多个 AutoCAD(有时还开一个 CASS),在它们之间交换文件麻烦死了。我想 Windows 中有不少剪切板增强工具,如 ClipX Ditto 之类,都提供多个缓冲位置,可以同时存储不同的文本,按照需要粘贴。AutoCAD 为什么没个类似功能呢?最后我研究了一番 Lisp 做了个简单的多重剪切板工具。
原理很简单,是利用”写块”和”插入块”的功能。使用前需要先配置缓存路径,目前是 ”F:/temp/” ,可以改成你自己的。完后按 c1 就是将选中对象存到剪切板位置1,按 v1 将其粘贴回来。这个临时图形是存在硬盘的,所以能直接粘贴到另一个进程的 CAD 中。
因为刚接触 Lisp 很多知识不了解,用 cond 函数时被括号内求值顺序卡了半天,最后总算弄明白了……这段很2的注释就不删除了,不知还有没有人遇到类似的问题。
;传送当前选择的图形对象,用于在不同文档,不同版本CAD之间转移所选对象 ;按 x1 c3 v2... 使用 ; x1 = 所选图形剪贴到缓存位置1 ; c3 = 所选图形复制到缓存位置3 ; v2 = 从缓存位置2粘贴回来 ;让函数名直接表示参数,使操作按键尽可能减少 ;有更好的办法么? #unsolved (defun c:x1 () ( setq sss ( ssget)) (blocktransport "x" "1" sss)) (defun c:x2 () ( setq sss ( ssget)) (blocktransport "x" "2" sss)) (defun c:x3 () ( setq sss ( ssget)) (blocktransport "x" "3" sss)) (defun c:x4 () ( setq sss ( ssget)) (blocktransport "x" "4" sss)) (defun c:x5 () ( setq sss ( ssget)) (blocktransport "x" "5" sss)) (defun c:c1 () ( setq sss ( ssget)) (blocktransport "c" "1" sss)) (defun c:c2 () ( setq sss ( ssget)) (blocktransport "c" "2" sss)) (defun c:c3 () ( setq sss ( ssget)) (blocktransport "c" "3" sss)) (defun c:c4 () ( setq sss ( ssget)) (blocktransport "c" "4" sss)) (defun c:c5 () ( setq sss ( ssget)) (blocktransport "c" "5" sss)) (defun c:v1 () ( setq sss nil ) (blocktransport "v" "1" sss)) (defun c:v2 () ( setq sss nil ) (blocktransport "v" "2" sss)) (defun c:v3 () ( setq sss nil ) (blocktransport "v" "3" sss)) (defun c:v4 () ( setq sss nil ) (blocktransport "v" "4" sss)) (defun c:v5 () ( setq sss nil ) (blocktransport "v" "5" sss)) (defun blocktransport ( method num sss / p n fn info ) (setvar "filedia" 0 ) (setvar "cmdecho" 0 ) (setvar "insunits" 0 ) (setq p "f:/_temp_/") ;在这里配置缓存路径,使用斜杠(而不是反斜杠) (setq n "_slot_") ;缓存文件名称,起名应该尽量诡异 (setq fn (strcat p n num ".dwg")) (setq info "") ;成功后输出信息 (setq fn_rnd (strcat p "back_" ( rtos (getvar "cdate") 2 8 ) ".dwg")) ;这个 condition 明显是"点对"啊, ;为什么 (cond ( (= method "x") (bla...) (bla...) (bla...) ) 是对的 ;而 后面那一堆括起来 (cond ( (= method "x") ((bla...) (bla...) (bla...)) ) 是错的? ;发现 (cond ((= 1 1) (alert "22") )) 没问题 ;发现 (cond ((= 1 1) (alert "22") (alert "33"))) 也没问题 ;但括起来后面的那堆 (cond ((= 1 1) ((alert "22") (alert "33")))) 却会先弹窗 33 ,从右向左! ;这什么破玩意 ;发现((bla1) (bla2) (bla3)) 都是从右向左的 ;也不尽然 括起来后,下面那些 (alert "1") - (alert "4") 顺序是 2 3 4 1 ;不括起来,下面那些 (alert "1") - (alert "4") 顺序是 1 2 3 4 ;也就是说 括起来后,()中第一个被视为函数,所以先求实参了? ;先加个 list 就可以括起来了 (list () () () bla1 bla2 bla3 blabla) (cond ((= method "x") ;剪切图形 to slot (list ;使用 list 串联表 ;(alert "1") (cond ((findfile fn) (command "-wblock" fn "y" "" "0,0" sss "" )) ('t (command "-wblock" fn "" "0,0" sss "" )) ) ;(alert "2") (command "oops" ) ( command "-wblock" fn_rnd "" "0,0" sss "") ;备份唯一名称的图块 (setq info (strcat "*cut* to slot" num " done !")) ;(alert "3") ;(alert "4") ) ) ((= method "c") ;复制图形 to slot ;不使用 list 串联表,依次计算零散的分支 (cond ((findfile fn) (command "-wblock" fn "y" "" "0,0" sss "" )) ('t (command "-wblock" fn "" "0,0" sss "" )) ) (command "oops" ) ( command "-wblock" fn_rnd "" "0,0" sss "") ;备份唯一名称的图块 (command "oops" ) ;写块时会从原图清掉这些图形,需要还原回来 (setq info (strcat "*copy* to slot" num " done !")) ) ((= method "v") ;粘贴图形 from slot (command "_insert" fn "0,0" "1" "1" "0") (setq ss (entlast)) (command "_explode" ss) ;炸开图块 (command "-purge" "b" (strcat n num) "y" "y") ;清理掉这个块的定义 (setq info (strcat "*paste* slot" num " done !")) ) ) (setvar "cmdecho" 1 ) (setvar "filedia" 1 ) (prompt info ) )
完