明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 15436|回复: 30

第二章 初学Visual LISP编程

  [复制链接]
发表于 2012-9-18 18:58:56 | 显示全部楼层 |阅读模式
第二章 初学Visual LISP编程

在本章中我们将开始使用Visual LISP写些基本的代码,并通过一个例子学会编写、测试、调试和编译你的代码直到成为一个完整的程序。为了能让CAD程序员保持兴趣,这里就不使用象“Hello World”这种惯用代码来做例子了。

(vl-load-com)

为了在Visual LISP中使用很酷的ActiveX功能,你首先需要用(vl-load-com)函数来初始化ActiveX接口。它可以包含在每个文件中或每个函数定义中,无所谓。当它被执行过后,后续的重复调用将毫无影响。
(defun C:SHOWLAYER (/ ent lay)
  (if (setq ent (entsel "\n选择对象以查看其图层名: "))
    (alert
      (strcat "图层名: "
       (vla-get-layer (vlax-ename->vla-object (car ent)))
      )
    )
  )
  (princ)
)

在上例的代码中,演示了怎样取得选定图元的图层并将其显示到提示框里。把代码加载到AutoCAD中并在命令行中键入SHOWLAYER运行它。此时屏幕上会提示“选择对象以查看其图层名:”,选中对象后该对象的图层名就会显示出来…
  
图2-1 SHOWLAYERS.LSP

这里其实与传统的通过DXF方式访问图层名有点不同,用户不需要知道在DXF中的组码8是指定图层。而可以用(vla-get-layer)来代替,这样更加直观。这也就是Visual LISP中ActiveX功能吸引人的关键:清晰。

提示:你可用任何方法将(vl-load-com)添加到启动组中。比如添加到acad.lsp或acaddoc.lsp文件中,或生成一个很小的LSP文件并通过“APPLOAD”将其加到启动组中。

AutoLISP和Visual LISP/ActiveX对比

图2-2 LISP和Visual LISP方法之间的比较

图2-2中两个语句在本质上是一样的,每一个语句稍有点冗长,需要消耗多一点系统资源去执行,但这些增加的负担在多数情况下是可以忽略不计的。

不管用哪种方式取得对属性的初始访问后(也即,entgetvlax-ename->vla-object),接下来的工作用ActiveX方式来写会更简单一些。象这种情况,一般每次只进行一个对象的操作。例如…
(defun GETLAYER (entity / elist)
(cdr (assoc 8 (entget entity)))
)

…和以下在功能上是一样的…
(defun GETLAYER (entity / obj)
  (vla-get-layer (vlax-ename->vla-object entity))
)

无论如何,这个比较并不全面,因为它没有为你演示ActiveX对象模型如何允许你在逻辑的层面上去进行关联性的操作。例如,以下的代码就为你显示了如何从参数/文件集合中取得属性:
(vla-get-supportpath
  (vla-get-files
    (vla-get-preferences (vlax-get-acad-object))
  )
)

以上的特性不可能仅靠AutoLISP就可完成。通过ActiveX和AutoCAD的对象模型才能做到。而实际上,Visual LISP和VBA可以通过AutoCAD的ActiveX接口来访问这些特性。

让我们来看看另一个进行特殊的LINE图元属性的例子,你可以看到ActiveX接口怎样提供了很方便的方法去理解这些名称,以便使编码更直观:
(setq ent (car (entsel "\n选择直线对象: ")))
(setq objLine (vlax-ename->vla-object ent))
(vla-get-layer objLine)
(vla-get-color objLine)
(vla-get-lineweight objLine)
(vla-put-layer objLine "0")
(vla-put-color objLine acRed)

通过这两个例子你可以了解到,相对于神秘的DXF组码来说,使用ActiveX能更直观地访问和编辑图元属性。同样,值得注意的是,DXF的62组码是临时的,而图元的Color属性才是持久的。换句话说:一个带color=ByLayer的图元在(entget)数据表中是没有DXF 62字段的。只有在将颜色添加并覆盖了默认层设置后,这个图元才有DXF 62字段。然而,如果你使用ActiveX访问这样的图元,即 color=ByLayer,返回的值就是acByLayer。

下面例子说明了做为开发者要如何使用它,要考虑到以下函数可以从一个图元复制图层、颜色和线型属性到另一个图元中:
(defun CopyLayerColor1 (obj1 obj2)
  (vla-put-layer obj2 (vla-get-layer obj1))
  (vla-put-color obj2 (vla-get-color obj1))
)

你会注意到我们不需要依赖DXF代码,我们也不需要使用(subst)(entmod)函数去更新图元属性。同样的函数用AutoLISP写的话就会被写成如下例这样:
(defun CopyLayerColor1 (obj1 obj2)
  (vla-put-layer obj2 (vla-get-layer obj1))
  (vla-put-color obj2 (vla-get-color obj1))
)
(defun CopyLayerColor2 (ent1 ent2 / elist1 elist2 lay1 col1)
  (setq elist1 (entget ent1)
      elist2 (entget ent2)
      lay1   (cdr (assoc 8 elist1))
  )
  (setq elist2 (subst (cons 8 lay1) (assoc 8 elist2) elist2))
  (if (assoc 62 elist1)
    (progn
      (setq col1 (cdr (assoc 62 elist1)))
      (if (assoc 62 elist2)
         (setq elist2 (cons (cons 62 col1) elist2))
         (setq elist2 (subst (cons 62 col1) (assoc 62 elist2) elist2))
      )
    )
  )
  (entmod elist2)
)

