CAD2004开发自定义实体主要依赖于ObjectARX SDK进行C++层面的深度二次开发。这是一个系统性的工程,涉及开发环境搭建、项目配置、实体类定义、注册与持久化等多个环节。下面将详细拆解开发步骤与环境配置方法。
一、 开发环境配置详解
开发CAD2004自定义实体,必须严格匹配其底层框架。核心组件包括Visual Studio、ObjectARX SDK、ObjectARX Wizards。
| 组件名称 | 具体版本要求 | 功能与作用 |
|---|---|---|
| 操作系统 | Windows 2000/XP | CAD2004原生支持的操作系统,在更高版本Windows上需以兼容模式运行。 |
| 集成开发环境 (IDE) | Microsoft Visual Studio .NET 2002 (VC7.0) | 官方指定的编译环境,版本必须严格对应以保证ObjectARX库的兼容性。 |
| 核心SDK | ObjectARX 2004 SDK | 提供用于开发自定义实体(AcDbEntity派生类)和所有ARX应用程序的头文件、库文件和工具。 |
| 辅助工具 | ObjectARX Wizards for VS2002 | Visual Studio的项目向导插件,用于快速创建ARX项目框架,自动配置编译器和链接器设置。 |
配置步骤:
- 安装基础软件:按顺序安装Visual Studio .NET 2002和CAD2004软件。
- 安装SDK与向导:安装ObjectARX 2004 SDK和对应VS2002的Wizards。安装后,在Visual Studio的新建项目对话框中应出现"ObjectARX/DBX/OMF Project"等选项。
- 关键项目配置(以新建的ARX项目为例) :
- 包含目录 :在项目属性中,添加ObjectARX SDK的
inc目录路径。 - 库目录 :添加ObjectARX SDK的
lib目录路径。 - 预处理器定义 :通常需要添加
ACRXAPP,RADPACK等。 - 链接器输入 :在附加依赖项中,添加核心库如
acad.lib、rxapi.lib、acdb.lib、acedapi.lib等。
- 包含目录 :在项目属性中,添加ObjectARX SDK的
一个典型的关键库链接配置示例如下:
cpp
// 项目属性 -> 链接器 -> 输入 -> 附加依赖项
acad.lib;rxapi.lib;acdb.lib;acedapi.lib;acge.lib;acgiapi.lib; // 根据实体功能需要增减
二、 自定义实体开发核心步骤
开发一个自定义实体,本质上是创建一个从AcDbEntity类(或其子类,如AcDbCurve)派生的新类,并重写一系列纯虚函数和关键函数。
1. 定义实体类
首先,需要声明并实现自定义实体类。以下是一个名为MyCustomEntity的简单示例框架:
cpp
// MyCustomEntity.h
#pragma once
#include "dbents.h"
class MyCustomEntity : public AcDbEntity
{
public:
ACRX_DECLARE_MEMBERS(MyCustomEntity); // 声明运行时类
MyCustomEntity();
virtual ~MyCustomEntity() = default;
// 核心重写函数
virtual Adesk::Boolean worldDraw(AcGiWorldDraw* mode) override;
virtual Acad::ErrorStatus transformBy(const AcGeMatrix3d& xform) override;
virtual Acad::ErrorStatus explode(AcDbVoidPtrArray& entitySet) const override;
// DWG文件持久化(存盘/读盘)
virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer) override;
virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const override;
// 自定义属性(示例)
void setCenterPoint(const AcGePoint3d& pt);
AcGePoint3d centerPoint() const;
void setRadius(double r);
double radius() const;
private:
AcGePoint3d m_center; // 示例数据:圆心
double m_radius; // 示例数据:半径
};
2. 实现实体类与运行时注册
在CPP文件中实现类成员,并使用宏将其注册到CAD运行时系统中。
cpp
// MyCustomEntity.cpp
#include "StdAfx.h" // ARX项目通常包含此预编译头
#include "MyCustomEntity.h"
// 将类注册到ObjectARX运行时机制中
ACRX_DXF_DEFINE_MEMBERS(MyCustomEntity, AcDbEntity,
AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, 0,
MYCUSTOMENTITY, "MyAppName");
// 构造函数初始化数据
MyCustomEntity::MyCustomEntity()
: m_center(0,0,0)
, m_radius(1.0)
{
}
// 世界坐标系绘制函数(核心)
Adesk::Boolean MyCustomEntity::worldDraw(AcGiWorldDraw* mode)
{
assertReadEnabled(); // 确保处于读打开状态
// 使用AcGiWorldDraw提供的几何接口进行绘制
mode->geometry().circle(m_center, m_radius, AcGeVector3d::kZAxis);
return Adesk::kTrue; // 已处理所有几何图形
}
// 几何变换函数
Acad::ErrorStatus MyCustomEntity::transformBy(const AcGeMatrix3d& xform)
{
assertWriteEnabled(); // 确保处于写打开状态
// 应用变换矩阵到中心点
m_center.transformBy(xform);
// 对于均匀缩放,半径也需要变换。此处简化处理。
return Acad::eOk;
}
// DWG文件输出(存盘)
Acad::ErrorStatus MyCustomEntity::dwgOutFields(AcDbDwgFiler* filer) const
{
assertReadEnabled();
Acad::ErrorStatus es;
// 先调用父类方法写入基础信息
if ((es = AcDbEntity::dwgOutFields(filer)) != Acad::eOk)
return es;
// 写入自定义数据
filer->writePoint3d(m_center);
filer->writeDouble(m_radius);
return filer->filerStatus();
}
// DWG文件输入(读盘)
Acad::ErrorStatus MyCustomEntity::dwgInFields(AcDbDwgFiler* filer)
{
assertWriteEnabled();
Acad::ErrorStatus es;
// 先调用父类方法读取基础信息
if ((es = AcDbEntity::dwgInFields(filer)) != Acad::eOk)
return es;
// 读取自定义数据(顺序必须与dwgOutFields一致)
filer->readPoint3d(&m_center);
filer->readDouble(&m_radius);
return filer->filerStatus();
}
// 以下为自定义属性的Getter/Setter实现
void MyCustomEntity::setCenterPoint(const AcGePoint3d& pt) { assertWriteEnabled(); m_center = pt; }
AcGePoint3d MyCustomEntity::centerPoint() const { assertReadEnabled(); return m_center; }
void MyCustomEntity::setRadius(double r) { assertWriteEnabled(); m_radius = r; }
double MyCustomEntity::radius() const { assertReadEnabled(); return m_radius; }
3. 应用程序初始化与命令注册
每个ARX模块需要一个入口函数来注册命令和自定义类。
cpp
// 主ARX应用程序入口文件 (例如 MyArxApp.cpp)
#include "StdAfx.h"
#include "MyCustomEntity.h"
// 初始化函数 - 在CAD加载ARX时调用
extern "C" AcRx::AppRetCode
acrxEntryPoint(AcRx::AppMsgCode msg, void* pkt)
{
switch (msg) {
case AcRx::kInitAppMsg:
// 解除数据库锁定,允许应用程序被卸载
acrxUnlockApplication(pkt);
// 注册自定义类
MyCustomEntity::rxInit();
acrxBuildClassHierarchy();
// 添加自定义命令
acedRegCmds->addCommand(_T("MYCOMMANDS"), _T("MYCREATE"), _T("CREATE"), ACRX_CMD_MODAL, &createMyEntity);
break;
case AcRx::kUnloadAppMsg:
// 删除命令组
acedRegCmds->removeGroup(_T("MYCOMMANDS"));
// 从运行时类层次结构中删除自定义类
deleteAcRxClass(MyCustomEntity::desc());
break;
}
return AcRx::kRetOK;
}
// 示例命令函数:创建一个自定义实体并添加到模型空间
void createMyEntity()
{
AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
AcDbBlockTable* pBlockTable;
AcDbBlockTableRecord* pBlockTableRecord;
// 以写模式打开当前数据库的模型空间块表记录
pDb->getBlockTable(pBlockTable, AcDb::kForRead);
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
pBlockTable->close();
// 创建自定义实体对象
MyCustomEntity* pEnt = new MyCustomEntity();
pEnt->setCenterPoint(AcGePoint3d(100, 100, 0));
pEnt->setRadius(50);
// 将实体添加到模型空间,并关闭所有对象
pBlockTableRecord->appendAcDbEntity(pEnt);
pBlockTableRecord->close();
pEnt->close();
}
三、 编译、调试与部署
- 编译 :在Visual Studio .NET 2002中配置好项目后,编译生成
.arx文件。 - 加载调试 :
- 启动CAD2004。
- 使用
ARX或NETLOAD命令(对于ObjectARX 2004,通常是ARX命令),然后选择"加载"并找到编译好的.arx文件。 - 或在CAD快捷方式的目标路径后添加
/l "path\to\your\module.arx"参数实现自动加载。 - 在Visual Studio中附加到
acad.exe进程进行源代码级调试。
- 部署 :将最终的
.arx文件分发给用户,用户通过上述加载命令即可使用其中定义的新实体和命令。
注意事项与挑战:
- 版本强绑定 :为CAD2004开发的ARX模块不能直接在更高版本CAD中运行,反之亦然。这是由ObjectARX SDK的版本依赖性决定的。
- 现代环境兼容性:在Windows 10/11等现代系统上进行开发,需处理旧版Visual Studio和SDK的兼容性问题,可能需使用虚拟机或专门的旧版开发机。
- 功能完整性 :上述示例仅实现了最基本的功能。一个完整的自定义实体通常还需重写
viewportDraw,getGeomExtents,getOsnapPoints,getGripPoints等方法,以支持视口渲染、范围计算、对象捕捉和夹点编辑等完整交互行为。
通过以上步骤,即可完成CAD2004环境下自定义实体的开发环境配置与核心功能实现。整个过程要求开发者对C++、AutoCAD数据库结构以及ObjectARX框架有深入的理解。