搜档网
当前位置:搜档网 › ADS基础

ADS基础

ADS基础
3.1 ADS的历史
当Autodesk发布基于OS/2操作系统的AutoCAD R10时,推出了一种全新的称为AutoCAD开发系统(ADS)的编程环境。ADS是一个带有Autodesk提供的库文件和头文件的C语言编程环境。随着AutoCAD R11的发布,AutoCAD的DOS版本用户也可以使用ADS了。在AutoCAD R11之前,大多数的应用程序
都是用AutoLISP开发的,当出售开发的第三方应用程序时,无法避免用户读取你的源代码。有一些应用程序可用来加密LISP代码—其思想由Kelvinator提出。然而,随着开发者队伍的日益强大,又有了一些可以解密源代码的应用程序。我个人从未使用过Kelvinator程序,总之,我认为如
果能领会我编写的代码,你就有足够能力编写AutoLISP应用程序。
所以后来出现了ADS,也就有了一种编译应用程序的手段。AutoCAD ADS应用程序呈现两种模式:实模式和保护模式。实模式的应用程序工作在DOS的640K常规内存范围内,而保护模式的应用程序能借助DOS的扩展内存打破640K的限制。开发ADS应用程序可以使用多种编译器。在实模式环境,
可以使用Borland的Turbo C或Microsoft C 5.1;而在保护模式环境,可以使用MetaWare High C、Zortech C++或Watcom C。那时保护模式的编译器比较昂贵。我研究后决定使用Watcom的产品。
既然现在有了ObjectARX,为什么还必须了解ADSRX呢?因为AutoCAD提供的ObjectARX中包含了ADS函数库,并称之为ADSRX。令人高兴的是我们不必精通ADSRX的各个方面。ADSRX主要用于下列三个方面:
ナ获取用户输入。
ナAutoCAD的选择集。
ナDCL类型的对话框,详见第6章。
利用ADSRX把已有的ADS应用程序转换成ObjectARX应用程序是比较容易的。如果你是AutoCAD编程的初学者,就直接学习ObjectARX的方法来进行程序开发。随着AutoCAD版本的提高和ObjectARX的升级,ADS最终将被淘汰。在AutoCAD/ObjectARX 2000中,形如ads_XXX的函数名大部分已被新的
函数名替换。在函数名发生变化的地方,我将以如下形式表示新老函数名:
新的ObjectARX 2000函数名[老的ads_XXX函数名]
我知道许多读者已经积累了大量的程序,很高兴告诉你ObjectARX 2000提供了一个名为migrtion.h的文件。如果你在工程文件中包含了该文件,这种新老函数名的转换将会自动进行,所以不必为此担忧。请注意在AutoCAD的下一个版本中,将不再提供migrtion.h文件。这仅是协助将ADS代
码转换为ObjectARX 2000的一个临时措施。
3.2 ADS中定义的变量、类型和常数值
有四个ADS使用的头文件,其文件名分别为adslib.h、ads.h、adscodes.h和adsdlg.h。头文件adsdlg.h用于DCL (对话框控制语言) 类型的对话框,这是第6章的主题。ObjectARX 2000提供了大量的数据类型(这些数据类型也适用于AutoCAD R14开发的ObjectAR

X 2.02)。然而,仍然使用着一
些老的ADS(ADSRX)数据类型。在应用程序中,当使用#include 时,应用程序将自动为你包含ads.h和adscodes.h文件。在ads.h文件中,许多类型定义说明如下。
1. 实数
在AutoCAD中,实数是双精度浮点数值,在ads.h文件中定义如下:
当在AutoCAD中使用双精度数时,可使用ads_real。
2. 点
在AutoCAD中,点就是X、Y和Z的位置,在ads.h文件中定义为数组类型,如下所示:
一个ads_point点就是一个具有三个ads_real数值的数组。在处理点的数值和点的计算时,在ads.h文件中很容易找到如下定义:
在下面的代码段中,我们定义了两个点变量pt1和pt2。表明了怎样初始化一个点,怎样使一个点与另一个点相等。
为了方便,AutoCAD在ads.h文件中提供了一个名为acdbPointSet()的复制宏。为了在应用程序中使用acdbPointSet()宏,必须在应用程序中包含string.h文件。
下面的代码段使点to与点from相等:
3. 转换矩阵类型
在这里我只想谈论一下转换矩阵类型的定义—在讨论选择集时再详细论述转换矩阵。一个转换矩阵就是一个具有ads_real实数值的4×4阶数组,在ads.h文件中定义如下:
4. 有用的常数值
在adslib.h文件中,可以找到如下有用的定义为你提供方便。
另一个有用的定义是PAUSE符,这是一个包含单个反斜线符号的字符串,用于acedCommand()和acedCmd()函数(后面讨论)。在定制菜单宏时,反斜线符号代表一个停顿点,允许用户用命令序列输入信息。
5. 结果缓冲区和类型码
虽然结果缓冲区(resbuf)在ObjectARX中仍然使用,但其使用本意已发生了改变。下面首先说明什么是结果缓冲区,然后说明怎样在ADS中使用结果缓冲区,最后说明怎样在ObjectARX中使用结果缓冲区。结果缓冲区结构resbuf在ads.h文件中定义,其中包含的联合体ads_u_val考虑了在Auto
CAD和ADS中使用的各种数据类型。
联合体ads_u_val如下:
结构resbuf如下:
利用此结构的rbnext字段可以把多个结果缓冲区链接成一单链表。当rbnext等于NULL时,表示到达了链表的结尾。通常定义二个 resbuf 指针,一个指向链表的开头,另一个用来遍历链表。restype字段用来表示在联合体的 resval 字段中存储的数据类型。restype字段中包含有在adscode
s.h文件中定义的许多预定义“结果类型码”中的一个,如表3-1所示。
表3-1 结果类型码
结果类型码说 明
RTNONE 无结果值
RTREAL 实数(浮点数)值
RTPOINT 二维点(X和Y;Z==0.0)
RTSHORT 短整数(16位)
RTANG 角度
RTSTR 字符串
RTENAME 实体名
RTPICKS 选择集名
(续)
结果类型码说 明
RTORINT 方位
RT3DPOINT 三维点(X、Y和Z)
RTLONG 长整数(32位)
RTVOID 无值(空)符号
RTLB 表开头(用于嵌套表)
RTLE 表结尾(

用于嵌套表)
RTDOTE 点(用于点对)
RTT AutoLISP真值(true)
RTNIL AutoLISP无值(nil)
RTDXF0 DXF组码零(仅用于acutBuildList()函数)
现在我们来讨论怎样在ADS中使用结果缓冲区表。在ADS中访问实体时,我们先使用acedEntSel()函数来选择实体,然后再使用acdbEntGet()函数来获得实体的数据。后面我们将讨论acedEntSel()函数。ADS函数acdbEntGet()返回一个结果缓冲区链表。随后我们遍历该结果缓冲区链表,以确
定我们要处理什么类型的实体,该实体具有什么样的特性。
图3-1 结果缓冲区链表
在ADS中(在AutoLISP中也一样)要访问实体的必要条件之一就是要知道并理解DXF组码。如图3-1所示的结果缓冲区链表表示在“0”层上有一个“圆(Circle)”实体,圆心为(5,5,0),半径为2.24086,平放在WCS的XY平面。假定我们有两个指向结果缓冲区的指针rb1和tb1如下:
在经过acedEntSel()和acdbEntGet()操作后,*rb1将指向一结果缓冲区。
以下面的方式遍历链表,往下移动指针*tb1。
假定我们要指定一个ads_real类型的变量rad存放图3-1所示的圆半径,我们就要检查结果缓冲区的restype字段以确认其值为40(圆半径的DXF组码为40)。
稍后我们将编写一个应用程序来画出这个圆,并对其进行修改。这样,你将获得在ADS中使用结果缓冲区的感受。ObjectARX也使用结果缓冲区,但与ADS是完全不同的。在ADS中结果缓冲区用于访问实体、符号表、浏览器,也用于acedCommand()、acedCmd()和acutBuildList()函数,所有这
些将在后面讨论。我不想在ObjectARX不再适用的结果缓冲区方面钻得太深,因为ObjectARX有比这好得多的机制来处理实体的访问、修改与创建以及对符号表的访问。只不过要知道在ObjectARX中仍将处理结果缓冲区。在ObjectARX中,所有的实体都是类,每一个类有查询和编辑函数,用
这些函数可以对实体进行操作。对于符号表的访问,ObjectARX有符号表浏览器类,它允许在不使用结果缓冲区的情况下遍历整个符号表,这也是为什么我不想在ADS的这一方面深究的部分原因。
6. ADSRX函数的返回类型
在开始讨论acedCommand()、acedCmd()和acutBuildList()函数之前,必须谈论一下ADSRX库函数的返回类型。ADS使用表3-2所示的返回类型码表示调用ADS库函数的成功、失败或特殊情况(如用户取消),这些返回类型码在adscodes.h文件中定义。
表3-2 库函数返回类型码
返回类型码说 明
RTNORM 用户输入值有效,正常
RTERROR 函数调用失败
RTCAN 用户按了Esc键
RTREJ AutoCAD拒绝无效请求
RTFAIL AutoLISP通信失败
RTKWORD 用户输入键盘或任意文字
并非所有的ADSRX库函数都返回这些状态码,某些库函数直接返回数值。我们最感兴趣的返回类型码是RTNORM、RTERROR、RTCAN和RTKWO

