admin 发表于 2024-5-26 08:57:03

acedSSGet()函数用法详解

大多数ObjectARX函数在处理选择集和实体时,都用名字来识别选择集或实体,该名字用一个长整型对来表示的,并对AutoCAD来维护。在ObjectARX中,该名字的类型为ads采用name。
在对选择集或实体进行操作之前,ObjectARX应用程序必须通过调用一个返回其名字的库函数来得到选择集或实体名字。
注意:选择集和实体的名字是不稳定的,它们仅仅在AutoCAD当前图形工作时有效。如果从AutoCAD退出或切换到另一个图形时其值就会丢失。
对于选择集来说,它也是与当前图有关联的,所以其名字的不稳定性不会影响选择集。但是对于实体就不一样了,因为它是被存放在图形数据库中的,名字的不稳定性要影响到对实体的操作。应用程序必须在下一次对同一图文件中的同一实体进行操作,可以使用实体句柄,重新获取其实体名。
选择集的处理
ObjectARX函数对选择集的处理类似于AutoLISP。acedSSGet()函数提供大多数创建选择集方法。它一般通过以下三种方法之一创建选择集:
(1)提供让用户选择对象。
(2)象交互式应用AutoCAD一样,利用RICKFIRST定义、Crossing、Crossing Polygon、Fence、Last、Previous、Window、Window Polygon等匹配条件的方式来选择实体对象,也可以通过指定一个单独点或Fence点来选择。
(3)使用一系列属性和条件筛选当前图数据库来选择实体对象。
该函数原型为:
int acedSSGet(const chat *str,const void *pt1,const void *pt2,const struct resbuf *entmask,ads采用name ss);


acedSSGet()的第一个参数str,说明所使用的选择条件,如下:

表示码 意义
NULL 单点选择(如果指定了pt1)或用户选择(如果pt1也为NULL)
# 非几何选择(all、last、previous)
:$ 提供提示文字
. 用户拾取方式
:? 其他回调函数
A All选择方式
B Box选择方式
C Crossing选择方式
CP Crossing Polygon选择方式
:D 可以重复,即可以重复选择一个实体,并加入选择集中
:E 在aperture中的所有实体
F Fence选择方式
G Groups选择
I 如果存在RICKFIRST集、则用该集
:K    关键字回调函数
L Last选择方式
M 多重选择方式
P Previous选择方式
:S 强制单个实体对象被选择
W Window选择方式
WP Window Polygon选择方式
X 用于筛选程序搜索整个图形数据库


紧跟着的两个参数用于指定与某些选择方式有关的可选择的点。当不使用他们时,应该取NULL值。如果第四个参数entmask不是NULL,则它指向一个缓冲区表,用于存放用筛选选择方式的结果。第五个参数ss是选择集的识别名字。
下列是调用acedSSGet()的例子:

1ads采用point pt1,pt2,pt3,pt4;
2structresbuf* pointlist;
3ads采用name ssname;
4pt1 = pt1 = pt1 = 0.0 ;
5pt2 = pt2 = 5.0 ;pt2 = 0.0 ;
6// 如果有的话,获取当前RICKFIRST选择集,没有则提供用户选择一个
7acedSSGet(NULL,NULL,NULL,NULL,ssname);
8// 如果有的话,获取当前RICKFIRST选择集
9acedSSGet(“I”,NULL,NULL,NULL,ssname);
10// 使用最近使用过的选择集
11acedSSGet(“P”,NULL,NULL,NULL,ssname);
12// 选择最后加入到数据库中的对象
13acedSSGet(“L”,NULL,NULL,NULL,ssname);
14// 选择通过点(5,5)的实体
15acedSSGet(NULL,pt2,NULL,NULL,ssname);
16// 选择从点(0,0)到点(5,5)的窗口中的实体
17acedSSGet(“W”,pt1,pt2,NULL,ssname);
18
19// 选择指定多边形包围的实体
20pt3 = 10.0 ;pt3 = 5.0 ;pt3 = 0.0 ;
21pt4 = 5.0 ;pt4 = pt4 = 0.0 ;
22pointlist = acutBuildlist(RTPOINT,pt1, RTPOINT,pt2, RTPOINT,pt3, RTPOINT,pt4, 0 );
23acedSSGet(“WP”,pointlist,NULL,NULL,ssname);
24
25// 选择选择从点(0,0)到点(5,5)的窗口内交叉的实体
26acedSSGet(“C”,pointlist,NULL,NULL,ssname);
27
28acutRelRb(pointlist);
29
30// 选择与指定栅栏交叉的实体
31pt4 = 15.0 ;pt4 = 0.0 ;
32pointlist = acutBuildlist(RTPOINT,pt1, RTPOINT,pt2, RTPOINT,pt3, RTPOINT,pt4, 0 );
33acedSSGet(“F”,pointlist,NULL,NULL,ssname);
34acutRelRb(pointlist);




