ayunger 发表于 2009-2-19 13:47:00

[建议]【再论VLisp中关于对象捕捉编程问题】

本帖最后由 作者 于 2009-2-19 13:55:36 编辑 <br /><br /> <p><font face="楷体_GB2312" size="4"><strong>&nbsp;&nbsp;&nbsp; 众所周知,在AutoCAD的Lisp程序开发中,最多的使用函数为(command ....),<br/>正式因为这个函数给了在AutoCAD应用领域的非程序员开发者令人振奋的、极其便捷的、<br/>简明直观和高效率的编程实现,省去了Object Arx开发的繁琐。也是Lisp到Vlisp的整<br/>个成长历程中,有多少莘莘学子和热血青年,花费多少个日日夜夜,舍弃咖啡屋的浪漫、<br/>丢下月光下的温馨,陪伴它“Good Good Study,Day Day Up”,也就才拥有了我们各<br/>方论坛中的繁荣昌盛的今天。然而,Lisp编程中,绘制对象时关闭对象捕捉</strong></font><font face="楷体_GB2312" size="4"><strong>和程序出错</strong></font></p><p><font face="楷体_GB2312" size="4"><strong>/系</strong></font><font face="楷体_GB2312" size="4"><strong>统取消引起的错误处理问题也是困扰多年的老话题了。常规程序片段如下:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (setq oldOsmode (getvar "osMode"))<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (setvar "osMode" 0)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (command "_.Line" Pt1 Pt2 "")<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (setvar "osMode" oldOsmode)<br/>&nbsp;&nbsp;&nbsp; 这段程序可以看出,为防止绘制对象(如: Line)是因捕捉未关闭而造成CAD绘制直线<br/>对象时产生错误,而进行了在绘制直线前,先关闭捕捉,再绘制直线,然后恢复捕捉设置<br/>的方法。当然对于这段程序的设计思路和编制首先是没有问题的,同时常规测试运行也正<br/>确。然而实际操作中,因在autoCAD命令行按Esc键等终止后,且采用(defun *error())<br/>函数无法捕捉到错误的情况下,上面的程序就会大相径庭了:程序运行之前的捕捉设置丢<br/>失了!<br/>&nbsp;&nbsp;&nbsp; 如何解决这个问题呢,各家论坛上曾介绍了不少关于错误信息捕获(defun *error())<br/>函数的加强编程,但是对于捕捉丢失的问题收效甚微。下面来看看伟大的AutoCAD帮州文件<br/>中关于【OSMODE 系统变量】是如何介绍的:<br/>&nbsp;&nbsp;&nbsp;&nbsp; 【OSMODE 系统变量】<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;类型:整数<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;保存位置:注册表<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;初始值:4133<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;使用以下位码设置“对象捕捉”的运行模式:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp; NON(无)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp; END(端点)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp; MID(中点)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp; CEN(圆心)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp; NOD(节点)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;16&nbsp; QUA(象限点)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;32&nbsp; INT(交点)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;64&nbsp; INS(插入点)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;128&nbsp; PER(垂足)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;256&nbsp; TAN(切点)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;512&nbsp; NEA(最近点)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1024&nbsp; QUI(快速)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2048&nbsp; APP(外观交点)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4096&nbsp; EXT(尺寸线)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8192&nbsp; PAR(平行)<br/>&nbsp;&nbsp;&nbsp; 要指定多个对象捕捉方式,请输入各个位码值之和。例如,输入 3 指定“端点”( 位<br/>码1)和“中点”(位码 2)对象捕捉。输入 16383 指定全部对象捕捉方式。<br/>&nbsp;&nbsp;&nbsp;<font color="#1111ee"> 使用状态行的“对象捕捉”按钮关闭对象捕捉模式,除了返回 OSMODE 的普通值,还将<br/>返回位码16384(0x4000)。这个附加值有助于开发人员编写 AutoCAD 应用程序并将此模式与<br/>“绘图设置”对话框关闭的对象捕捉模式区别开来。设置此位码值将关闭对象捕捉。在该位<br/>码值关闭时将OSMODE设置为其他值可以打开对象捕捉。<br/></font>&nbsp;&nbsp;&nbsp; 请注意仔细阅读“使用状态行的....”这段。其中这个返回码:16384,应该引起程序员<br/>的非常重视!简而言之:在(getvar "osMode")值加上16384,就等于用鼠标单击命令行下方<br/>的[捕捉对象]按钮,例如: <br/>&nbsp;&nbsp;&nbsp; 若: osMode=3,即打开对象捕捉开关,且设置为“端点”和“中点”;<br/>&nbsp;&nbsp;&nbsp; 则: osMode=3+16384=16387,即关闭对象捕捉开关,而“端点”和“中点”仍然存在,<br/>仅仅是被屏蔽掉了。当再次设置: osMode=16387-16384=3 时捕捉对象被打开了,且为“端<br/>点+中点”模式。<br/>&nbsp;&nbsp;&nbsp; 综上所述,根据以上分析,则该段程序改写如下:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (setvar "osmode" (+ (rem (getvar "osmode") 16384) 16384));关闭捕捉.<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (command "_.Line" Pt1 Pt2 "")<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (setvar "osmode" (rem (getvar "osmode") 16384));打开捕捉.</strong></font></p><p><font face="楷体_GB2312" size="4"><strong>&nbsp;&nbsp;&nbsp; 编写为函数则,如下:<br/><font color="#e70808">&nbsp;;;;**************************<br/>&nbsp;;;; No.0 对象捕捉开关 函数&nbsp;&nbsp; <br/>&nbsp;;;;**************************<br/>&nbsp;(defun ayOSMode (isOpenSnap)<br/>&nbsp;&nbsp; (if isOpenSnap<br/>&nbsp;&nbsp;&nbsp;&nbsp; (setvar "osmode" (rem (getvar "osmode") 16384));打开捕捉.<br/>&nbsp;&nbsp;&nbsp;&nbsp; (setvar "osmode" (+ (rem (getvar "osmode") 16384) 16384));关闭捕捉.<br/>&nbsp;&nbsp; );end_if<br/>&nbsp;);end_defun<br/></font>&nbsp;&nbsp;&nbsp; 则上述程序段则改写为:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (ayOSMode nil);关闭捕捉.<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (command "_.Line" Pt1 Pt2 "")<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; ......<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;((ayOSMode T);打开捕捉.</strong></font></p><p><font face="楷体_GB2312" size="4"><strong>&nbsp;&nbsp;&nbsp; 【解释说明】如上的对象捕捉设置函数,和采用(setvar "osMode" 0)后恢复到原来的设置值有何不同<br/>呢?<br/>&nbsp;&nbsp;&nbsp; 1、函数(defun ayOSMode ...)没有显示的设置对象捕捉为: osMode=0,仅仅是加上系统提供的16384值,<br/>暂时屏蔽了对象捕捉,等同于用鼠标单击命令行下方的[捕捉对象]按钮关闭对象捕捉,没有重新设置对象捕捉<br/>码数值。<br/>&nbsp;&nbsp;&nbsp; 2、无论系统中发生什么错误/取消/终止,即便是程序中(defun *error())函数捕捉不到的错误信息也好,<br/>系统任然能够隐式保留对象捕捉设置值,仅仅是像[捕捉对象]按钮被用鼠标单击后关闭一样而已。<br/>&nbsp;&nbsp;&nbsp; 3、能够和AutoCAD系统中提供的命令一样,对象捕捉总是保存最近用户设置过的设置码,因而完成了程序<br/>员开发的程序和AuotCAD系统命令一样,在对象捕捉控制方面相同的效果。</strong></font></p><p><font face="楷体_GB2312" size="4"><strong></strong></font></p><p><font face="楷体_GB2312" size="4"><strong></strong></font></p><p><font face="楷体_GB2312" size="4"><strong></strong></font></p><p><font face="楷体_GB2312" size="4"><strong></strong></font></p><p><font face="楷体_GB2312" size="4"><strong></strong></font></p><p><font face="楷体_GB2312" size="4"><strong></strong></font></p><p><font face="楷体_GB2312"><br/><font size="4"><strong></strong></font></font></p>

luowy 发表于 2009-2-19 15:43:00

呀,真想不到还有这东西存在,lisp实在,魅力无穷呀

TANER 发表于 2009-2-19 15:52:00

(defun set-osmode (flag)<br/>&nbsp; (setvar "OSMODE" (boole (cond<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (flag 2)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (7)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ) (getvar "OSMODE") 16384<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br/>&nbsp; )<br/>)

caoyin 发表于 2009-2-19 17:02:00

<p>我觉得这样比较实用:</p><p>(command "line" <font color="#ff3300">"_non"</font> pt1 <font color="#ff0000">"_non"</font> pt1 "")</p><p>省去了osmode的设置</p>

xieling888 发表于 2012-4-25 08:53:17

受用,,确实以前不知道,,现在明白了。。多谢楼上的!

ggdlove 发表于 2013-12-16 11:17:51

受用了,这是一个好建议。谢谢分享

混沌初开 发表于 2013-12-16 21:54:52

楼主好强大!
页: [1]
查看完整版本: [建议]【再论VLisp中关于对象捕捉编程问题】