RD。
3.3 ADSRX中的AutoCAD命令
1. acedCommand()[ads_command()]
现在让我们把注意力转向acedCommand()函数。其定义如下:
acedCommand()函数的参数表是可变长的。acedCommand()函数的参数是成对处理的。每对参数中的第一个表示参数的类型,第二个表示其实际的数据。参数表中的最后一个必须是单个参数,其值为0或RTNONE。每个表示参数类型的参数值必须为表3-1列出的在adscodes.h文件中定义的结果
类型码中的一个(例如RTPOINT)。acedCommand()函数可执行任一AutoCAD命令,就像在键盘输入命令一样。为画出图3-1所示结果缓冲区链表列举的圆,可执行acedCommand()函数,如下所示:
使用单个0也可以结束参数表,但使用RTNONE更好些。圆心是一个点,半径是一个实数,但为什么使用RTSTR类型呢?如果考虑输入的值,它们都用双引号,就像在命令提示下输入命令一样,是字符型。也可按如下方式调用该函数:
在这段代码中,注意我们是借助返回码符号RTNORM来判断ADSRX库函数acedCommand()是调用成功还是调用失败。而acedCmd()和acutBuildList()函数是用在哪里呢?
2. acedCmd()[ads_cmd()]
acedCmd()函数的定义是:
注意此函数有一个resbuf指针类型的参数。该 resbuf 指针从何而来?它来自acutBuildList()函数。利用acedCommand()函数,实质上是为要执行的命令构造一个 resbuf 结构,只是在编译时就知道参数的值。利用acedCmd()函数,我们可以构造一个运行时的 resbuf 结构,在运行时把参
数传递到acedCmd()函数。下面我们来关注一下acutBuildList()函数。
3. acutBuildList()[ads_buildlist()]
acutBuildList()函数的定义如下:
acutBuildList()函数创建一个结果缓冲区链表。注意acutBuildList()函数返回一个指向resbuf 结构的指针,如果调用失败则返回NULL。上面提到并非所有的ADSRX函数都返回表3-2列出的类型码,这是其中之一。该函数像acedCommand()函数一样,其参数表是可变长的。下面我们来看一
看用acedCmd()函数创建一直线实体。
4. acutRelRb()[ads_relrb()]
观察上面代码段的最后部分,我们使用了一个新的函数,其名为acutRelRb()。该函数用来释放结果缓冲区,其定义如下:
acutRelRb()函数释放分配给结果缓冲区或结果缓冲区链表的内存。ADS函数acutBuildList()为结果缓冲区链表分配内存,直到我们释放该内存。如果acutRelRb()函数调用成功,则返回RTNORM(尽管我未做过测试)。有时只需要单个结果缓冲区,而非结果缓冲区链表。ADS函数acutNewRb()
可方便地用于这种情况,稍后我们将看到其应用的例子。
5. acutNewRb()[ads_newrb()]
acutNewRb()函数的定义为:
acutNewRb()函数分配一新的结果缓冲区,并设置restype字段为v。acutNewRb()函数返回一个指向新分配的结果缓