对acedSSGet()的补充函数是acedSSFree(),它能在应用程序用完选择集后释放选择集。选择集是按名字来被使用的。对上面程序段中定义的ads采用name,在这里使用为:
acedSSFree(ssname);

注意:AutoCAD不能同时打开多于128个选择集,包括运行中的ObjectARX和AutoLISP应用程序打开选择集的总和。在不同的系统有可能有所不同。如果超过上限,AutoCAD拒绝创建选择集。因此在不用选择集时,应尽快用acedSSFree()释放。

选择集筛选表
当acedSSGet()函数的entmask参数明确记录了实体的范围值列表时,acedSSGet()扫描被选择的实体,同时建立一个包含主实体名的选择集,这些实体与筛选条件相匹配。比如,使用这种方法,用户可以得到一个给定的选择集,这个选择集包括给定的层、类型、颜色的所有实体。
筛选表可以与任何的选择项联合使用。如果用“X”选择方式,意味着建立一个仅使用筛选表的选择集。在AutoCAD以前的版本中,如果用“X”选项,acedSSGet()将扫描全部图形数据库。
注意:要是仅仅筛选表指定为“X”,而参数entmask是NULLL,则acedSSGet()选择所有在数据库中的实体。
参数entmask必须是一个结果缓冲区表。每一个缓冲区指定一个检查参数和匹配的值;缓冲区的restype段是一个DXF组码,它指定要查询的参数的种类,而缓冲区的restype域指定要匹配的值。下面是相应的例子:

ExpandedBlockStart.gif 代码
structresbuf eb1,eb2,eb3;
charsbuf1[ 10 ],sbuf2[ 10 ];
ads采用name ssname1,ssname2;
eb1.restype = 0 ;// 实体名
strcpy(sbuf1,”CIRCLE”);
eb1.resval.restring = sbuf1;
eb1.rbnext = NULL;// 无其他内容
// 检索所有圆
acedSSGet(“X”,NULL,NULL, & eb1,ssname1);

eb2.restype = 8 ; // 层名
strcpy(sbuf2,”FLOOR3”);
eb2.resval.rstring = sbuf2;
eb2.rbnext = NULL;
// 检索在图层FLOOR3上的所有实体
acedSSGet(“X”,NULL,NULL, & eb2,ssname2);




注意: 在每个缓冲区中指定的resval必须属于合适的类型,比如:名字类型是字符串(resval.rstring);标高和厚度是双精度浮点型(resval.rreal);颜色、属性和标志值是短整型(resval.rint);拉伸向量是三维的点(resval.rpoint),等等。
如果entmask指定了多个参数,那么只有匹配所有指定条件的实体才能被包含在选择集里。就象下面的例子:
1eb2.restype = 62 ; // 实体颜色
2eb3.resval.rint = 1 ; // 红色
3eb3.rbnext = NULL;
4eb1.rbnext =& eb2; // 增加另外两个条件
5eb2.rbnext =& eb3; // 建立链表
6// 检索在图层FLOOR3层上所有红色的圆
7acedSSGet(“X”,NULL,NULL, & eb1,ssname1);


除非表中包括关系和条件操作符,否则实体的所有域都要被测试。
如果在数据库中没有实体与指定的筛选条件匹配,函数acedSSGet()将返回RTERROR。
前面关于acedSSGet()的例子用的是“X”选项,它扫描整个图形数据库;如果筛选表与其他选项(如用户选择、窗口选择等)联合使用,筛选条件只能在被选中的实体上起作用。请看下面的一组例子:
筛选用户选择的实体:
1eb1.restype = 0 ; // 实体类型组
2strcpy(sbuf1,”TEXT”);
3eb1.resval.rstring = sbuf1; // 类型为TEXE
4eb1.rbnext = NULL;
5
6// 让用户生成选择集,但该选择集中只能有TEXT实体
7acedSSGet(NULL,NULL,NULL, & eb1,ssname1);
筛选前一个选择集:

1eb1.restype = 0 ; // 实体类型组
2strcpy(sbuf1,”LINE”);
3eb1.resval.rsting = sbuf1; // 类型为LINE.
4Eb1.rbnext = NULL;
5// 选择在上一个选择集中符合条件的实体
6acedSSGet(“P”,NULL,NULL, & eb1,ssname1);


在选择窗口内筛选实体:

1eb1.restype = 8 ; // 层
2strcpy(sbuf1,”FLOOR8”);
3eb1.resval.rstring = sbuf1; // 层名
4eb1.rbnext = NULL;
5// 选择在窗口内并在FLOOR8层上的实体
6acedSSGet( " W " , pt1, pt2,& eb1, ssname1);


注意:某些组码在不同的实体里有不同的含义,并且不是所有的组码都存在于所有的实体内。如果在筛选程序中指定一个特定的组码,不包含该组码的实体将被排除在acedSSGet()所返回的选择集之外。



筛选表中的通配符
筛选表中指定的符号可以包括通配符。由函数acedSSGet()织别的通配符与函数acutWcMatch()织别的通配符完全一样。
例如,下面的程序代码可以检索一个名为K2的匿名块:

1eb2.restype = 2 ; // 块名
2strcpy(sbuf1,” * K2”);
3eb2.resval.rstring = sbuf1; // 匿名块名
4eb2.rbnext = NULL;
5// 选择匿名块*K2的块插入引用
6acedSSGet(“X”,NULL,NULL, & eb2,ssname1);




筛选扩展数据
扩展数据是字符串、数据、三维点、距离、层名,或者是其他附加在对象上得数据,特别是由外部应用程序附加到对象上得数据。
扩展数据大小为16KB。
通过指定,我们可以为一个特殊的应用程序使用-3组码在筛选表中指定扩展数据来检索扩展数据。例如:,函数acedSSGet()返回一个以指定名字注册的带扩展数据的实体。acedSSGet()不检索每个扩展数据项(组码的范围为1000—2000)。
下面程序用于选择所有带有扩展数据的圆(Circle),应用程序为这些扩展数据注册的一个标志符(ID)为“APPNAME”。



1eb1.restype = 0 ; // 实体类型
2strcpy(sbuf1,”CIRCLE”);
3eb1.resval.rstring = sbuf1; // 实体为CIRCLE
4eb1.rbnext =& eb2;
5eb2.restype =- 3 ; // 扩展数据
6eb2.rbnext =& eb3;
7eb3.restype = 1001 ;
8strcpy(sbuf2,”APPNAME”);
9eb3.resval.rstring = sbuf2; // APPNAME应用程序
10eb3.rbnext = NULL;
11// 选择注册到APPNAME应用程序中的圆的扩展数据
12acedSSGet(“X”,NULL,NULL, & eb1,ssname1);


如果不止一个应用程序名包含在表中,则acedSSGet()在选择集中所包含实体,必须对所有指定的应用程序都有扩展数据。比如,下面的程序选择带有注册到“APP1”和“APP2”中的扩展数据的圆。

1eb1.restype = 0 ; // 实体类型
2strcpy(sbuf1,”CIRCLE”);
3eb1.resval.rstring = sbuf1; // 圆
4eb1.rbnext =& eb2;
5
6eb2.restype =- 3 ; // 扩展数据
7eb2.rbnext =& eb3;
8eb3.restype = 1001 ;
9strcpy(sbuf2,”APP1”);
10eb2.resval.restring = sbuf2; // 应用程序APP1
11eb2.rbnext =& eb4;
12eb4.restype = 1001 ; // 扩展数据
13strcpy(sbuf3,”APP2”);
14eb4.resval.rstring = sbuf3; // 应用程序APP2
15eb4.rbnext = NULL;
16// 选择注册应用程序APP1和APP2的圆扩展数据
17acedSSGet(“X”,NULL,NULL, & eb1,ssname1);


下面的程序与上面的作用相同。

1eb1.restype = 0 ;
2strcpy(sbuf1,”CIRCLE”);
3eb1.resval.rstring = sbuf1;
4eb1.rbnext =& eb2;
5
6eb2.restype =- 3 ;
7eb2.rbnext =& eb3;
8eb3.restype = 1001 ;
9strcpy(sbuf2,”APP[ 12 ]”); // ”APP”
10eb3.resval.rstring = sbuf2;
11eb3.rbnext = NULL;
12// 选择注册到APP1和APP2的圆的扩展数据
13acedSSGet(“X”,NULL,NULL, & eb1,ssname1);




