资源预览内容
第1页 / 共60页
第2页 / 共60页
第3页 / 共60页
第4页 / 共60页
第5页 / 共60页
第6页 / 共60页
第7页 / 共60页
第8页 / 共60页
第9页 / 共60页
第10页 / 共60页
亲,该文档总共60页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第11章使用反应器AutoLISP使用反应器11.1反应器反应器是一种反馈机制,它可以在发生某些特定事件时,将所发生的事件通知给应用程序,应用程序将会根据发生的具体事件做出相应的决策。例如,在某个图元上链接了一个反应器,如果用户移动这个图元,应用程序就会接到反应器的通知,知道了该图元被移动这个事件,如果需要,应用程序可以用适当的动作(如移动与该图元相关的其它图元,或显示有关信息等)响应该通知。1. 1. 反应器的类型 反应器有多种类型,每种反应器对应一个或多个AutoCADAutoCAD事件。反应器可以分为以下几个大类: l l数据库反应器:当图形数据库发生特定类型的事件时,该反应器将通知应用程序。AutoLISP使用反应器 l l文档反应器:当前图形文档发生改变(如打开新的图形文档、激活其它文档窗口、改变文档的锁定状态等)时,该反应器将通知应用程序。 l l编辑器反应器:在调用AutoCADAutoCAD命令(如打开图形、关闭图形、保存图形、输入输出DXFDXF文件、改变系统变量的值等)时,该反应器将通知应用程序。 l l链接反应器:当加载和卸载ARXARX应用程序时,该反应器将通知应用程序。 l l对象反应器:当特定对象(AutoCADAutoCAD图元)被修改、复制或删除时,该反应器将通知应用程序。 调用函数vlr-typesvlr-types可返回反应器类型的完整列表。表11-111-1列出了AutoCADAutoCAD反应器类型及其标识符。AutoLISP使用反应器表11-1AutoCAD11-1AutoCAD反应器类型及其标识符反应器类型的标识符 说明:VLR-AcDb-Reactor :VLR-AcDb-Reactor 数据库反应器:VLR- DocManager- Reactor :VLR- DocManager- Reactor 文档管理反应器:VLR-Editor- Reactor :VLR-Editor- Reactor 通用编辑器反应器:VLR-Linker- Reactor :VLR-Linker- Reactor 链接反应器:VLR-Object- Reactor :VLR-Object- Reactor 对象反应器 其中通用编辑器反应器被进一步细分为更加明确的几种反应器类型,见表11-211-2。表11-111-1中的通用编辑器反应器类型只是为了向后兼容才保留的,表11-211-2所示的各种编辑类型的反应器不能被通用编辑器 :VLR-Editor-:VLR-Editor-ReactorReactor引用。AutoLISP使用反应器表11-2 11-2 编辑类型的各种反应器及其标识符反应器类型的标识符 说明:VLR-Command-Reactor :VLR-Command-Reactor 通报命令事件:VLR-DeepClone-Reactor :VLR-DeepClone-Reactor 通报 deep clone deep clone 事件:VLR-DWG-Reactor :VLR-DWG-Reactor 通报打开或关闭图形文件的事件:VLR-DXF-Reactor :VLR-DXF-Reactor 通报和读写 DXF DXF 文件相关的事件:VLR-Insert-Reactor :VLR-Insert-Reactor 通报和插入块有关的事件:VLR-Lisp-Reactor :VLR-Lisp-Reactor 通报 LISP LISP 事件:VLR-Miscellaneous-Reactor :VLR-Miscellaneous-Reactor (表中未列出的)其它编辑器反应器类型:VLR-Mouse-Reactor :VLR-Mouse-Reactor 通报鼠标事件(例如双击):VLR-SysVar-Reactor :VLR-SysVar-Reactor 通报对系统变量的修改:VLR-Toolbar-Reactor :VLR-Toolbar-Reactor 通报对工具栏上位图的修改:VLR-Undo-Reactor :VLR-Undo-Reactor 通报 undo undo 事件:VLR-Wblock-Reactor :VLR-Wblock-Reactor 通报和写块有关的事件:VLR-Window-Reactor :VLR-Window-Reactor 通报和移动或改变AutoCADAutoCAD窗口大小的事件:VLR-XREF-Reactor :VLR-XREF-Reactor 通报附着或修改 XREF XREF 有关的事件AutoLISP使用反应器3. 3. 反应器回调事件 大部分AutoCADAutoCAD操作都会产生一些特定的事件,这些事件能够用来触发反应器的动作,这样的事件被称为回调事件。例如,当发出SaveSave命令保存图形时,将会发生AutoCAD保存图形文件(:vlr-beginSave:vlr-beginSave)的事件,当保存过程结束时,将会发生AutoCAD已将当前图形保存到磁盘(:vlr-saveComplete:vlr-saveComplete)的事件。设计基于反应器的应用程序就是根据回调事件的内容编写这些事件发生时所要激活的函数。 vlr-reaction-namesvlr-reaction-names函数返回与给定反应器类型相关的所有事件组成的表: (vlr-reaction-names reactor-type)(vlr-reaction-names reactor-type) 参数reactor-typereactor-type是反应器类型的标识,见表11-111-1和表11-211-2。AutoLISP使用反应器例如,下列代码将返回和图形反应器相关的所有事件组成的表:(vlr-reaction-names :VLR-DWG-Reactor)(vlr-reaction-names :VLR-DWG-Reactor)返回(:VLR-beginDwgOpen :VLR-endDwgOpen :VLR-dwg :VLR-(:VLR-beginDwgOpen :VLR-endDwgOpen :VLR-dwg :VLR-databaseConstructed :VLR-databaseToBeDestroyed :VLR-beginSave :VLR-databaseConstructed :VLR-databaseToBeDestroyed :VLR-beginSave :VLR-saveComplete :VLR-beginClose) saveComplete :VLR-beginClose) 下列代码将返回和对象反应器相关的所有事件组成的表:(vlr-reaction-names :vlr-object-reactor)(vlr-reaction-names :vlr-object-reactor); ;返回(:VLR-cancelled :VLR-copied :VLR-erased :VLR-unerased :VLR-(:VLR-cancelled :VLR-copied :VLR-erased :VLR-unerased :VLR-goodbye :VLR-openedForModify :VLR-modified :VLR-subObjModified goodbye :VLR-openedForModify :VLR-modified :VLR-subObjModified :VLR-modifyUndone :VLR-modifiedXData :VLR-unappended :VLR-:VLR-modifyUndone :VLR-modifiedXData :VLR-unappended :VLR-reappended :VLR-objectClosed)reappended :VLR-objectClosed)AutoLISP使用反应器 加载并运行以下代码,将会打印出所有相关反应器事件的列表(按反应器类型排序)。(defun print-reactors-and-events ()(defun print-reactors-and-events () (foreach rtype (vlr-types) (foreach rtype (vlr-types) (princ (strcat n (vl-princ-to-string rtype) (princ (strcat n (vl-princ-to-string rtype) (foreach rname (vlr-reaction-names rtype) (foreach rname (vlr-reaction-names rtype) (princ (strcat nt (vl-princ-to-string rname) (princ (strcat nt (vl-princ-to-string rname) (princ) (princ) ) AutoLISP AutoLISP ReferenceReference列出了与各种反应器类型相关的所有事件,有关信息在创建反应器的函数部分做了说明。 和ActiveXActiveX一样,必须首先调用vl-load-comvl-load-com函数,加载支持反应器和其它AutoLISPAutoLISP扩展函数之后,才能实现反应器的功能。AutoLISP使用反应器11.2 11.2 定义反应器的回调函数 反应器的回调函数就是回调事件发生时所要执行的函数。反应器的回调函数是用AutoLISPAutoLISP定义的。编写回调函数有以下一些限制: 不能使用commandcommand函数调用AutoCADAutoCAD命令,只能用ActiveXActiveX函数访问图形对象。 不能使用entgetentget和entmodentmod函数。 不能使用选择集操作函数。 不能使用交互输入函数。 在事件处理函数中不要加载警告和信息之外的对话框。 定义对象反应器回调函数和定义其它反应器的回调函数也不完全相同。AutoLISP使用反应器11.2.1 11.2.1 定义对象反应器的回调函数定义对象反应器的回调函数的格式如下: (defun (defun function function (notifier-object (notifier-object reactor-object reactor-object parameter-list)parameter-list)参数notifier-objectnotifier-object是事件发生的对象。参数reactor-objecreactor-objec是调用这个函数的反应器对象。参数parameter-listparameter-list是回调事件返回的回调数据表。 例如,例11-111-1定义了名为print-radiusprint-radius的回调函数。notifier-objectnotifier-object是事件发生的对象,reactor-objectreactor-object是调用这个函数的反应器对象,parameter-listparameter-list是回调事件返回的回调数据表。虽然在本例并不关心parameter-listparameter-list的值,但定义回调函数时,也要进行变量声明。AutoLISP使用反应器【例11-111-1】定义名字为print-radiusprint-radius的回调函数,该函数用来打印圆的半径。(defun print-radius (notifier-object reactor-object parameter-list)(defun print-radius (notifier-object reactor-object parameter-list) (vl-load-com) (vl-load-com) (cond (cond (vlax-property-available-p (vlax-property-available-p notifier-object notifier-object Radius)Radius) ;判断该图形对象是否具有radiusradius特性 (princ “(princ “这个圆的半径是: ) (princ (vla-get-radius notifier-object) (princ (vla-get-radius notifier-object) ) ) ) ) )AutoLISP使用反应器11.2.2 11.2.2 定义其它反应器的回调函数 由于其它反应器不需要链接到AutoCADAutoCAD图元上,因此定义其它反应器的回调函数只需要以下两个参数:(defun function(reactor-object parameter-list)(defun function(reactor-object parameter-list)参数reactor-objectreactor-object是调用这个函数的反应器对象。参数parameter-listparameter-list是回调事件返回的回调数据表。例11-211-2定义了名为saveDrawingInfosaveDrawingInfo的回调函数。参数calling-calling-reactorreactor是调用该函数的反应器对象。参数commandInfocommandInfo是回调事件返回的回调数据表。该函数在发生保存AutoCADAutoCAD图形的事件时将被激活,显示文件的路径和大小等信息。AutoLISP使用反应器【例11-211-2】定义名字为saveDrawingInfosaveDrawingInfo的回调函数。(defun saveDrawingInfo(calling-reactor commandInfo / dwgname )(defun saveDrawingInfo(calling-reactor commandInfo / dwgname ) (vl-load-com) (vl-load-com) (setq dwgname (cadr commandInfo) (vl- dwgname) (setq dwgname (cadr commandInfo) (vl- dwgname) (alert(strcat (alert(strcat 这这个个文文件件( dwgname dwgname )的的大大小小是是 (itoa (itoa ) ) 字字节节.).) (princ) (princ) ) 在该例中,通过函数vl-vl-获取图形文件的大小,通过警告对话框显示这些信息。AutoLISP使用反应器11.2.3. AutoCAD11.2.3. AutoCAD预定义的回调函数 AutoCADAutoCAD提供了两个预定义的回调函数,可以在测试反应器时使用这些函数: (1 1)vlr-beep-reactionvlr-beep-reaction函数vlr-beep-reactionvlr-beep-reaction的功能是让计算机发出“嘟嘟”声。 (2 2)vlr-trace-reactionvlr-trace-reaction函数vlr-trace-reactionvlr-trace-reaction函数的功能是将参数列表打印到VLISPVLISP的“跟踪”窗口。AutoLISP使用反应器11.3 11.3 创建反应器 创建反应器的主要工作就是将事件和回调函数相关联。创建反应器用vlr-vlr-reactor-reactor函数。每种类型的反应器都有一个与之对应的用于创建该反应器的AutoLISPAutoLISP函数,这些函数的名称和反应器类型的名称相同,只是没有前面的冒号。例如,vlr-vlr-acdb-reactoracdb-reactor为创建数据库反应器函数,vlr-toolbar-reactorvlr-toolbar-reactor为创建工具栏反应器函数。所有创建反应器的构造函数都返回一个反应器对象。 AutoLISP AutoLISP ReferenceReference列出了与每种反应器类型相关的所有可能事件。例如,通过vlr-DWG-reactorvlr-DWG-reactor条目,可看到表11-311-3所示与DWGDWG反应器相关的所有可能事件。AutoLISP使用反应器表11-3DWG反应器事件事件名称 说明:vlr-beginClose :vlr-beginClose 图形数据库将被关闭。:vlr-databaseConstructed :vlr-databaseConstructed 已经构建图形数据库。:vlr-databaseToBeDestroyed :vlr-databaseToBeDestroyed 将从内存中删除图形数据库的内容。:vlr-beginDwgOpen AutoCAD:vlr-beginDwgOpen AutoCAD将打开图形文件。:vlr-endDwgOpen AutoCAD:vlr-endDwgOpen AutoCAD已结束打开操作。:vlr-dwg :vlr-dwg 新图形已被加载到AutoCADAutoCAD图形窗口。:vlr-beginSave AutoCAD:vlr-beginSave AutoCAD将保存图形文件。:vlr-saveComplete AutoCAD:vlr-saveComplete AutoCAD已将当前图形保存到磁盘。AutoLISP使用反应器11.3.111.3.1创建对象反应器 因为对象反应器必须链接到特定的AutoCADAutoCAD图元(对象)上,所以在定义对象反应器时,必须指定反应器所要链接的图元。创建对象反应器通过函数vlr-object-reactorvlr-object-reactor,该函数的调用格式如下: (vlr-object-reactor owners data callbacks)(vlr-object-reactor owners data callbacks) 参数ownersowners为VLAVLA对象表,表内可以是多个VLAVLA对象。这些对象也被称为反应器的所有者。 参数datadata为与反应器对象相关联的数据,如果没有数据则该项为nilnil。 参数callbackscallbacks为点对表,用于指明事件和与该事件相关联的回调函数。点对表的格式如下: (event-name . callback_function)(event-name . callback_function) 该 点 对 表 的 event-nameevent-name是 表 11-411-4所 示 ObjectObject事 件 中 的 名 称 标 识 ,callback_functioncallback_function为回调函数。表11-511-5是针表11-411-4所示对特定的回调事件返回的回调数据表。 该函数的返回值为reactor_object(对象反应器)。AutoLISP使用反应器名称标识 事件:vlr-cancelled :vlr-cancelled 对对象的修改已经取消。:vlr-copied :vlr-copied 对象已被复制。:vlr-erased :vlr-erased 对象的删除标志已被设置。:vlr-unerased :vlr-unerased 对象的删除标志已被重置。:vlr-goodbye :vlr-goodbye 即将从内存中删除对象。:vlr-openedForModify :vlr-openedForModify 即将修改对象。:vlr-modified :vlr-modified 对象已被修改。如果取消修改,还将激发 :vlr-cancelled :vlr-cancelled 和:vlr-modifyUndone:vlr-modifyUndone。:vlr-subObjModified :vlr-subObjModified 对象的子图元已被修改。在修改多段线或网格顶 点时触发该事件。:vlr-modifyUndone :vlr-modifyUndone 对象的修改已被放弃。:vlr-modifiedXData :vlr-modifiedXData 对象的扩展图元数据已被修改。:vlr-unappended :vlr-unappended 已从图形数据库中拆离对象。:vlr-reappended :vlr-reappended 对象已被重新链接到图形数据库。:vlr-objectClosed :vlr-objectClosed 对对象的修改已经完成。表11-4Object事件及其名称标识AutoLISP使用反应器名称 表长度 参数:vlr-cancelled 0:vlr-cancelled 0:vlr-erased :vlr-erased :vlr-unerased :vlr-unerased :vlr-goodbye:vlr-goodbye:vlr-openedForModify :vlr-openedForModify :vlr-modified :vlr-modified :vlr-modifyUndone :vlr-modifyUndone :vlr-modifiedXData :vlr-modifiedXData :vlr-unappended :vlr-unappended :vlr-reappended :vlr-reappended :vlr-objectClosed:vlr-objectClosed:vlr-copied 1 :vlr-copied 1 由复制操作创建的对象(ename)(ename)。:vlr-subObjModified 1 :vlr-subObjModified 1 已被修改的子对象(ename)(ename)。表11-5Object事件回调数据AutoLISP使用反应器 例如,下面的代码创建了一个对象反应器。该对象反应器只有一个所有者,即VLAVLA对象myCirclemyCircle;与该反应器对象相关联的数据为Circle Circle ReactorReactor;点对表为(:vlr-modified (:vlr-modified . . print-radius)print-radius), 当 发 生 myCirclemyCircle对 象 被 修 改 ( 即 :vlr-:vlr-modifiedmodified)事件时,调用print-radiusprint-radius回调函数:(setq (setq circleReactor circleReactor (vlr-object-reactor (vlr-object-reactor (list (list myCircle) myCircle) Circle Circle Reactor Reactor (:vlr-modified (:vlr-modified . . print-print-radius)radius) 上述反应器对象赋给了变量circleReactorcircleReactor。可以通过该变量实现对该反应器的查询、修改或删除等。AutoLISP使用反应器 创建对象反应器除了必须指定反应器所要链接的图元之外,还要注意以下几点:(1 1)在定义所有者列表时,只能指定VLAVLA对象,而不允许使用enameename对象。要求VLAVLA对象是因为回调函数只能用ActiveXActiveX方法修改AutoCADAutoCAD对象,而ActiveXActiveX方法要求使用VLAVLA对象。尽管不能在回调反应器中使用由entlastentlast和entgetentget等函数获取VLAVLA对象,但可以用vlax-ename-vla-objectvlax-ename-vla-object函数将enameename对象转换成VLAVLA对象。(2 2)如果对象已被包括在对象反应器的所有者列表之中,那么就不能在回调函数中修改该对象。如果这样做,将会导致一个出错消息,并使AutoCADAutoCAD崩溃。 下面是实现对象反应器功能的实例: :AutoLISP使用反应器(1 1)加载例11-311-3所示程序段【例11-311-3】生成一个圆的VLAVLA对象。(setq myCircle(setq myCircle(progn(progn (setq ctrPt (getpoint (setq ctrPt (getpoint n n输输入入圆圆心心: : ) ) radius (distance ctrPt (getpoint ctrpt n radius (distance ctrPt (getpoint ctrpt n输输入半径入半径 : ): ) ) ) (vla-addCircle (vla-addCircle (vla-get-ModelSpace (vla-get-ModelSpace ;将圆加入到图形模型空间 (vla-get-ActiveDocument (vlax-get-acad-object)(vla-get-ActiveDocument (vlax-get-acad-object) (vlax-3d-point ctrPt) (vlax-3d-point ctrPt) radius radius ) ) 该代码使用vla-addCirclevla-addCircle画一个圆,将返回值赋给变量myCirclemyCircle。该返回值是VLAVLA对象,包含指向所画圆对象的指针。AutoLISP使用反应器(2 2)加载例11-1 11-1 所示回调函数print-radiusprint-radius。(3 3)定义对象反应器(setq circleReactor (vlr-object-reactor (list myCircle)(setq circleReactor (vlr-object-reactor (list myCircle) Circle Reactor (:vlr-modified . print-radius) Circle Reactor (:vlr-modified . print-radius)(4 4)在AutoCADAutoCAD图形窗口,选取该圆并修改其大小,print-radius print-radius 函数将在AutoCADAutoCAD命令窗口显示一个消息。例如,如果用夹点或STRETCHSTRETCH命令改变了该圆的大小,将在命令提示区显示以下信息: * * STRETCH *STRETCH * Specify Specify stretch stretch point point or or Base Base point/Copy/Undo/eXit:point/Copy/Undo/eXit:这这个个圆圆的的半径是半径是: :190.0190.0 如果用夹点或STRETCHSTRETCH命令改变其他圆时的大小,将没有该提示信息中的“这这个个圆圆的半径是的半径是:”:”,这是因为在其他的圆上没有链接circleReactorcircleReactor反应器。AutoLISP使用反应器11.3.2 11.3.2 创建其它反应器 其它反应器不需要链接AutoCADAutoCAD图元,所以在定义时,只需要两个参数。创建其它反应器通过函数vlr-vlr-reactor-reactor,该函数的调用格式如下: (vlr-(vlr-reactor data callbacks)-reactor data callbacks) 参数datadata为任意要与反应器对象关联的数据,如果没有数据则该项为nilnil。 参数callbackscallbacks为点对表,指明事件和与该事件相关联的回调函数,点对表的格式如下: (event-name . callback_function)(event-name . callback_function) 例如,下列代码定义了一个DWGDWG编辑器反应器。当用户发出SaveSave命令时,该反应器将激活saveDrawingInfosaveDrawingInfo函数。 (vlr-dwg-Reactor nil (:vlr-saveComplete . saveDrawingInfo)(vlr-dwg-Reactor nil (:vlr-saveComplete . saveDrawingInfo) 在该例中,第一个参数为nilnil是因为没有与反应器相关联的数据;第二个参数是点对表,指明:vlr-saveComplete:vlr-saveComplete事件与saveDrawingInfosaveDrawingInfo回调函数相关联。当:vlr-saveComplete:vlr-saveComplete事件发生时,AutoCADAutoCAD传递给回调函数一个图形文件名字的字符串。AutoLISP使用反应器 每个点对表都指定了反应器要通报的事件,以及该事件发生时要调用的回调函数。在本例中,只指定了一个事件:vlr-saveComplete:vlr-saveComplete。 只要用户发出命令,不管是从AutoCADAutoCAD命令行、菜单、工具栏或AutoLISPAutoLISP程序,都会通知编辑器反应器。所以,该DWGDWG反应器的回调函数需要明确它应对什么事件作出响应。在本例中,回调函数saveDrawingInfosaveDrawingInfo只是检查SaveSave命令。 下面是实现DWGDWG反应器功能的实例: (1) 1) 加载例11-211-2所定义的回调函数saveDrawingInfosaveDrawingInfo。 (2(2)定义DWGDWG反应器 (vlr-dwg-Reactor (vlr-dwg-Reactor nil nil (:vlr-saveComplete (:vlr-saveComplete . . saveDrawingInfo)saveDrawingInfo) (3 3)在AutoCADAutoCAD图形窗口点取存盘的图标或调用存图的命令。当完成存图工作时将会弹出图11-111-1所示的AutoCAD MessageAutoCAD Message对话框。说明该实例成功。图11-1AutoCAD11-1AutoCAD的MessageMessage对话框AutoLISP使用反应器11.3.3 11.3.3 将数据附着到反应器对象 利用创建反应器函数的参数datadata可以为反应器指定与其关联的数据,如果该项为nilnil,表示不需要为反应器指定与其关联的数据。 一个对象可能链接多个反应器,如果它们的参数datadata都为nilnil,应用程序将无法区分它们。在这种情况下就应该为反应器指定文本字符串或应用程序能识别的其它数据。 例 如 , 前 面 创 建 对 象 反 应 器 circleReactorcircleReactor的 实 例 中 , 字 符 串“CircleReactor”CircleReactor”就是与反应器circleReactorcircleReactor相关联的数据。11.4 11.4 查询、修改和控制反应器的状态11.4.1 11.4.1 查询反应器 有多种不同的方法来获取反应器的信息。可以使用标准的VLISPVLISP数据查看工具查看反应器的信息,也可以用有关反应器的AutoLISPAutoLISP函数。AutoLISP使用反应器1.1.了解图形中有关反应器的总体情况 通过vlr-reactorsvlr-reactors函数可以了解当前图形中总共用到了哪些反应器或有哪些指定类型的反应器。vlr-reactorsvlr-reactors函数的调用格式如下:(vlr-reactors reactor-type.)(vlr-reactors reactor-type.) 参数reactor-typereactor-type为反应器类型的标识符。如果指定了reactor-typereactor-type参数,该函数返回由指定类型反应器组成的表。如果省略参数reactor-typereactor-type,该函数返回所有当前图形所有的反应器。 以下表达式列出图形中的所有反应器: (vlr-reactors)(vlr-reactors) ; 返 回 (:VLR-Object-Reactor (:VLR-Object-Reactor #VLR-Object-#) Reactor) (:VLR-Editor-Reactor (:VLR-Editor-Reactor #)#),有一个对象反应器和一个编辑器反应器。AutoLISP使用反应器以下表达式列出所有的对象反应器: (vlr-reactors (vlr-reactors :vlr-object-reactor):vlr-object-reactor) ; 返 回 (:VLR-Object-(:VLR-Object-Reactor #)Reactor #),有一个对象反应器以下表达式列出所有数据库反应器:(vlr-reactors :vlr-acdb-reactor)(vlr-reactors :vlr-acdb-reactor) ;返回nilnil,没有数据库反应器以下表达式列出所有DWGDWG反应器: (vlr-reactors (vlr-reactors :vlr-dwg-reactor):vlr-dwg-reactor); 返 回 (:VLR-DWG-Reactor (:VLR-DWG-Reactor # # #)#),有一个DWGDWG反应器,有两个指向该DWGDWG反应器的指针。AutoLISP使用反应器2. 2. 用VLISPVLISP的检验工具检查反应器 可以使用VLISPVLISP的检验工具检查反应器。在VLISPVLISP编辑器窗口选择circleReactorcircleReactor,单击按钮 ,将弹出图11-211-2所示检验窗口,该窗口显示以下信息:图11-211-2有关反应器的检验窗口l l反应器的类型标识符,如VLR-Object-ReactorVLR-Object-Reactorl l该反应器的所有者,如l l事件和与之相关联的回调函数,如: VLR-modified PRINT-RADIUS: VLR-modified PRINT-RADIUSl l该反应器是否是活动的:如果是活动的,added-p added-p 为 T T,否则它为 nilnill l附着到反应器上的用户数据,如“Circle Reactor”Circle Reactor”l l反应器的文档范围:如active-document-onlyactive-document-onlyl l该反应器所在文挡:如双击以 Owners Owners 开头的条目,可查看反应器所有者的列表。AutoLISP使用反应器3. 3. 用函数调用、查询反应器VLISPVLISP还提供了可在应用程序或控制台提示处查看反应器定义的函数:(1 1)vlr-typevlr-type函数返回指定反应器的类型,例如: (vlr-type circleReactor)(vlr-type circleReactor) ;返回 :VLR-Object-Reactor:VLR-Object-Reactor(对象反应器)(2 2)vlr-current-reaction-name vlr-current-reaction-name 函数返回当前反应器触发回调函数的事件名称。例如:(vlr-current-reaction-name)(vlr-current-reaction-name) ;返回nilnil(3 3)vlr-data vlr-data 返回附着到反应器的特定应用程序数据,可用该数据区分链接在同一个对象上的多个反应器。例如:(vlr-data circleReactor)(vlr-data circleReactor) ;返回 Circle Reactor“Circle Reactor“(4 4)vlr-ownersvlr-owners函数返回向某对象反应器发出通报的AutoCADAutoCAD图形中的对象(反应器所有者)列表,下述函数调用将列出 circleReactor circleReactor 的所有者:(vlr-owners circleReactor)(vlr-owners circleReactor) ;返回 (#)(#)(5 5)vlr-reactionsvlr-reactions函数返回指定反应器的回调条件回调函数列表,下例将返回 circleReactor circleReactor 的相关信息。例如:(vlr-reactions circleReactor)(vlr-reactions circleReactor) ;返回 (:VLR-modified . PRINT-RADIUS)(:VLR-modified . PRINT-RADIUS)AutoLISP使用反应器11.4.2 11.4.2 修改反应器1 1 添加或替换反应器的回调函数 通过函数vlr-reaction-setvlr-reaction-set可以添加或替换反应器中的一个回调函数。该函数的调用格式如下:(vlr-reaction-set reactor event function)(vlr-reaction-set reactor event function) 参数reactorreactor为反应器 对象。eventevent为符号,表示该反应器类型可用的事件之一。FunctionFunction为要添加或替换的AutoLISPAutoLISP函数名。返回值未确定。 例如,下面的命令使反应器circleReactorcircleReactor在修改对象时调用print-areaprint-area函数:(vlr-reaction-set (vlr-reaction-set circleReactor circleReactor :vlr-modified :vlr-modified print-print-area)area) ;返回PRINT-AREAPRINT-AREAAutoLISP使用反应器2. 2. 修改与反应器相关联的数据 通过函数vlr-data-setvlr-data-set可以修改与反应器相关联的数据。该函数的调用格式如下:(vlr-data-set obj data)(vlr-data-set obj data) 参数objobj为反应器对象,表示要修改数据的反应器对象。datadata为新数据。返回值为参数datadata。 例如,查看附着到反应器circleReactorcircleReactor的数据值: (vlr-data circleReactor) (vlr-data circleReactor) 返回Circle ReactorCircle Reactor 用字符串Circle Circle Area Area ReactorReactor替换反应器circleReactorcircleReactor的原有数据Circle ReactorCircle Reactor: (vlr-data-set (vlr-data-set circleReactor circleReactor Circle Circle Area Area Reactor)Reactor) ; ;返回Circle Circle Area ReactorArea Reactor 验证是否有了改变: (vlr-data circleReactor)(vlr-data circleReactor) ; ;返回Circle Area ReactorCircle Area Reactor 注意,应小心使用vlr-data-set函数,以免构成循环结构。AutoLISP使用反应器3. 3. 将一个数据库对象添加到反应器的所有者列表内 通过函数vlr-owner-addvlr-owner-add可以将一个数据库对象添加到指定反应器的所有者列表内。该函数的调用格式如下:(vlr-owner-add reactor owner)(vlr-owner-add reactor owner) 参数reactorreactor为反应器对象。ownerowner为要添加到反应器所有者列表中的VLAVLA对象。返回值为已添加了反应器的VLAVLA对象。例如,在下例中,名为archiearchie的圆弧对象被添加到反应器circleReactorcircleReactor的所有者列表中: (vlr-owner-add (vlr-owner-add circleReactor circleReactor archie)archie) ;返回 #vla-#OBJECT IAcadArc 03ad0bcc 可 通 过 检 验 该 反 应 器 来 验 证 这 点 : 更 新 反 应 器 circleReactor circleReactor 的检验窗口,用鼠标双击检验窗口的OwnersOwners开头的条目,将弹出图11113 3所示的反应器所有者检验窗口。AutoLISP使用反应器图11113 3反应器所有者的检验窗口4. 4. 从反应器所有者列表中删除某所有者对象 通过函数vlr-owner-removevlr-owner-remove可以从反应器所有者列表中删除某所有者对象。该函数的调用格式如下: (vlr-owner-remove reactor owner)(vlr-owner-remove reactor owner) 参数reactorreactor为反应器 对象。ownerowner为要从反应器所有者列表中删除的VLAVLA对象。返回值为被删除的VLAVLA对象。例如: (vlr-owner-remove (vlr-owner-remove circleReactor circleReactor archie)archie); 返 回 #vla-#OBJECT IAcadArc 03ad0bccAutoLISP使用反应器11.4.3 11.4.3 控制反应器的状态1. 1. 判断反应器是否是活动的 通过函数vlr-added-pvlr-added-p可以判断反应器是否是活动的。vlr-vlr-added-padded-p函数的调用格式如下: (vlr-added-p obj)(vlr-added-p obj) 参数objobj为反应器对象,表示要测试的反应器。如果反应器是活动的(已在 AutoCAD AutoCAD 中注册),返回T T,如果该反应器失效,则返回nilnil。例如: (vlr-added-p circleReactor)(vlr-added-p circleReactor) ;返回T T,表示该反应器是活动的AutoLISP使用反应器2. 2. 使反应器失效 通过函数vlr-removevlr-remove可以使指定的反应器失效。vlr-removevlr-remove函数的调用格式如下:(vlr-remove obj)(vlr-remove obj) 参数objobj为反应器对象。如果成功,返回反应器对象,否则,返回nilnil。例如,使反应器circleReactorcircleReactor失效:(vlr-remove circleReactor)(vlr-remove circleReactor);返回# 注意,失效的反应器,并没有从内存中被删除,该反应器仍然存在。AutoLISP使用反应器2. 2. 恢复失效的反应器 通过函数vlr-addvlr-add可以恢复指定的失效反应器,使之成为活动的(在AutoCADAutoCAD中注册)。vlr-addvlr-add函数的调用格式如下: (vlr-add obj)(vlr-add obj) 参数objobj为反应器对象,表示要恢复的失效反应器。如果成功,返回反应器对象,否则,返回nilnil。例如,恢复失效的circleReactorcircleReactor反应器: (vlr-add circleReactor)(vlr-add circleReactor) ;返回# 通过函数vlr-remove-allvlr-remove-all可以使图形中所有的反应器失效。vlr-remove-allvlr-remove-all函数的调用格式如下: (vlr-remove-all reactor-type)(vlr-remove-all reactor-type)AutoLISP使用反应器 可选参数reactor-typereactor-type为反应器类型的标识符,如果未指定reactor-typereactor-type,该函数禁用图形中所有的反应器。返回为包含若干个子表的表,每个子表的第一个元素表示反应器的类型,后续元素表示禁用的反应器对象。如果没有活动的反应器,该函数返回nilnil。例如,下面的函数调用将禁用所有编辑器反应器:(vlr-remove-all:vlr-editor-reactor)返 回 (:VLR-Editor-Reactor#)下面的调用函数将禁用所有反应器:(vlr-remove-all)返回(:VLR-Object-Reactor#)(:VLR-Editor-Reactor#)AutoLISP使用反应器11.5临时反应器和永久反应器反应器可以是临时的,也可以是永久的。二者的区别是:下一次打开该图形时,临时反应器将丢失,永久反应器则仍然存在。前者是反应器的默认模式。1.将临时反应器变成永久反应器通过函数vlr-pers可以将临时反应器变成永久反应器。函数vlr-pers的调用格式如下:(vlr-persobj)参数obj为反应器对象。如果成功则返回指定的反应器对象,否则返回nil。例如:(vlr-perscircleReactor);返回#AutoLISP使用反应器2.将永久反应器改变为临时反应器通过函数vlr-pers-release可以将永久反应器改变为临时反应器。函数vlr-pers的调用格式如下:(vlr-pers-releaseobj)参数obj为反应器对象。如果成功则返回反应器对象,否则返回nil。(vlr-pers-releasecircleReactor);返回#3.判断反应器是否是永久反应器通过函数vlr-pers-p可以判断反应器是否是永久反应器。函数vlr-pers-p的调用格式如下:(vlr-pers-pobj)参数obj为反应器对象。如果指定反应器是永久反应器,则返回指定的反应器对象,否则返回nil。例如:(vlr-pers-pcircleReactor);返回#AutoLISP使用反应器4.列出当前图形文档中的永久反应器通过函数vlr-pers-list可以列出当前图形文档中的永久反应器。函数vlr-pers-list的调用格式如下:(vlr-pers-listreactor-type)参数reactor-type为要列出的反应器对象。如果未指定reactorr-type,该函数列出所有永久反应器。返回值为由反应器对象组成的表。例如:(vlr-pers-list);返回(# #(#)AutoLISP使用反应器5.打开含有永久反应器的图形时的注意事项打开含有永久反应器的图形时的注意事项 反反应应器器只只是是链链接接事事件件和和回回调调函函数数的的一一种种工工具具,回回调调函函数数本本身身不不是是反反应应器器的的一一部部分分,它它一一般般也也不不是是图图形形的的一一部部分分。只只有有AutoCAD中中加加载载了了相相关关联联的的回回调调函函数数时时,图图形形中中保保存存的的反反应应才才有有实实际际作作用用。如如果果将将反反应应器器和和回回调调函函数数定定义义在在独独立立名名称称空空VLX中,则在打开图形时会自动加载回调函数。中,则在打开图形时会自动加载回调函数。 如如果果打打开开的的图图形形包包括括VLISP反反应应器器信信息息,但但没没有有加加载载相相关关回回调调函函数数,AutoCAD会会显显示示一一个个错错误误信信息息。可可用用函函数数vlr-pers-list返回图形文档中所有永久反应器组成的表。返回图形文档中所有永久反应器组成的表。AutoLISP使用反应器11.6反应器的使用规则由于将来可能修改反应器的内部实现机制,使用反应器时请尽量遵守下述规则,如果不遵守这些规则,可能会导致应用程序出现不可预料的结果。(1)不要依赖于反应器通报的顺序除了少数特例之外,建议不要依赖于反应器通报的顺序。例如 , OPEN命 令 将 触 发 BeginCommand、 BeginOpen、EndOpen和EndCommand事件。然而,它们发出的顺序可能不是这样的。可以依赖的顺序只有Begin事件是在相应End事件之前。例如commandWillStart()总是在commandEnded()之前发生,而beginInsert()总是在endInsert()之前发生。因为将来可能引入新的事件通报,可能会重新排列现有通报顺序,所以依赖于更复杂的顺序,可能会给您的应用程序带来问题。AutoLISP使用反应器(2)不要依赖于通报间函数调用的顺序在通报之间函数调用的顺序也是不能保证的。例如,当收到对象A的通报:vlr-erased时,它仅表示对象A被删除,如果在收到对象A的通报:vlr-erased之后收到了对象B的通报:vlr-erased,这只是表示对象A和B都已被删除。并不能保证B是在A后面被删除。如果应用程序依赖于这个层次的关系,那么应用程序在后续版本的AutoCAD中很可能会崩溃。所以不要依赖于这些顺序,而应该依赖于用反应器来指示系统的状态。(3)不要在反应器回调函数中使用任何需要和用户交互的函数在反应器回调函数中试图调用交互函数会导致严重问题,因为在事件发生时,AutoCAD可能仍在处理某命令。所以要避免使用要求用户输入的函数,如getpoint、entsel和getkword等,也不要使用选择集操作函数和command函数。AutoLISP使用反应器(4)在事件处理函数中不要加载对话框对话框和用户交互函数一样,也会影响AutoCAD的当前操作。但是,消息对话框和警告对话框可认为是非交互的,所以可以使用它们。(5)不要更新引发事件的对象引起对象触发回调函数的事件可能仍在处理之中,当调用回调函数时AutoCAD可能仍在使用该对象。所以,在回调函数中不要试图更新这样的对象。然而,可以从触发事件的对象中读取信息。例如,假设有一块用砖填充的地板,而且将反应器链接到地板边界上。如果修改地板的尺寸,反应器回调函数将自动添加或删除砖以填充新的地板面积。通过函数能够获取边界的新面积,但不能去修改边界本身。AutoLISP使用反应器(6)不要在回调函数中执行能触发相同事件的操作如果在反应器回调函数中执行的某操作过程中触发了同样的事件,将会陷入一个无限循环。例如,如果在BeginOpen事件的回调函数中试图打开一个图形,AutoCAD将持续打开更多的图形,直到打开的图形数目达到上限,无法再打开图形为止。(7)能在发生同一事件时调用多个回调函数在设置反应器以前要确认当前没有设置该反应器,否则可能在发生同一事件时调用多个回调函数。(8)显示有模对话框时,不会发生任何事件所谓有模对话框,是指操作其它窗口之前必须关闭的话框时。显示这样的对话框时,不会发生任何事件。AutoLISP使用反应器11.7定义反应器实例1.定义将对象反应器链接到指定直线的命令。要求:当直线被修改时,弹出显示该直线长度的信息对话框。很明显,反应器的链接对象就是指定的直线。触发事件是直线被修改,从表11-4可以查找出图形对象被修改的事件是:vlr-modified。回调函数的功能是调用信息对话框显示被选直线长度。程序的代码如下:【例11-4】定义将对象反应器链接到指定直线的命令。(vl-load-com)(defunc:rct-line(/elrltvrl)(setqel(car(entseln选择一条链接反应器的直线:)(setqrlt(list(vlax-ename-vla-objectel);将图元名转换为VLA对象AutoLISP使用反应器;创建对象反应器,回调事件是图元被修改,回调函数是show-l(setqvrl(vlr-pers(vlr-object-reactorrltnil(:vlr-modified.show-l)(princ);定义回调函数(defunshow-l(notifier-objectreactor-objectparameter-list/l)(setql(vla-get-lengthnotifier-object);将被选直线的长度赋给变量l(setql(rtosl24);将数值转换为字符串(alert(strcat直线的长度是:l);调用信息对话框)AutoLISP使用反应器加载以上程序,在Command:提示下输入rct-line命令,用鼠标指定一条直线,该反应器就会链接到指定的直线上。修改这条直线时,就会出现图114所示显示有该直线当前长度信息的对话框。图114显示直线当前长度信息的对话框AutoLISP使用反应器2.定义绘制图115所示图形的命令。要求:将对象反应器链接到圆上,如果圆被修改,两条直线与圆的相对位置和相对比例不变。图115一个圆和两条直线组成的图形根据题意,反应器的链接对象是圆。触发事件是圆被修改,从表11-4可以查找出图形对象被修改的事件是:vlr-modified。回调函数的功能是两条直线随之被修改,且修改后与圆的相对位置和相对比例不变。两条直线是与该反应器相关联的对象。AutoLISP使用反应器【例11-5】定义将对象反应器链接到圆上的命令,如果圆被修改,两条直线与圆的相对位置和相对比例不变。(vl-load-com)(defunc:c1l2(/p0p1p2p3p4rr1eh1eh2l1-l2rltvrl)(setqp0(getpointn输入圆心:)(setqr(getdistp0n输入半径:)(commandcirclep0r)(setqr1(*1.25r)(setqec(entlast)(setqp1(polarp00r1)(setqp2(polarp0(*0.5pi)r1)(setqp3(polarp0pir1)AutoLISP使用反应器(setqp4(polarp0(*-0.5pi)r1)(commandlinep1p3)(setqeh1(cdr(assoc5(entget(entlast);第一条直线的句柄(commandlinep2p4)(setqeh2(cdr(assoc5(entget(entlast);第二条直线的句柄(setql1-l2(listeh1eh2);两条直线的句柄表(setqrlt(list(vlax-ename-vla-objectec);圆的图元名转换为VLA对象(setqvrl(vlr-pers(vlr-object-reactorrltl1-l2(:vlr-modified.c-2l);反应器链接到圆上,两条直线的句柄表为关联数据,当发生修改该圆的事件时,调用c-2l函数(princ);静默退出)AutoLISP使用反应器;定义c-2l函数(defunc-2l(notifier-objectreactor-objectparameter-list/ecec_lel1el2ell_1ell_2p0p1p2p3p4p0xp0yp0z)(setqec(vlax-vla-object-enamenotifier-object);VLA对象的圆转换为图元名ec_l(entgetec);圆的图元表p0(cdr(assoc10ec_l);获取圆心的坐标r(*1.25(cdr(assoc40ec_l);获取圆的半径之后1.25)(setqel1(handent(car(vlr-datareactor-object);第一条直线的图元名(setqel2(handent(cadr(vlr-datareactor-object);第二直条线的图元名AutoLISP使用反应器(setqp0x(carp0);获取圆心的X坐标(setqp0y(cadrp0);获取圆心的Y坐标(setqp0z(caddrp0);获取圆心的Z坐标(setqp1(list(+p0xr)p0yp0z);修改直线端点的坐标(setqp2(listp0x(+p0yr)p0z);修改直线端点的坐标(setqp3(list(-p0xr)p0yp0z);修改直线端点的坐标(setqp4(listp0x(-p0yr)p0z);修改直线端点的坐标(setqell_1(entgetel1);第一条直线的图元表(setqell_1(subst(vl-list*10p1)(assoc10ell_1)ell_1);直线的新端点替换直线的老端点(setqell_1(subst(vl-list*11p3)(assoc11ell_1)ell_1);直线的新端点替换直线的老端点AutoLISP使用反应器(entmodell_1);更新第一条直线(setqell_2(entgetel2);第二条直线的图元表(setqell_2(subst(vl-list*10p2)(assoc10ell_2)ell_2);直线的新端点替换直线的老端点(setqell_2(subst(vl-list*11p4)(assoc11ell_2)ell_2);直线的新端点替换直线的老端点(entmodell_2);更新第二条直线)加载以上程序,在Command:提示下输入c1l2命令,输入圆心和半径,即可绘制出图115所示图形。修改这个圆,两条直线将随之按题意的要求改变。在本程序中,与反应器相关联的数据是两条直线的句柄。获取圆心和半径的途径是:将圆的VLA对象转换为图元名。根据圆的图元名获取圆的图元表。从圆的图元表获取圆的圆心和半径。修改直线的途径是:从关联的数据表获取是两条直线的句柄。根据直线的句柄获取直线的图元名。根据直线的图元名获取直线的图元表。修改和更新直线的图元表。调用较多的是普通的AutoLISP函数。AutoLISP使用反应器本例还可以利用ActiveX对象实现相同的功能。程序代码如下:【例145】利用ActiveX对象实现例144的功能(vl-load-com)(defunc:c1l2(/p0p1p2p3p4recel1el2v_cv_l1v_l2l1-l2vrl)(setqp0(getpointn输入圆心:)(setqr(getdistp0n输入半径:)(commandcirclep0r)(setqr(*1.25r)(setqec(entlast)(setqv_c(list(vlax-ename-vla-objectec);圆的图元名转换为VLA对象(setqp1(polarp00r)AutoLISP使用反应器(setqp2(polarp0(*0.5pi)r)(setqp3(polarp0pir)(setqp4(polarp0(*-0.5pi)r)(commandlinep1p3)(setqel1(entlast);第一条直线的图元名(setqv_l1(vlax-ename-vla-objectel1);第一条直线转换为VLA对象(commandlinep2p4)(setqel2(entlast);第二条直线的图元名(setqv_l2(vlax-ename-vla-objectel2);第二条直线转换为VLA对象(setql1-l2(listv_l1v_l2);两条直线的VLA对象表AutoLISP使用反应器(setq vrl (vlr-pers(vlr-object-reactor v_c l1-l2 (:vlr-modified.c-2l);反应器链接到圆上,两条直线的VLA对象表为关联数据,当发生修改该圆的事件时,调用c-2l函数(princ);定义c-2l函数(defunc-2l(notifier-objectreactor-objectparameter-list/p0p1p2p3p4p0xp0yp0zlv_l1v_l2)(setqp0(VLA-get-centernotifier-object);获取圆的圆心,P0是变体(setqp0(vlax-variant-valuep0);将变体转换为安全数组(setqp0(vlax-safearray-listp0);将安全数组转换为表(setqc_r(*1.25(VLA-get-radiusnotifier-object);获取圆的半径之后1.5AutoLISP使用反应器(setqv_l1(car(vlr-datareactor-object);第一条直线的VLA对象(setqv_l2(cadr(vlr-datareactor-object);第二条直线的VLA对象(setqp0x(carp0);获取圆心的X坐标(setqp0y(cadrp0);获取圆心的Y坐标(setqp0z(caddrp0);获取圆心的Z坐标;计算直线端点的新位置再转换为ActiveX的三维点(setqp1(vlax-3d-point(list(+p0xc_r)p0yp0z);(setqp2(vlax-3d-point(listp0x(+p0yc_r)p0z)(setqp3(vlax-3d-point(list(-p0xc_r)p0yp0z)(setqp4(vlax-3d-point(listp0x(-p0yc_r)p0z)AutoLISP使用反应器(vla-put-startpointv_l1p1);更新直线1的起点(vla-put-endpointv_l1p3);更新直线1的终点(vla-put-startpointv_l2p2);更新直线2的起点(vla-put-endpointv_l2p4);更新直线2的终点)本程序中,与反应器相关联的数据是两条直线的VLA对象。直接从圆的VLA对象中获取圆的圆心和半径属性。直接修改直线的起点和终点属性。因此具有程序代码简短、运行速度快的特点。AutoLISP使用反应器
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号