冲区的指针。参数v应为在adscodes.h文件中定义的结果类型码中的一个(例如RTPOINT)。别忘记调用acutRelRb()函数释放用acutNewRb()函数分配的内存。
3.4 向用户发送信息
向用户发送信息由下列三个ADS函数来实现:acutPrompt()、acutPrintf()和acedAlert()。
1. acutPrompt()[ads_prompt]
acutPrompt()函数在命令行显示一段信息,其定义如下:
如果acutPrompt()函数调用成功返回RTNORM,否则返回一错误码。函数的参数是一指向字符串常量的指针,函数不能改变字符串的内容。
执行上述语句,在命令行将提示:
2. acutPrintf()[ads_printf()]
acutPrintf()函数的定义如下:
acutPrintf()函数等同于标准C库函数printf(),只是acutPrintf()函数在文本屏幕显示输出。acutPrintf()函数在向AutoCAD发送字符串之前,把要输出的字符串保存在一内部缓冲区中。该缓冲区含有133个字节,所以,调用acutPrintf()函数显示的信息不能超过132个字符。acutPrintf(
)函数使用与C语言中的printf()函数完全相同的扫描码,如下例所示:
执行的结果是在文本屏幕或命令行输出如下提示:
如果acutPrintf()函数调用成功返回RTNORM,否则返回一错误码。
3. acedAlert()[ads_alert()]
acedAlert()函数显示一个带有错误或警告信息的警告框,其定义如下:
该函数显示一个带有错误或警告信息的警告框,其错误或警告信息由参数str传递。警告框就是具有一个OK按钮的对话框。如果要显示多行信息,可以在字符串中包含换行字符(用‘\n’表示)。字符串最多可含132个字符(第133个字符保留用作字符串结束符号)。
如果acedAlert()函数调用成功返回RTNORM,否则返回RTERROR。
3.5 应用程序实例CH3_1
本章的所有应用程序实例均由ObjectARX 2000向导(Wizard)建立。ObjectARX 2000向导把所有的用户定义的命令放在一个名为Commands.cpp的文件中。在该应用程序实例中,示范了各种ADSRX数据类型和下列ADS函数的应用:
在实例中,还示范了怎样遍历一个结果缓冲区链表。在本应用程序实例中,有许多函数还未谈及,但在本章稍后我们将会进行讨论。这些函数如下所示:
我们首先列出应用程序,然后讨论其要点。Ch3_1.cpp文件的内容如下:
用户定义的命令RBCIRC放在Ch3_1Commands.cpp文件中,其内容如下:
3.6 应用程序实例CH3_1要点分析
本应用程序有一个必需的入口点函数acrxEntryPoint()。在AutoCAD启动过程中(如果acad.rx文件中有此应用程序文件名)或当用户使用ARX命令加载此应用程序时,入口点函数acrxEntryPoint()就调用用户定义的initApplication()函数。上述任何一种情况应用程序均将接收到AcRx::kInit
AppMsg消息。initApplication()函数调用用户定义的AddCommand()函数,后者负责acedRegCmds->addCo

