[建议]【再论vlisp中关于对象捕捉编程问题】
www.dimcax.com
[建议]【再论vlisp中关于对象捕捉编程问题】
众所周知,在autocad的lisp程序开发中,最多的使用函数为(command ....),
正式因为这个函数给了在autocad应用领域的非程序员开发者令人振奋的、极其便捷的、
简明直观和高效率的编程实现,省去了object arx开发的繁琐。也是lisp到vlisp的整
个成长历程中,有多少莘莘学子和热血青年,花费多少个日日夜夜,舍弃咖啡屋的浪漫、
丢下月光下的温馨,陪伴它“good good study,day day up”,也就才拥有了我们各
方论坛中的繁荣昌盛的今天。然而,lisp编程中,绘制对象时关闭对象捕捉和程序出错
/系统取消引起的错误处理问题也是困扰多年的老话题了。常规程序片段如下:
(setq oldosmode (getvar "osmode"))
(setvar "osmode" 0)
(command "_.line" pt1 pt2 "")
......
(setvar "osmode" oldosmode)
这段程序可以看出,为防止绘制对象(如: line)是因捕捉未关闭而造成cad绘制直线
对象时产生错误,而进行了在绘制直线前,先关闭捕捉,再绘制直线,然后恢复捕捉设置
的方法。当然对于这段程序的设计思路和编制首先是没有问题的,同时常规测试运行也正
确。然而实际操作中,因在autocad命令行按esc键等终止后,且采用(defun *error())
函数无法捕捉到错误的情况下,上面的程序就会大相径庭了:程序运行之前的捕捉设置丢
失了!
如何解决这个问题呢,各家论坛上曾介绍了不少关于错误信息捕获(defun *error())
函数的加强编程,但是对于捕捉丢失的问题收效甚微。下面来看看伟大的autocad帮州文件
中关于【osmode 系统变量】是如何介绍的:
【osmode 系统变量】
类型:整数
保存位置:注册表
初始值:4133
使用以下位码设置“对象捕捉”的运行模式:
0 non(无)
1 end(端点)
2 mid(中点)
4 cen(圆心)
8 nod(节点)
16 qua(象限点)
32 int(交点)
64 ins(插入点)
128 per(垂足)
256 tan(切点)
512 nea(最近点)
1024 qui(快速)
2048 app(外观交点)
4096 ext(尺寸线)
8192 par(平行)
要指定多个对象捕捉方式,请输入各个位码值之和。例如,输入 3 指定“端点”( 位
码1)和“中点”(位码 2)对象捕捉。输入 16383 指定全部对象捕捉方式。
使用状态行的“对象捕捉”按钮关闭对象捕捉模式,除了返回 osmode 的普通值,还将
返回位码16384(0x4000)。这个附加值有助于开发人员编写 autocad 应用程序并将此模式与
“绘图设置”对话框关闭的对象捕捉模式区别开来。设置此位码值将关闭对象捕捉。在该位
码值关闭时将osmode设置为其他值可以打开对象捕捉。
请注意仔细阅读“使用状态行的....”这段。其中这个返回码:16384,应该引起程序员
的非常重视!简而言之:在(getvar "osmode")值加上16384,就等于用鼠标单击命令行下方
的[捕捉对象]按钮,例如:
若: osmode=3,即打开对象捕捉开关,且设置为“端点”和“中点”;
则: osmode=3+16384=16387,即关闭对象捕捉开关,而“端点”和“中点”仍然存在,
仅仅是被屏蔽掉了。当再次设置: osmode=16387-16384=3 时捕捉对象被打开了,且为“端
点+中点”模式。
综上所述,根据以上分析,则该段程序改写如下:
(setvar "osmode" (+ (rem (getvar "osmode") 16384) 16384));关闭捕捉.
(command "_.line" pt1 pt2 "")
......
(setvar "osmode" (rem (getvar "osmode") 16384));打开捕捉.
编写为函数则,如下:
;;;**************************
;;; no.0 对象捕捉开关 函数
;;;**************************
(defun ayosmode (isopensnap)
(if isopensnap
(setvar "osmode" (rem (getvar "osmode") 16384));打开捕捉.
(setvar "osmode" (+ (rem (getvar "osmode") 16384) 16384));关闭捕捉.
);end_if
);end_defun
则上述程序段则改写为:
(ayosmode nil);关闭捕捉.
(command "_.line" pt1 pt2 "")
......
((ayosmode t);打开捕捉.
【解释说明】如上的对象捕捉设置函数,和采用(setvar "osmode" 0)后恢复到原来的设置值有何不同
呢?
1、函数(defun ayosmode ...)没有显示的设置对象捕捉为: osmode=0,仅仅是加上系统提供的16384值,
暂时屏蔽了对象捕捉,等同于用鼠标单击命令行下方的[捕捉对象]按钮关闭对象捕捉,没有重新设置对象捕捉
码数值。
2、无论系统中发生什么错误/取消/终止,即便是程序中(defun *error())函数捕捉不到的错误信息也好,
系统任然能够隐式保留对象捕捉设置值,仅仅是像[捕捉对象]按钮被用鼠标单击后关闭一样而已。
3、能够和autocad系统中提供的命令一样,对象捕捉总是保存最近用户设置过的设置码,因而完成了程序
员开发的程序和auotcad系统命令一样,在对象捕捉控制方面相同的效果。
d
呀,真想不到还有这东西存在,lisp实在,魅力无穷呀
d
(defun set-osmode (flag)
(setvar "osmode" (boole (cond
(flag 2)
(7)
) (getvar "osmode") 16384
)
)
)
d
我觉得这样比较实用:
(command "line" "_non" pt1 "_non" pt1 "")
省去了osmode的设置
d