关系检测

除非用户另外指定,在一个筛选表中的每一项与实体之间,有一个隐含的等量(equals)检测,对于数字量(整数、实数值、点和向量),通过在筛选表中包括关系操作符,用户可指定另外一些关系,关系操作符当做一个特殊的组(即-4组)传递,其值是一个在筛选表中将被应用于下一组检测的字符串。
下面的程序可以挑选半径大于等于2。0的圆:

1eb3.restype = 40 ; // 半径
2eb3.resval.rreal = 2.0 ;
3eb3.rbnext = NULL;
4
5eb2.restype =- 4 ; // 筛选操作
6strcpy(sbuf1,” >= ”);
7eb2.resval.rstring =& eb3;
8
9eb1.restype = 0 ; // 实体类型
10strcpy(sbuf2,”CIRCLE”);
11eb1.resval.rstring = sbuf2; // 圆
12eb1.rbnext =& eb2;
13
14// 选择半径大于等于2。0的圆
15acedSSGet(“X”,NULL,NULL, & eb1,ssname1);




条件筛选

条件操作符也可由-4组指定,但它们必须是配对的。下面的的程序用来挑选半径为1。0的圆,并且在“ABC”层上的所有直线:

1structresbuf *prb;prb=acutBuildList( - 4 ," <or " , - 4 ," <and " , RTDXF0,   " CIRCLE " ,40 ,1.0 ,- 4 ," and> " ,- 4 ," <and " , RTDXF0,      " LINE " ,8 ," ABC " ,- 4 ," and> " ,- 4 ," or> " ,0 );
2acedSSGet( " X " , NULL, NULL, prb, ssname1);


条件操作符不是大小写敏感的,可以使用小写形式。

用于检测扩展数据的条件表达式只能包含-3组。为了选择带有寄存于“APP1”和“APP2”其中之一的扩展数据的所有圆,可以用以下程序来实现:

1prb=acutBuildList( - 4 ," <xor " ,- 3 ," APP1 " ,- 3 ," APP2 " ,      - 4 ," xor> " ,0 );
2acedSSGet( " X " , NULL, NULL, prb, ssname1);

admin 发表于 2024-5-26 08:59:15