mmand()函数的调用。这样就把我们要定义的命令RBCIRC(Result Buffer CIRCle)添加到了命令栈。当终止AutoCAD的运行或者用户使用ARX命令卸载此应用程序时,应用程序会接收到一
条AcRx::kUnloadAppMsg消息,此消息促使应用程序调用unloadApplication()函数。unloadApplication()函数通过对acedRegCmds->removeGroup()函数的调用从命令栈中移去我们定义的命令组。如果你对这部分内容还有点模糊,请参阅第1章,在那里我们详细讨论了开始和运行ARX应用程
序的机制。
我们增加了两个用户定义的函数:rbcirc()和printEntInfo()。rbcirc()函数负责画出图3-1所示结果缓冲区描述的圆。printEntInfo()函数负责遍历结果缓冲区并显示所画圆的信息。在rbcirc()函数中,圆是通过调用acedCommand()函数创建的,如下所示:
注意,ads_point类型的变量cp声明和初始化是一次进行的:
也可以这样来声明和初始化cp:
下一个函数是acdbEntLast,稍后我们将做详细讨论。它捕捉由AutoCAD画出的最近一个实体,并把其ads_name名保存在circEnt中。我们在调用遍历结果缓冲区链表的printEntInfo()函数时使用circEnt。在rbcirc()函数的while循环中,会询问用户是否要再画一个圆实体。许多用户输入函
数我们还未谈及,后面将会介绍。请注意调用acutBuildList()函数构造结果缓冲区链表的地方,我们依次把它传给acedCmd()函数以画出圆实体。
printEntInfo()函数是遍历结果缓冲区链表之处,该函数要求一个ads_name类型的参数。AcdbEntGet()函数以最近生成实体为参数,对结果缓冲区指针rbEnt赋值,实体作为参数传递。结果缓冲区有一个rbnext字段,它指向下一个结果缓冲区。该字段允许我们构造一个结果缓冲区链表。我
们还定义了另一个结果缓冲区指针rbTrav,用来遍历结果缓冲区链表。在执行rbTrav = rbEnt时设置指针rbTrav指向链表的起点。注意在while循环的结尾有一句rbTrav = rbTrav->rbnext。该语句使我们从一个结果缓冲区移到下一个结果缓冲区—只要有可指向的结果缓冲区,while循环就
为真。在switch语句中检查restype字段。在这里你必须知道DXF码。调试应用程序时,在while循环结束之前的rbTrav = rbTrav->rbnext语句处放置一个断点,然后在变量窗口中观察rbEnt所指结果缓冲区的值。确定变量窗口显示Locals标签,如图3-2所示。
图3-2 调试模式的结果缓冲区
3.7 获取用户信息
大多数应用程序需要获取用户输入以同ADS进行对话,ADS提供了丰富的用户输入函数和技术。如果你使用过AutoLISP的输入函数,就会发现ADS与此非常类似。所有的ADS用户输入函数均具有acedGetXXX()的形式,这里的XXX是输入数据的类型。有些输入数据的类型是显而易见的,下面我们
先列出所

