明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 2340|回复: 6

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

  [复制链接]
发表于 2009-2-19 13:47:00 | 显示全部楼层 |阅读模式
本帖最后由 作者 于 2009-2-19 13:55:36 编辑

    众所周知,在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系统命令一样,在对象捕捉控制方面相同的效果。


评分

参与人数 1明经币 +1 收起 理由
自贡黄明儒 + 1 很给力!

查看全部评分

发表于 2009-2-19 15:43:00 | 显示全部楼层
呀,真想不到还有这东西存在,lisp实在,魅力无穷呀
回复 支持 0 反对 1

使用道具 举报

发表于 2009-2-19 15:52:00 | 显示全部楼层
(defun set-osmode (flag)
  (setvar "OSMODE" (boole (cond
                            (flag 2)
                            (7)
                          ) (getvar "OSMODE") 16384
                   )
  )
)
发表于 2009-2-19 17:02:00 | 显示全部楼层

我觉得这样比较实用:

(command "line" "_non" pt1 "_non" pt1 "")

省去了osmode的设置

发表于 2012-4-25 08:53:17 | 显示全部楼层
受用,,确实以前不知道,,现在明白了。。多谢楼上的!
发表于 2013-12-16 11:17:51 | 显示全部楼层
受用了,这是一个好建议。谢谢分享
发表于 2013-12-16 21:54:52 | 显示全部楼层
楼主好强大!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-5-25 22:36 , Processed in 0.178559 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表