[建议]【再论VLisp中关于对象捕捉编程问题】
本帖最后由 作者 于 2009-2-19 13:55:36 编辑 <br /><br /> <p><font face="楷体_GB2312" size="4"><strong> 众所周知,在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/> (setq oldOsmode (getvar "osMode"))<br/> (setvar "osMode" 0)<br/> (command "_.Line" Pt1 Pt2 "")<br/> ......<br/> (setvar "osMode" oldOsmode)<br/> 这段程序可以看出,为防止绘制对象(如: Line)是因捕捉未关闭而造成CAD绘制直线<br/>对象时产生错误,而进行了在绘制直线前,先关闭捕捉,再绘制直线,然后恢复捕捉设置<br/>的方法。当然对于这段程序的设计思路和编制首先是没有问题的,同时常规测试运行也正<br/>确。然而实际操作中,因在autoCAD命令行按Esc键等终止后,且采用(defun *error())<br/>函数无法捕捉到错误的情况下,上面的程序就会大相径庭了:程序运行之前的捕捉设置丢<br/>失了!<br/> 如何解决这个问题呢,各家论坛上曾介绍了不少关于错误信息捕获(defun *error())<br/>函数的加强编程,但是对于捕捉丢失的问题收效甚微。下面来看看伟大的AutoCAD帮州文件<br/>中关于【OSMODE 系统变量】是如何介绍的:<br/> 【OSMODE 系统变量】<br/> 类型:整数<br/> 保存位置:注册表<br/> 初始值:4133<br/> 使用以下位码设置“对象捕捉”的运行模式:<br/> 0 NON(无)<br/> 1 END(端点)<br/> 2 MID(中点)<br/> 4 CEN(圆心)<br/> 8 NOD(节点)<br/> 16 QUA(象限点)<br/> 32 INT(交点)<br/> 64 INS(插入点)<br/> 128 PER(垂足)<br/> 256 TAN(切点)<br/> 512 NEA(最近点)<br/> 1024 QUI(快速)<br/> 2048 APP(外观交点)<br/> 4096 EXT(尺寸线)<br/> 8192 PAR(平行)<br/> 要指定多个对象捕捉方式,请输入各个位码值之和。例如,输入 3 指定“端点”( 位<br/>码1)和“中点”(位码 2)对象捕捉。输入 16383 指定全部对象捕捉方式。<br/> <font color="#1111ee"> 使用状态行的“对象捕捉”按钮关闭对象捕捉模式,除了返回 OSMODE 的普通值,还将<br/>返回位码16384(0x4000)。这个附加值有助于开发人员编写 AutoCAD 应用程序并将此模式与<br/>“绘图设置”对话框关闭的对象捕捉模式区别开来。设置此位码值将关闭对象捕捉。在该位<br/>码值关闭时将OSMODE设置为其他值可以打开对象捕捉。<br/></font> 请注意仔细阅读“使用状态行的....”这段。其中这个返回码:16384,应该引起程序员<br/>的非常重视!简而言之:在(getvar "osMode")值加上16384,就等于用鼠标单击命令行下方<br/>的[捕捉对象]按钮,例如: <br/> 若: osMode=3,即打开对象捕捉开关,且设置为“端点”和“中点”;<br/> 则: osMode=3+16384=16387,即关闭对象捕捉开关,而“端点”和“中点”仍然存在,<br/>仅仅是被屏蔽掉了。当再次设置: osMode=16387-16384=3 时捕捉对象被打开了,且为“端<br/>点+中点”模式。<br/> 综上所述,根据以上分析,则该段程序改写如下:<br/> (setvar "osmode" (+ (rem (getvar "osmode") 16384) 16384));关闭捕捉.<br/> (command "_.Line" Pt1 Pt2 "")<br/> ......<br/> (setvar "osmode" (rem (getvar "osmode") 16384));打开捕捉.</strong></font></p><p><font face="楷体_GB2312" size="4"><strong> 编写为函数则,如下:<br/><font color="#e70808"> ;;;**************************<br/> ;;; No.0 对象捕捉开关 函数 <br/> ;;;**************************<br/> (defun ayOSMode (isOpenSnap)<br/> (if isOpenSnap<br/> (setvar "osmode" (rem (getvar "osmode") 16384));打开捕捉.<br/> (setvar "osmode" (+ (rem (getvar "osmode") 16384) 16384));关闭捕捉.<br/> );end_if<br/> );end_defun<br/></font> 则上述程序段则改写为:<br/> (ayOSMode nil);关闭捕捉.<br/> (command "_.Line" Pt1 Pt2 "")<br/> ......<br/> ((ayOSMode T);打开捕捉.</strong></font></p><p><font face="楷体_GB2312" size="4"><strong> 【解释说明】如上的对象捕捉设置函数,和采用(setvar "osMode" 0)后恢复到原来的设置值有何不同<br/>呢?<br/> 1、函数(defun ayOSMode ...)没有显示的设置对象捕捉为: osMode=0,仅仅是加上系统提供的16384值,<br/>暂时屏蔽了对象捕捉,等同于用鼠标单击命令行下方的[捕捉对象]按钮关闭对象捕捉,没有重新设置对象捕捉<br/>码数值。<br/> 2、无论系统中发生什么错误/取消/终止,即便是程序中(defun *error())函数捕捉不到的错误信息也好,<br/>系统任然能够隐式保留对象捕捉设置值,仅仅是像[捕捉对象]按钮被用鼠标单击后关闭一样而已。<br/> 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> 呀,真想不到还有这东西存在,lisp实在,魅力无穷呀 (defun set-osmode (flag)<br/> (setvar "OSMODE" (boole (cond<br/> (flag 2)<br/> (7)<br/> ) (getvar "OSMODE") 16384<br/> )<br/> )<br/>) <p>我觉得这样比较实用:</p><p>(command "line" <font color="#ff3300">"_non"</font> pt1 <font color="#ff0000">"_non"</font> pt1 "")</p><p>省去了osmode的设置</p> 受用,,确实以前不知道,,现在明白了。。多谢楼上的! 受用了,这是一个好建议。谢谢分享 楼主好强大!
页:
[1]