有的acedGetXXX()类函数,然后逐个加以讨论。
acedGetXXX()类函数如下:
acedInitGet()函数是干什么的?acedInitGet()并不是印刷错误—它控制acedGetXXX()类函数的用户输入,后面会作说明。下面逐个讨论各函数。
1. acedGetInt()[ads_getint()]
acedGetInt()函数暂停程序运行,等待用户输入一个整数,其定义如下:
acedGetInt()函数暂停程序运行以等待用户输入一个整数,并设置result为选定的整数值。prompt参数指定acedGetInt()函数暂停前显示的字符串。prompt是可选的,如果不需要使用,可放置一个NULL替代字符串的值。AutoCAD用户可以输入介于-32 768到+32 767范围内的任一有效整数(
短型)。
acedGetInt()函数返回下述代码之一:如果函数调用成功返回RTNORM,如果失败返回RTERROR,如果用户取消(按Esc键)则返回RTCAN。大多数的acedGetXXX()类函数都是如此。
举例如下:
注意在acedGetInt()函数中传递的是qty的地址,因为函数要求是一个指向整数的指针(或一个整数的地址),而非整数本身。这是一种开始ADS编程时易犯的常见错误。对于许多acedGetXXX()类函数来说,这是一种常用技术,所以应该知道。
2. acedGetReal()[ads_getreal()]
acedGetReal()函数与acedGetInt()函数除了result参数是ads_real类型之外,几乎是一样的。其定义为:
注意参数result是一个指向ads_real类型的指针。
3. acedGetString()[ads_getstring()]
acedGetString()函数暂停程序运行以等待用户输入一个字符串,其定义如下:
该函数使result指向用户输入的字符串。参数cronly说明字符串能否包含空格。prompt参数指定acedGetString()函数暂停前显示的字符串。prompt是可选的,如果不需要使用,可放置一个NULL替代字符串的值。result参数必须指向足以容纳字符串的内存区。acedGetString()函数最多可
返回132个字符,所以result所指的字符串长度不能超过133个字符。如果参数cronly的值是真(非零),则字符串可以包含空格,用户必须按Enter键终止字符串的输入。如果参数cronly的值是假(0),则按空格键或Enter键均能终止字符串的输入。acedGetString()函数返回下列码之一:如
果函数调用成功返回RTNORM,如果失败返回RTERROR,如果用户取消(按Esc键)则返回RTCAN。
下面是一段不能输入含空格字符串的实例代码:
下面是一段允许输入含空格字符串的代码:
4. acedGetDist()[ads_getdist()]
acedGetDist()函数暂停程序运行以等待用户输入直线距离,其定义如下:
该函数暂停程序运行等待用户输入直线距离,并设置result为选定的距离之值。参数pt在当前UCS中指定一个基点。参数prompt指定acedGetDist()函数暂停前显示的字符串。参数pt和prompt是可选的,如果不需要使用,可放置一个NULL替代点或字符串的值

