|
使用 ADSRX
ADS 是 AutoCAD 开发系统的简称,从 AutoCAD R10 版时 Autodesk 开始提供这种开发方式(实际上后来演变成现在的 ObjectARX ),它是一个带有 Autodesk 提供的库文件和头文件的 C 语言编程环境。
新的 ObjectARX 出现之后,保留了一部分 ADS 的内容,这部分内容经过修改后被称为 ADSRX,在 ObjectARX 用于完成一些特定的功能:
获取用户输入。
创建和使用 AutoCAD 的选择集。
使用 DCL 对话框(由于 DCL 对话框的使用不够方便,与 MFC 用户界面相比功能又显得很弱,本书不再讨论,仅讨论 MFC 用户界面)
2. 说明
ObjectARX 编程中,可以使用 acedCommand 或 acedCmd 函数来执行 AutoCAD 内部的命令,这与在 AutoCAD 中直接执行相应命令的效果是一样的(甚至在命令窗口中都能找到执行命令的痕迹),本篇通过创建圆、对图形进行缩放来说明这两个函数的使用。
结果缓冲区作为一种特殊的数据类型,在某些特定的场合仍有不可替代的作用,因此在实例中通过创建和访问结果缓冲区的内容来帮助读者更好地理解结果缓冲区的结构。
本篇所得到的 ARX 文件向 AutoCAD 注册三个命令, AddCircle1 和 AddCircle2 命令能够在图形窗口中创建圆,EntInfo 命令能够在命令窗口中显示所选择的圆的参数。
3. 思路
(1) acedCommand 函数
acedCommand 函数的定义为:
int acedCommand(int rtype, ... unnamed);
该函数的参数个数是可变的,并且参数成对出现。参数对中
第一个参数表示参数的类型(参考ARX 帮助系统中如图所示的列表),
第二个表示其实际的数据。
参数表的最后一个参数必须是0 或者 RTNONE (使用 RTNONE 更好一些)
下面的代码用于在 AutoCAD 中创建一个圆心为(0, 0, 0 )、半径为 10 的圆:
acedCommand(RTSTR, "Circle", // 命令
RTSTR, "0,0,0", // 圆心
RTSTR, "10", // 半径
RTNONE); // 结束命令
在 AddCircle1 命令的实现函数中,使用变量值作为 acedCommand 函数的参数,所实现的
功能与上面的代码完全一样。
(2) acedCmd 函数
acedCmd 函数的定义为:
int acedCmd(const struct resbuf * rbp);
//该函数的参数是一个 resbuf 类型的指针,这里需要的结果缓冲区可以由 acutBuildList 函数生成。
//由于 acedCommand 函数实质上也是为要执行的命令构造了一个 resbuf 结构,
//因此 acedCmd 函数和 acedCommand 函数完全能够实现相同的功能,在 AddCircle2命令的实现函数中演示了 acedCmd 函数的用法。
(3) 结果缓冲区(resbuf)
结果缓冲区( resbuf )是 ObjectARX 中定义的一个结构体,其定义为:
struct resbuf {
struct resbuf *rbnext; // 连接列表的指针
short restype;
union ads_u_val resval;
};
其中,联合体 ads_u_val 的定义为:
union ads_u_val {
ads_real rreal;
ads_real rpoint[3];
short rint; // 必须声明为short,而不是int
char *rstring;
long rlname[2];
long rlong;
struct ads_binary rbinary;
};
3. 步骤
(1) 添加一个新类 CUserInteraction
绘制两个圆
static void AddCircle1();
static void AddCircle2();
void CUserInteraction::AddCircle1()
{
// 声明ADS变量
ads_point ptCenter = {0, 0, 0}; // 圆心
ads_real radius = 10; // 半径
// 调用acedCommand函数创建圆
acedCommandS(RTSTR, _T("Circle"), // 命令
RTPOINT, ptCenter, // 圆心
RTREAL, radius, // 半径
RTNONE); // 结束命令
}
void CUserInteraction::AddCircle2()
{
struct resbuf *rb; // 结果缓冲区
int rc = RTNORM; // 返回值
// 创建结果缓冲区链表
ads_point ptCenter = {30, 0, 0};
ads_real radius = 10;
rb = acutBuildList(RTSTR, _T("Circle"),
RTPOINT, ptCenter,
RTREAL, radius,
RTNONE);
// 创建圆
if (rb != NULL)
{
rc = acedCmdS(rb);
}
// 检验返回值
if (rc != RTNORM)
{
acutPrintf(_T("\n创建圆失败!"));
acutRelRb(rb);
// 进行缩放
acedCommandS(RTSTR, _T("Zoom"),
RTSTR, _T("E"),
RTNONE);
}
}
(2) 查看圆信息
static void LookOverEntInfo();
void CUserInteraction::LookOverEntInfo()
{
// 提示用户选择实体
ads_name entName;
ads_point pt;
if (acedEntSel(_T("\n选择实体:"), entName, pt) != RTNORM)
return;
struct resbuf *rbEnt; // 保存实体数据的结果缓冲区
struct resbuf *rb; // 用于遍历rbEnt的结果缓冲区
// 从entName获得保存实体数据的结果缓冲区
rbEnt = acdbEntGet(entName);
rb = rbEnt;
while (rb != NULL)
{
switch (rb->restype)
{
case -1: // 图元名
acutPrintf(_T("\n图元名:%x"), rb->resval.rstring);
break;
case 0:
acutPrintf(_T("\n图元类型:%s"), rb->resval.rstring);
case 8:
acutPrintf(_T("\n图层:%s"), rb->resval.rstring);
break;
case 10:
acutPrintf(_T("\n圆心:(%.2f,%.2f,%.2f)"),
rb->resval.rpoint[X],
rb->resval.rpoint[Y],
rb->resval.rpoint[Z]);
break;
case 40: // 半径
acutPrintf(_T("\n半径:%.4f"), rb->resval.rreal);
break;
case 210: // 圆所在平面的法向矢量
acutPrintf(_T("\n平面的法向矢量:(%.2f,%.2f,%.2f)"),
rb->resval.rpoint[X],
rb->resval.rpoint[Y],
rb->resval.rpoint[Z]);
break;
default:
break;
}
rb = rb->rbnext; // 切换到下一个节点
}
if (rbEnt != NULL)
{
acutRelRb(rbEnt);
}
}
(3) 在acrxEntryPoint.cpp中
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyLookOverEntInfo, MyLookOverEntInfo, ACRX_CMD_MODAL, NULL) //用户交互
//当前项目中注册命令 LookOverEntInfo
static void MidasMyGroupMyLookOverEntInfo()
{
CUserInteraction::AddCircle1();
CUserInteraction::AddCircle2();
CUserInteraction::LookOverEntInfo();
}
|
|