请注意,对于DXF的62组码的额外检查要同时存在于源图元和目标图元的数据表中。如你所见,在执行许多常规任何中,Visual LISP和ActiveX可以明显地减少代码的数量。减少了代码也就同时减少了潜在的错误的发生。减少了错误也就等于减少了相应的测试和调试代码。所有这些都能更快更简单更高效地完成高质量的代码,并且也会令消费者更满意。

浏览对象属性和方法

如果你还没有发现AutoCAD中的对象提供的大量属性和方法,有一个好方法可以帮你熟悉它们,就是通过(vlax-dump-object)函数,这个函数需要一个参数,即所要显示对象属性的对象,还有一个可选的参数,它是一个标识(任何非nil值),代表了是否显示对象的方法。
(vlax-dump-object object [show-methods])

下例是在常规的直线图元上使用该函数的结果:
_$ (setq e (entsel)); pick a LINE entity
_$ (setq obj (vlax-ename->vla-object (car e)))
Returns #<VLA-OBJECT IAcadLine 00f20024>
_$ (vlax-dump-object obj T)
; IAcadLine: AutoCAD Line Interface
; Property values:
; Angle (RO) = 0.630844
; Application (RO) = #<VLA-OBJECT IAcadApplication 00a8a730>
; Color = 256
; Delta (RO) = (4.98519 3.64122 0.0)
; Document (RO) = #<VLA-OBJECT IAcadDocument 00ed1e0c>
; EndPoint = (9.63516 6.56966 0.0)
; Handle (RO) = "2B"
; HasExtensionDictionary (RO) = 0
; Hyperlinks (RO) = #<VLA-OBJECT IAcadHyperlinks 00f21c44>
; Layer = "0"
; Length (RO) = 6.17338
; Linetype = "ByLayer"
; LinetypeScale = 1.0
; Lineweight = -1
; Normal = (0.0 0.0 1.0)
; ObjectID (RO) = 1074179416
; ObjectName (RO) = "AcDbLine"
; OwnerID (RO) = 1074179320
; PlotStyleName = "ByLayer"
; StartPoint = (4.64998 2.92844 0.0)
; Thickness = 0.0
; Visible = -1
; Methods supported:
; ArrayPolar (3)
; ArrayRectangular (6)
; Copy ()
; Delete ()
; GetBoundingBox (2)
; GetExtensionDictionary ()
; GetXData (3)
; Highlight (1)
; IntersectWith (2)
; Mirror (2)
; Mirror3D (3)
; Move (2)
; Offset (1)
; Rotate (2)
; Rotate3D (3)
; ScaleEntity (2)
; SetXData (2)
; TransformBy (1)
; Update ()


如你所见,这是一个用于检查图元的属性和方法的非常有帮助的函数,它同样对检查任何其它对象也很有帮助 ,包括应用对象、文档、集中等等。

ActiveX与DXF对比?
ActiveX是否能帮你完成任何一个你必须由VLISP来完成的编程工作?当然不是。还是有相当一些情况只能用旧的AutoLISP来解决。在其它情况下,你可以用它们二者之一的任何一种来完成,但是AutoLISP方法将变成最有效或最易处理的选择,你可以会说:“那当然,你是这样认为的!”那让我们看一些例子吧。

选择集
你可以随便用AutoLISP或Visual LISP来创建或遍历选择集(或更准确地称之为选集),然而,你很快就会发现,在AutoLISP中处理选择集比在VLISP中更容易得多,也少很多问题。

点表
事实上,在AutoLISP中操作任何表结构要比在VLISP操作来得容易,虽然两者都很强大和灵活,用LISP构建和修改表结构比使用VLISP的数组结构更为简单。

图元属性
尽管大部分属性通过VLISP的ActiveX来访问比较容易也比较直接,但还是有些属性没有显露出来而只能通过AutoLISP的DXF组码值来读取。例如,线性标注对象(acDbRotatedDimension)的控制点,引线(LEADER)对象的控制点。而象不常用的BLOCKDEF(块参照)的说明属性在AutoLISP和VLISP中都完全无法访问,它只能使用特定加载的函数库才能访问。

虽然VLISP增加了很多又好又强大的功能,但我在接下来的内容中还是会不厌其烦的举详细的例子来说明使用AutoLISP仍然是很重要的。



该贴已经同步到 明经通道的微博

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2019-5-14 22:43:15 | 显示全部楼层
虽然有点懵,但是还是要努力扩展到自己能看懂,能上手操作
发表于 2020-4-29 11:50:59 | 显示全部楼层
讲的很好  对于初学者 很友好  
发表于 2012-9-19 16:45:24 | 显示全部楼层
持续关注中!
发表于 2012-9-20 16:16:09 | 显示全部楼层
我会坚持听下去,努力学习
发表于 2012-10-19 10:34:40 | 显示全部楼层
好好学习,天天向上
发表于 2012-10-20 15:33:31 | 显示全部楼层
讲得太好了,样例也很到位,容易理解!
发表于 2012-10-25 07:32:29 | 显示全部楼层
很到位,呵呵
发表于 2012-11-12 22:44:29 | 显示全部楼层
学习中。。。
发表于 2013-1-4 17:10:26 | 显示全部楼层
努力学习
发表于 2013-1-17 17:11:25 | 显示全部楼层

好好学习,天天向上
发表于 2013-3-6 17:49:54 | 显示全部楼层
看不懂呢
??
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-11-22 20:58 , Processed in 0.210432 second(s), 28 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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