。用户可以用键盘直接输入距离
值,也可以指定图形屏幕上的两个位置确定距离。AutoCAD从第一点到当前十字光标位置拉出一条橡皮筋线以帮助用户目测距离值。如果参数pt不为NULL,AutoCAD就利用这一值作为两点中的第一点。在缺省情况下,acedGetDist()函数把参数pt和result看作三维点。预先调用acedInitGet(
)函数(稍后讨论)能迫使pt为二维点,并保证acedGetDist()函数在result中返回二维平面距离。acedGetDist()函数返回下列代码之一:如果函数调用成功返回RTNORM,如果失败返回RTERROR,如果用户取消(按Esc键)则返回RTCAN。下面是一段实例代码:
5. acedGetPoint()[ads_getpoint()]
acedGetPoint()函数暂停程序运行以等待用户输入一个点,其定义如下:
该函数暂停程序运行等待用户输入一个点,并设置result为所选定点的值。参数pt在当前的UCS中指定一个相对基点。参数prompt指定acedGetPoint()函数暂停前显示的字符串。参数pt和prompt均是可选的,如果不需要使用,可放置一个NULL替代点或字符串的值。AutoCAD用户可以用键盘
直接输入坐标值来指定点。acedGetPoint()函数把参数pt和result看作三维点。用户也可以指定图形屏幕上的一个位置来确定点。如果参数pt不为NULL,AutoCAD会从点pt到当前十字光标位置画出一条橡皮筋线。存储在result中的点坐标是以当前的UCS表达的。acedGetPoint()函数返回下
列代码之一:如果函数调用成功返回RTNORM,如果失败返回RTERROR,如果用户取消(按Esc键)则返回RTCAN。下面是一段实例代码:
6. acedGetCorner()[ads_getcorner()]
acedGetCorner()函数暂停程序运行以等待用户输入图形屏幕上所画的矩形框的对角点。其定义如下:
该函数暂停程序运行等待用户输入矩形框的对角点,并设置result为所选定点的值。参数pt在当前UCS中指定矩形的基点,这一参数对于acedGetCorner()函数是必选的(NOT OPTIONAL)。参数prompt指定acedGetCorner()函数暂停前显示的字符串。参数prompt是可选的,如果不需要使用,可
放置一个NULL替代字符串的值。AutoCAD用户可以用键盘直接输入坐标值来指定对角点,acedGetCorner()函数把pt看作是一个三维点。用户也可以指定图形屏幕上的一个位置来确定对角点。AutoCAD从点pt到当前十字光标位置画出一动态矩形框以帮助用户目测第二对角点的位置。矩形画在
当前UCS的XY平面内。acedGetCorner()函数返回下列代码之一:如果函数调用成功返回RTNORM,如果失败返回RTERROR,如果用户取消(按Esc键)则返回RTCAN。
如果用户正从一个3D视点观察一对象,使用acedGetCorner()函数有一点困难: acedGet Corner()函数画出的动态矩形总是平行于屏幕正面。
7. acedGetAngle()[ads_getangle()]和acedGetOrient()[ads_getorient(

)]
acedGetAngle()函数提示用户输入一个相对于ANGBASE系统变量设置的当前值的角度。
acedGetAngle()函数暂停程序运行等待用户输入一个角度,并设置result为所选定的角度值。参数pt在当前(二维的)UCS中指定角度的基点,参数prompt指定acedGetAngle()函数暂停前显示的字符串。参数pt和prompt均是可选的,如果不需要使用,可放置一个NULL替代点或字符串的值。
AutoCAD用户可以用键盘输入角度值,也可以在图形屏幕上指定两个二维点来设置角度。AutoCAD会从第一点到当前十字光标位置画一条橡皮筋线以帮助用户目测角度。如果参数pt不为NULL,AutoCAD就用这一点作为两点中的第一个点。角度值在当前UCS的XY平面内度量(acedGetAngle()函数
忽略pt的Z值)。acedGetAngle()函数总是用弧度表示result的值。
acedGetAngle()函数总是相对于ANGBASE系统变量的当前值。对于acedGetOrient()函数,0度角总是指向右,即“东”或“三点钟”。acedGetAngle()和acedGetOrient()两函数均返回从角度基准(即0度)按逆时针方向度量以弧度为单位的角度值(实数)。如果总是要求0度指向右(即“东”)
,可使用acedGetOrient()函数。acedGetAngle()和acedGetOrient()函数返回下列代码之一:如果函数调用成功返回RTNORM,如果失败返回RTERROR,如果用户取消(按Esc键)则返回RTCAN。
8. acedInitGet()[ads_initget()]
acedInitGet()函数控制紧随其后的一个acedGetXXX()函数的用户输入。例如:在acedGetInt()函数中,用户可以输入一个负数、0或按Enter键和什么都不输入,如实例代码段说明的那样。现在假设在应用程序中需要一条输入,但不允许0和负输入。我们怎样来控制这种情况呢?在调用ace
dGetXXX()函数之前,调用带有合适参数设置的acedInitGet()函数就可以满足上述要求。acedInitGet()函数的定义如下:
参数val设定输入数据的范围和方式,通过设置控制位的开与关来实现(在参数val中指定)。设置的控制位组合只控制紧随其后的一个acedGetXXX()函数的输入,之后立即失效。应用程序不必再次调用acedInitGet()函数来清除。可选参数kwl(关键字列表)指定用户输入函数可接受的关键字
。稍后我们再讨论关键字。如果不需要传递关键字,参数kwl应当是NULL或空串。如果acedInitGet()函数调用成功返回RTNORM,否则返回RTERROR。现在我们来讨论由控制acedGetXXX()类函数输入的val参数指定的代码。
可由acedInitGet()函数设置的输入选项如表3-3所示。
表3-3 acedInitGet()函数的输入选项
位 位值代 码说 明
位0 1 RSG_NONULL 不允许空输入
位1 2 RSG_NOZERO 不允许输入0
位2 4 RSG_NONEG 不允许输入负数
位3 8 RSG_NOLIM 不检查图形边界(即使LIMCHECK为1)
位4 16 未使用
位5 32 RSG_DASH 用虚线表示橡皮筋线

