3. acdbEntLast()[ads_entlast()]、acedNEntSel()[ads_nentsel()]、acedNEntSelP()[ads_nentselp()] 在ADS中还有几个其他的实体选择函数:acdbEntLast()、acedNEntSel()和acedNEntSelP()。
先看一下acdbEntLast()函数。AutoCAD始终知道最近生成的一个实体,该实体可以通过acdbEntLast()函数找到。acdbEntLast()函数的定义如下:
acdbEntLast()函数在图形中找出最近的实体,并把图形数据库中最近的(未删除的)主实体名存入result。即使最近的实体在屏幕之外或在冻结的层上也能选到。最近的实体是指最近创建的实体,所以acdbEntLast()函数可用于获得刚加进AutoCAD数据库中实体的实体名。如果acdbEntLast()函数调用成功,返回RTNORM,否则返回RTERROR。
对于块和多段线复杂实体,ADS函数acedNEntSel()和acedNEntSelP()(代表嵌套的实体选择)将选择属性(假定选择了块实体,且块的属性
已定义)和顶点信息(假定选择了多段线)。与acedNEntSel()函数相比,Autodesk推荐使用acedNEntSelP()函数。acedNEntSelP()函数比acedNEntSel()函数增加了更新的内容,所以我们只讨论acedNEntSelP()函数。
下面是acedNEntSelP()函数的定义:这是一个带有许多参数的复杂函数。acedNEntSelP()函数暂停运行等待用户输入,并传回一个实体名
(存入entres)和一个用于选择实体的点(存入ptres)。参数pickflag的值为FALSE或TRUE,用于指定acedNEntSelP()函数是否可以人机交互(即允许用户选择与输入点对应的点)。如果pickflag的值为FALSE,acedNEntSelP()函数提示用户指定实体,参数ptres的初始值被忽略了。如果pickflag的值为TRUE,ptres的初始值被用于选择实体。我几乎未使用过pickflag为TRUE。如果需要其他参数的说明,请参阅ADSRX文档。如果str为NULL,AutoCAD就用标准的“Select objects:|” 提示。我最感兴趣的参数是entres,其中存放一个顶点或一个属性。
3.9 应用程序实例CH3_1要点的进一步分析
在应用程序实例CH3_1.ARX中,就在创建第一个圆之后使用了acedGetXXX()类函数。现在再来看一看这些函数。在while循环中,我
们询问用户是否需要再画一个圆。只要用户不回答“No”,就会不断地要求用户画圆。让我们来观察一下while循环的前两行:
acedInitGet()函数中的关键字表是“Yes No”,第一个参数是NULL,所以我们能够接受空输入。我们本可以使用RSG_NONULL迫使用户打入“Y”或“N”。在一般情况下,AutoCAD的缺省选项用尖括号表示,这里是
”,kw的值将为“No”。然而,如果用户只按Enter键,kw将为一空串。这种情形由switch语句的RTNONE case处理,把“Yes”复制到kw缓冲区。记住acedInitGet()函数只适用于紧跟其后的acedGetXXX()类函数。再次运行该应用程序时,试着输入一些不是“Y”或“N”的字母,看看会发
生什么。你会重复地得到提示直至按下Y、N或Enter键。
如果用户要再画圆,程序就进入if语句的else分支,并要求用户选择圆心,如下面的代码所示:
这里,我们使用RSG_NONULL调用acedInitGet()函数,因为我们要用户选择一个圆心。在下一句的acedGetPoint()函数调用中,注意第一个参数是NULL。记住在acedGetPoint()函数中,第一个参数可以用作选点的参考点。这是第一个点,所以我们使用NULL。当要求选
择圆心时试着按Enter 键,会重新提示选择圆心。
当输入圆半径时,我们使用acedGetDist函数替代acedGetPoint()函数,因为acedGetDist函数的响应允许我们选择一个点或从键盘输入一个距离值。下面是使用acedGetDist()函数的代码:
注意我们怎样用RSG_NONULL、RSG_NOZERO和RSG_NONEG的组合来调用acedInitGet()函数。这是因为我们要使用跟在acedInitGet()
函数设置之后的acedGetDist()函数。acedGetDist()函数中的第一个参数是cp,这是我们前面选定的点。从点cp开始会画出一条橡皮筋线。当用户选定第二点后
,从点cp到第二点之间的距离被存入变量rad,这是一个ads_real数据类型的变量。然而,用户还可用键盘敲入数值。我们不允许零和负数输入,这就是为什么在调用acedInitGet()函数时还包括RSG_NOZERO和RSG_NONEG的原因。
在用户定义的带有一个ads_name类型参数的printEntInfo()函数中,我们调用acdbEntGet()函数检索结果缓冲区链表。如果调用成功,结
果缓冲区链表会包含实体的数据结构,如下列代码段所示:
我们使用rbEnt->rbnext字段来遍历链表,并检测rbEnt->restype字段的值,这一字段表示存储在rbEnt->resval字段中的数据类型。
3.10 选择集
一个选择集就是AutoCAD当前图形中的一组实体,通过名字加以引用,在这里是一个ads_name对象。选择集非常类似于AutoCAD实体的“组(group)”。一旦拥有一个选择集,就可以确定组成选择集的实体数量(也称为选择集长度引用)。既然我们知道了选择集的长度,我们就可以使用循环机制遍历选择集中的每个实体,并读取和修改实体。一个实体在一个选择集中只能表示一次,然而一个实体可以属于多个选择集。如果我们有一个选择集ss1,并希望向选择集中添加一条直线实体,我们可以手工选择直线实体。按规则我们可以多次选择直
线实体,但在选择集中多次选择的实体只表示一次。假定我们现在创建第二个选择集ss2,并选择同一条直线实体,那么该实体就被加到第二个选择集中。现在直线实体出现在ss1和ss2两个选择集中,但在每一个选择集中直线实体只表达一次。
选择集是实体的有名集合,选择集中的实体由AutoCAD用户手工选择或依据实体特性加入。依据特性选择实体,如选择“parts”层上半径小于0.25的所有圆,这允许我们把它们的半径改为0.375。选择集甚至可以选择被冻结的图层上的实体。选择集也可以是空的—它只是存放AutoCAD实体的一个容器,就像放糖果的纸袋一样,如果你没有在里面放糖果或者你已把它们全部吃光,纸袋就空了。表3-6列出了
处理选择集的ADS函数。 表3-6 ADS的选择集函数
选择集函数 说 明 等效的AutoLISP函数 acedSSGet() 选择要加到选择集中的实体 ssget
acedSSLength() 返回指定选择集的长度 sslength
acedSSAdd() 添加实体到已有选择集或新建一空选择集 ssadd acedSSDel() 从已有选择集中删除实体 ssdel
acedSSName() 在选择集中检索出实体的ads_name ssname acedSSMemb() 测试某实体是否为选择集的成员 ssmemb acedSSFree() 释放选择集 —
1. acedSSGet()[ads_ssget()]
选择集是ads_name对象,为了把实体加入到指定的选择集,必须使用acedSSGet()函数选择实体,或者假如预先知道实体名,则可使用acedSSAdd()函数。
下面是acedSSGet()函数的定义:acedSSGet()函数返回一个选择集,当指定了一种AutoCAD选取模式时就获得该选择集,选取模式可以通过AutoCAD用户的提示或过滤图形数据库指定。使用acedSSGet()函数有多种方式。首先我们将说明函数中的各个参数,然后阐述使用acedSSGet()函数的各种方式。
参数str是指定实体选取模式的可选字符串。参数pt1和pt2指定若干选取模式的可选点。对于polygon(多边形)或fence(栏选)选取模式选项,参数pt1还可以是一个含有多个点的结果缓冲区链表。参数filter是一个可选的结果缓冲区链表,能使acedSSGet()函数过滤图形以选
择具有某种类型与(或)具有某种特性的实体。无论你使用哪一种模式来获得选择集,都用参数ss来标识选择集的名称。参数str指定要使用哪一种选取模式,它可以是表3-7所列字符串之一。
从表3-7可以看出有多种选择集的选取模式,如果想探讨所有的选项,可参阅帮助文档。一般我只做两件事:让用户选择实体(NULL选项)或根据特性选择实体(“X”选项)。
下面是一些有代表性的调用acedSSGet()函数的程序代码。如acutBuildList()函数调用示例那样,对于多边形选项CP和WP(但不包括F)
会自动封闭列出的点,不必把终点指定为起点。 表3-7 acedSSGet()函数的选取模式选项:参数str的值 值(选取模式) 说 明
NULL 单点选择(指定pt1)或用户选择(pt1也是NULL) “I” 指定PICKFIRST实体集 “C” Crossing选取模式
“CP” Crossing polygon选取模式 “F” Fence(或open polygon)选取模式 “L” Last选取模式,选择最近生成的实体
“P” Previous选取模式,选择上一个选择集 “W” Window选取模式
“WP” Window Polygon选取模式 “X” 只用于过滤选取模式 “G” Groups选取模式
“:$” Prompts supplied选取模式 “:?” “Other” callbacks选取模式 “:D” Duplicates allowed选取模式 “:E” Everything in aperture选取模式 “:K” Keyword callbacks选取模式 “:N” Nested选取模式 “:S” 单一对象选取模式 “.” 用户选取模式
“#” 非几何选取模式(all、last、previous) “A” All选取模式 “B” BOX选取模式 “M” Multiple选取模式
3.10.1 选择集的过滤
为了使用选择集过滤模式,参数str必须指定为“X”。选择集过滤模式允许依据特性选择实体。过滤参数是一个结果缓冲区表,在这里给acedSSGet()函数详细说明了要使用的实体种类和特性种类。如果过滤参数是NULL,并且参数str为“X”,则选择集ss将包含当前AutoCAD图形中的每一
个实体,而不考虑实体是否在冻结的层上。函数调用如下:
现在选择集ss将包含当前AutoCAD图形中的每一个实体。那么我们怎样选择数据库中所有的圆实体呢?为了有效地使用选择集,必须知道DXF组码。首先我们必须构造一个结果缓冲区,但因为我们只寻找一种实体,所以我们可以使用acutNewRb()函数来创建该结果缓冲区。下面是一段代码实
例:
下面的程序代码实例生成由某一图层上所有的实体组成的选择集。图层的DXF组码是8。
好了,下面我们举一个稍微复杂一点的例子,假定我们要选择“parts”层上的所有圆。这是一个利用acutBuildList()函数构造结果缓冲区表后再传给acedSSGet()函数的实例。