int acedSSGet(
    const ACHAR * str,
    const void * pt1,
    const void * pt2,
    const struct resbuf * filter,
    ads采用name ss
);
参数详解:

   const ACHAR * str:选择模式(例如框选窗选)

   const void * pt1 :两个point和某些模式是相关联的,例如多边形框模式,还有可能是两个字符串指针,用来代替acedSSget的提示,例如:$模式
   
   const void * pt2 :同上

    const struct resbuf * filter :根据具体需求过滤掉某些并不需要的实体,例如我只想选择圆并且图层在CIRCLE图层上
   

    ads采用name ss:存储了选择的结果
   

   
    注意事项:
   
   

   
   

   
    1.得到的选择集再用完之后,一定要记得释放ads采用ssfree(ss) ;
   
   

   
   

   
    2.选择模式一共有三种分别是
   
    Selection Method Mode Options
   
    .
   
    Colon Mode Options.
   
    Keyword Filter Mode Options
   
   

   
   

   
    再绝大多数情况下, selection method mode不能够和包含colon mode或者keyword filter mode options的模式一起用,
   
   

   
   

   
    唯一准许的情况是":U" and ":V"这两种情况 。Colon mode options 能够和keyword filter mode 能够混用,并且可以使用多种合理组合,例如
   
    (
   
    "-#-W:$:?:K:N").
   
   
   
   

   
   

   
    3.对于
   
    "CP"
   
   and
   
    "WP"
   
   ,会自动闭合你提供的点链表,你没有必要提供一个闭合的点,言外之意你没有必要使第一个点等于最后一个点
   
   

   
   

   
    4.如果你希望你所书写的代码能够在任意一个版本都运行良好,请使用
   
   ("采用") 作为模式字符串的前缀
   
   

   
   

   
    实例解析:
   
   

   
   

   
    需求,我希望获得一个长度,点选一个直线实体获得长度,或者直接在命令行中输入长度
   
   

   
   

   
    分析:
   
   

   
   

   
    大家首先想到的就是acedEntSel,但是这个函数没有办法获得一个数字字符串(我是没发现怎么可以)
   
   

   
   

   
    用acedSSGet就比较容易实现这样的需求,前提是你仔细阅读文档,并且多加实验
   
   

   
   

   
    实现:
   
   

   
   

   
    typedef resbuf* (*ssgetcallback)(const TCHAR*) ;
   
   

   
   

   
    resbuf* keywordCallback(const TCHAR* str);
   
   

   
   

   
    struct resbuf* otherCallback(const TCHAR* str) ;

   
   

   
   

   
    void TestSSGet()
   
   

   
   

   
    {
   
   

   
   

   
            resbuf* filter = ads采用buildlist( RTDXF0 , 采用T("LINE") ,0 ) ;
   
   

   
   

   
            //用于替换掉默认的字符串(并且加了关键字)
   
   

   
   

   
            //注意在这里关键字并没有起任何作用,但是你可以让它发挥作用如果你需要的话
   
   

   
   

   
            TCHAR* promtStr ;
   
   
        promtStr = 采用T("") ;
        promtStr = 采用T("") ;






   
           //下面设置关键字回调和非关键回调






   
           //首先保存一下系统默认回调






   
           ssgetcallback keyworldCallBackOld = NULL ;






   
           ssgetcallback otherkeyworldCallBackOld = NULL ;






   
          
   
   acedSSGetKwordCallbackPtr(&
   
   keyworldCallBackOld
   
   ) ;






   
          acedSSGetOtherCallbackPtr(&otherkeyworldCallBackOld) ;






   
           //设置回调






   
           acedSSSetKwordCallbackPtr( keywordCallback ) ;
        acedSSSetOtherCallbackPtr( otherCallback ) ;






   
           //单选并且只能选取一次用关键字:S(想使用关键字:S必须加"+.")






   
           //替换掉默认提示必须加关键字:$






   
           //使用关键字必须加:K






   
           ads采用name name ;






   
           int iResult = acedSSGet( 采用T("采用+.:S:$:K:?") , promtStr , 采用T("N R 采用 N R") , filter , name );






   
          






   
           //恢复回调函数






   
          

   
           acedSSSetKwordCallbackPtr(
   
   keyworldCallBackOld
   
   ) ;
        acedSSSetOtherCallbackPtr(
   
   otherkeyworldCallBackOld
   
   ) ;


   
   

   
    }
   
   

   
   

   
    resbuf* keywordCallback(const TCHAR* str)
{
       

   
            acutPrintf(采用T("\n你输入了一个关键字"), str);
        return NULL;
}
struct resbuf* otherCallback(const TCHAR* str)
{
        acutPrintf(采用T("\n在这里判断它是不是一个数字字符串,如果是转化成数字供你使用!!!!!!"), str);
   
   

   
   

   
           

   
    //注意 根据我的项目需求如果符合条件了,就应该退出,那么在这里如果判断输入数据合法,就应该手动发送一个
   
   

   
   

   
    //取消,这个根据个人需求写代码
        return NULL;
}
   
   







   
   写的好辛苦,我这有部分代码粘贴的有部分手写的,因为我项目中的代码比这要复杂






   
   







   
   强烈推荐看一下arx提供的demo ArxDebug项目,里面有一个命令ArxDbgTestSelSet大家搜一下,比我这个强大,看一下更容易上手


有什么问题欢迎交流

补充一个条件和判断的代码吧
return AcRx::kRetOK ;
ads采用name name;
resbuf* filter = ads采用buildlist( -4 , 采用T("<OR") ,
-4 , 采用T("<AND") , RTDXF0 , 采用T("LINE") , 8 , 采用T("0") , -4 , 采用T("AND>") ,
-4 , 采用T("<AND") , RTDXF0 , 采用T("CIRCLE") , -4 , 采用T(">=") , 40 ,10000.0 , 采用T("AND>") ,
RTDXF0 , 采用T("DIMENSION") ,
-4 , 采用T("OR>") ,
0 ) ;
acedSSGet( NULL , NULL , NULL , filter , name ) ;
选择以下三种类型实体
1.在图层“0”上的直线
2.半径大于10000的圆 (即使是整数,也必须写为10000.0)
3.任意标注实体
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/panzhijiepanzhiyang/article/details/40824173
页: [1]
查看完整版本: acedSSGet()函数用法详解