或矩形框
位6 64 RSG_2D 不考虑3D点的Z坐标(只用于acedGetDist()函数)
位7 128 RSG_OTHER 允许任意输入(无论什么用户类型)
上文提到我们要使用acedGetInt()函数并附带下列条件:不允许0和负数输入。这可以由下面的代码段实现:
为了获得所需代码的组合,可用加号“+”相连,如上述代码段。如果用户按了Enter键,输入了“0”或负数,AutoCAD会不断提示用户输入错误直至val获得一个正整数。在执行下一句的acedGetInt()函数时,用户可以只按Enter键,AutoCAD就会继续往下运行,但变量qty将没有值。记住
上述代码段中的acedInitGet()函数只对首次调用acedGetInt()函数起作用,对第二个函数acedGetInt()不起作用。如果要对第二个acedGetInt()函数施加用户输入控制,就必须在调用第二个acedGetInt()函数之前用合适的代码组合再次调用acedInitGet()函数。
表3-3列出的所有代码并不适用于全部的acedGetXXX()类函数,见表3-4。例如:对于acedGetPoint()函数,代码RSG_NONEG就没有意义。但代码RSG_NONULL对于acedGetPoint()函数是完全有意义的。表3-4列出了各代码适用的acedGetXXX()类函数。
表3-4 用户输入函数与适用的控制位
acedGetXXX() 非空(1) 非零(2) 非负(4) 无界(8) 虚线(32) 2D距离(64) 任意输入(128)
函数名 RSG_NONULL RSG_NOZERO RSG_NONEG RSG_NOLIM RSG_DASH RSG_2D RSG_OTHER
acedGetInt() X X X X
acedGetReal() X X X X
acedGetDist() X X X X X X
acedGetAngle() X X X X
acedGetOrient() X X X X
acedGetPoint() X X X X
acedGetCorner() X X X X
acedGetKword() X X
9. acedInitGet()[ads_initget()]和acedGetKword()[ads_getkword()]
acedInitGet()函数的第二个参数是关键字表。现在就来讨论什么是关键字表以及怎样和acedGetKword()函数结合使用。关键字表是由acedInitGet()函数建立的。假定要画下列三对象之一:球、棱锥和立方体。可以利用acedInitGet()函数建立一个关键字表如下:
在这种情形下,“Ball Pyramid Cube”是一个在调用acedGetKword()函数之前建立的关键字表。注意出现在命令行提示中的方括号。如果把鼠标移到屏幕的活动图形区并右击,出现在方括号内的条目也作为选项出现在右键快捷菜单中。就是这样,现在懂得怎样增加右键快捷菜单选项了吧
。注意命令提示必须同时有效。acedGetKword()函数的定义如下:
假定用户要画一个球。在AutoCAD的命令提示下用户通过输入字母B选Ball选项。这可以输入大写或小写,也可以输入整个单词。其结果是字符串缓冲区kw现在包含了字符串“Ball\0”,关键字表中的一个。正是关键字表中每个词的大写字母定义了使acedGetKword()函数接受用户的输入所
必须打入的字符。如果用户要选择画球、长方体、棱锥和立方体该怎么办?球(Ball)和长方体(

Box)均以相同的字母开头,对此有多种解决方案,如下所示。
在这种情形下,用户可以选字母‘O’或打入“box”来画长方体(bOx)。字母的大小写无关紧要。下面是另一种解决方案:
在这种情形下,为画出一个长方体(BOx)用户必须输入最少字母“BO”。同样,在输入时字母的大小写是无关紧要的,输入“BA”画一个球,输入“p”画一个棱锥,输入“c”画一个立方体。
10. acedGetInput()[ads_getinput()]
在调用一个用户输入函数之后,acedGetInput()函数检索由AutoCAD用户输入的关键字。其定义如下:
检索出的关键字保存在str中,这不能和由acedInitGet()函数建立的关键字表相混淆。参数str必须是指向字符缓冲区的指针,字符缓冲区应足以容纳要输入的关键字。str的最大长度是511字符(保留第512个字符为空字符)。acedGetInput()函数除非紧跟在用户输入函数的调用之后调用,
否则是毫无意义的且不会成功。即使如此,也只有当用户输入函数返回RTKWORD值时,调用才会成功。在下面的例子中调用了acdbEntGet()函数,这也是一个我们尚未讨论的用户输入函数。在下面的代码段中通过例子很好地解释了acedGetInput()函数的使用。
我们还未谈到ads_name数据类型和acedEntSel()函数,后面将会讨论。先来看一看acedInitGet()函数的调用。
关键字表是“Model Paper Name”,所以用户最少可以用键盘输入一个字母“m”、“p”或“n”与关键字表中的某一关键字匹配。还要注意位代码是“0”。这意味着用户可以按Enter键表示无输入,这是完全可以接受的。acedEntSel()函数允许用户选择一个实体。正如所见,这里有许多
输入选择。如果用户按Enter键,返回码rc的值为RTNONE,如果按Esc键,rc的值为RTCAN。上面两种情形(RTNONE或RTCAN)均由switch语句的第一部分捕获。如果在调用acedEntSel()函数时出错,将返回RTERROR。在考虑RTKWORD之前,先来看一下RTNORM。如果用户选定了一个实体,返回码r
c的值就为RTNORM,所做的任何处理都将在实体进行,并作为switch语句这一部分的结果。如果用户选定了由acedInitGet()函数建立的关键字表中的一个,返回码rc的值就为RTKWORD。这里就是acedGetInput()函数开始起作用的地方:选定了哪一个关键字?注意acedGetInput()函数的返回
值与RTNORM进行了比较,如果它们不等说明发生了错误。假定调用acedGetInput()函数时没有出错,那么就检查kw缓冲区中的关键字值,并采取相应的操作。因此,在用户能够利用关键字表或其他输入选项的地方就是acedGetInput()函数开始活动的地方。
如果acedGetInput()函数调用成功,返回RTNORM,否则返回RTERROR。
11. acedGetFileD()[ads_getfiled()]
acedGetFileD()函数不是acedGetXXX()类函

数,也不受acedInitGet()函数的控制,但由于具有acedGet前缀,我们在这里一起讨论。acedGetFileD()函数用标准的AutoCAD文件对话框提示用户输入一文件名。acedGetFileD()函数的定义如下:
参数title指定整个对话框的标题,default指定缺省文件名(可以是NULL),ext是缺省文件扩展名(如果是NULL,ext的缺省值为*)。从AutoCAD R13开始,参数ext可以接受用分号隔开的多个文件扩展名。如果acedGetFileD()函数成功地获得一个文件名则返回RTNORM,并使result中包含文件
名,若不在当前目录还包含路径名;否则返回RTERROR。下面为一段代码实例:
上述代码段产生如图3-3所示的对话框。
图3-3 acedGetFileD()函数产生的Select an ARX File对话框
acedGetFileD()函数为路径名分配内存。程序负责用结果缓冲区调用acutRelRb()函数。在ADSRX文档中提到了“Type it”按钮。请注意在AutoCAD R14和AutoCAD 2000的对话框中没有“Type it”按钮,这种对话框的外观与资源管理器风格的对话框非常相似。ObjectARX文档中关于对AutoC
AD R14和AutoCAD 2000的“Type it”按钮的讨论也是错误的。然而AutoCAD 2000的AutoLISP文档是正确的。
表3-5 acedGetFileD()函数的flags选项
位 值说 明
1 表示创建新文件
2 禁用“Type it”按钮(AutoCAD R14/2000无此项)
4 用户能输入任意文件扩展名
8 对输入的文件名执行库搜索
16 把acedGetFileD()函数的第二个参数解释为路径或目录名,而非文件名
32 当开始一个同名的新文件时,禁止文件已存在警告框的显示
还有,在AutoCAD R14/2000中,系统变量FILEDIA对acedGetFileD()函数不起作用。如果FILEDIA的值为“0”,调用acedGetFileD()函数仍然会出现对话框。表3-5列出了flags位的意义(详见ADSRX文档)。若要设置多种选项只需位值相加。

https://www.sodocs.net/doc/df14534975.html,/s/blog_4ac0a0d30100c5d7.html

相关主题