ObjectARX程序设计入门
AutoCAD图形实际上是一系列存放在一个AcDbDatabase类型的数据库中的AcDb对象。AcDbDatabase数据库中所有的对象都有一个句柄,在一个图形(DWG)文件中,对象句柄是唯一的,用来标识对象。AutoCAD图形实体(AcDbEntity类对象)只是AcDbDatabase数据库的一种特殊的对象,用户可以在图形窗口看到并编辑它。AcDbDatabase数据库中的对象还有符号表、词典和其它与AcDb类对象相关的符号。数据库中所有的图形实体和对象都可以使用ObjectARX技术,通过程序设计来进行修改和编辑。这一点其实也就是AutoCAD二次开发的基本出发点和最终目标。<这话对吗?总感觉有些不妥,但不知道如何表达才准确。><尖括号中的内容是我个人感想,不会出现在最终文档中。>
AcDbDatabase既然是数据库,它必然具备数据库的基本组织结构。它由多个表(Table)和表中的记录(Record)构成。AcDbDatabase数据库包括九个符号表和一个命名对象词典。<下面这张图表与大部分教材不同,各位以为如何?>
AcDbDatabase数据库
|------AcDb符号表
| |------块表(AcDbBlockTable)
| |------尺寸标注样式表(AcDbDimStyleTable)
| |------层表(AcDbLayerTable)
| |------线型表(AcDbLinetypeTable)
| |------已注册应用程序表(AcDbRegAppTable)
| |------字体样式表(AcDbTextStyleTable)
| |------用户坐标系表(AcDbUCSTable)
| |------视口表(AcDbViewportTable)
| |------视图表(AcDbViewTable)
|-------命名对象词典
AcDbDatabase数据库使用了面向对象的数据库(OODB)技术,用传统的数据库的术语来说,它甚至不是第一范式(1NF)的,记录的组织形式与普通的数据库有较大的不同。<这大概是很多人没把AutoCAD图形看作数据库的原因。>在AutoCAD命令行运行LISP函数entget可以清楚地看到实体在AcDbBlockTable块表中的记录组织形式。当然,在ObjectARX技术中,关于数据库记录的细节进行了数据封装,对数据库的表和记录进行操作要通过访问各个类的成员函数来实现。
以下详细解释AcDbDatabase数据库操作的ObjectARX技术。
1.1 新建数据库、使用已有的数据库
要使用AcDbDatabase数据库,与使用其它数据库一样,首先要声明一个数据库对象。AcDbDatabase类的声明,调用类的构造函数:
AcDbDatabase ::AcDbDatabase(bool buildDefaultDrawing = true, bool noDocument = false);
其中,buildDefaultDrawing参数控制是否创建一个包括所有默认数据记录的数据库。该参数的默认值为true,这样在AcDbDatabase数据库创建时,将在新建的数据库中包含一个AutoCAD图形数据库必须包含的基本数据要素,这些要素包括九个符号表及其初始记录(比如0层、STANDARD文字样式等),命名对象词典(组词典和多线样式词典)以及必要的系统变量设置。这样就可以向新建的数据库中添加各种实体和对象。若指定该参数为false,AutoCAD将创建一个完全空的AcDbDatabase数据库。这样的AcDbDatabase数据库不能直接向其中添加实体或对象,需读入一个图形文件来拓展该图形数据库,然后再逐步添加或修改数据库中的实体或对象。读入图形数据库使用函数:
AcadErrorStatus AcDbDatabase::readDwgFile(const char* fileName );
<其实,readDwgFile()函数还有两个参数,分别控制数据库读写权限和内码转换,好象在这没必要作更深入的讨论,因此略过。>
AcDbDatabase构造函数的noDocument参数控制打开或的数据库是否与当前文档关联(true代表不和当前文档关联,false表示和当前文档关联)。此参数的使用将在“多文档处理”一节中详细讨论。
这样,要使用AcDbDatabase数据库,若准备新建数据库并向其中添加实体或对象,使用这样的代码:
AcDbDatabase *pDb= new AcDbDatabase();
若要使用已有的图形,比如“test.dwg”文件,则使用下列代码:
AcDbDatabase *pDb= new AcDbDatabase(false);
pDb->readDwgFile(“test.dwg”);
注意,在这种情况下,AcDbdatabase()的参数必须指定为false(当然,0或者Adesk::kFalse都可以)。<ARX帮助中说必须为Adesk::kFalse,AutoDesk是不是有点老大作风?>因为使用pDb->readDwgFile()函数时,pDb必须是一个完全空白的数据库,也就是说,哪怕使用了AcDbDatabase(false);新建数据库,只要对数据库进行了操作,就不能再使用readDwgFile()函数,否则会导致严重的内存错误。
还有一种情况,ARX程序只对当前图形数据库进行操作,在ACAD R14及以前版本和相应的ARX中使用:
AcDbDatabase *pDb=acdbCurDwg(); //该函数返回指向当前图形数据库的指针
在ACAD 2000以上版本中也可以使用相同的方法,不过建议使用下列函数:
AcDbDatabase *pDb=acdbHostApplicationServices()->workingDatabase();
实际上,在ARX 2000及以上版本中,acdbCurDwg()已经定义为宏,宏扩展后就是上述函数。
1.2 使用数据库表和记录
新建或打开图形数据库后,可获取表和记录的指针,然后再对记录进行操作。要获取AcDbDatabase数据库记录指针,大致分为两个步骤:
首先,获取数据库表的指针。为了获取该指针,须声明一个类指针,该指针类型决定要使用的数据库表的类型(或名称)。比如说,要使用AcDb的块表及其记录,应该这样声明指针类:AcDbBlockTable *pBlkTbl;
然后使用AcDbDatabase类的成员函数获取表指针。获取块表指针可使用函数getBlockTable()函数。
Acad::ErrorStatus AcDbDatabase::getBlockTable(AcDbBlockTable*& pBlkTbl,
AcDb::OpenMode mode);
该函数的第一个参数是一个指向表引用(或者说地址)的指针。用于函数输出块表指针。另一个参数控制使用表的读写权限。
其它符号表指针的获取与块表指针的获取基本一致,可参考ARX帮助或dbsymtb.h头文件。从ARX2000开始,在AcDbDatabase类的成员函数中,还有一种方法可获取数据库中符号表的指针。即使用getSymbolTable()函数,该函数有九个重载版本,分别对应九个符号表,几个重载版本之间仅第一个参数的类型不同。例如,要新建图层,可以这样获取层表指针:
AcDbLayerTable* pLayerTbl;
pDb->getSymbolTable(pLayerTbl,AcDb::kForWrite); //此处pDb指已打开的数据库指针。
使用数据库,最终往往要对数据库表中的记录进行操作,因此打开表后,就需要获取记录指针。所有AcDb符号表记录指针都可通过调用对应表的getAt()函数来实现。每一个getAt()函数都有两个重载版本,分别输出记录ID或记录指针。<是不是太哆嗦?>
getAt()函数完整语法:
输出记录指针:
Acad::ErrorStatus AcDb##BASE_NAME##Table::getAt(const char* pEntryName,
AcDb##BASE_NAME##TableRecord*&pRecord, AcDb::OpenMode mode,
Adesk::Boolean openErasedRecord =Adesk::kFalse) const;
输出记录ID:
Acad::ErrorStatus AcDb##BASE_NAME##Table::getAt(const char* pEntryName,
AcDbObjectId& recordId, Adesk::Boolean getErasedRecord =Adesk::kFalse) const;
实际应用时,将##BASE_NAME##替换成九个符号表的实际类型。
在这解释两个参数,char* pEntryName要求输入符号表记录名称,例如块表中至少有两条记录,模型空间(可用宏ACDB_MODEL_SPACE访问记录名称)和图纸空间(即ACDB_PAPER_SPACE)。
最后,取出数据库符号表记录后,若不再使用表对象,应及时关闭,回收系统资源。
AcDb##BASE_NAME##Table::close();
1.3 添加、删除记录
获取数据库记录指针或记录ID后,就可以对数据库记录进行操作了,这包括在数据库中添加、删除记录,提取记录中的数据,即查找记录。
向数据库中添加记录,通用的方法是调用符号表类的add()成员函数。
Acad::ErrorStatus AcDb##BASE_NAME##Table ::add(AcDbSymbolTableRecord* pRecord); 或
Acad::ErrorStatus AcDb##BASE_NAME##Table ::add(AcDbObjectId& recordId,
AcDbSymbolTableRecord* pRecord); //该函数第一个参数用于输出新添加的记录ID
在这要说明一下,通常我们向模型空间添加实体不用这些方法。因为模型空间本身就是AcDb块表中的一条记录,向其中添加实体仅仅是对该记录进行操作,不需要向数据库中添加记录。
1.4 图形数据库实例
第一个例子来自ARX示例文档,目录\ObjectARX xxxx\docsamps\ents\ents.cpp文件演示了打开当前图形数据库并添加实体对象以及层表和组词典的使用方法。这个例子首先在当前图形数据库中建立一个线对象和一个圆对象,将圆的颜色变为红色,并与线对象组合成组(Group),另外,还在当前图形数据库中添加一个新图层。
下一个例子是对上一例子中添加图层的方法做出完善。在这个例子中将说明对层表和线型表及其记录操作的方法。
void addLayer()
{ AcDbLayerTable *pLayerTbl; //先声明一个空的层表指针
acdbHostApplicationServices()->workingDatabase() //当前图形数据库
->getSymbolTable(pLayerTbl, AcDb::kForWrite); //打开层表为写入状态
if (!pLayerTbl->has("MyLayer")) { //has()函数是层表类的成员函数
AcDbLayerTableRecord *pLayerTblRcd= new AcDbLayerTableRecord;//新层表记录
pLayerTblRcd->setName("MyLayer"); //设定图层名
pLayerTblRcd->setIsFrozen(0); // 图层解冻
pLayerTblRcd->setIsOff(0); // 打开图层
pLayerTblRcd->setVPDFLT(0); // 使用默认视口
pLayerTblRcd->setIsLocked(0); // 图层解锁
AcCmColor color; // AcCmColor是ACAD颜色管理类
color.setColorIndex(1);
pLayerTblRcd->setColor(color); // 图层颜色为红色
// 为给新图层设置线型,要得到线型表记录的ID。
// 以下的代码演示如何得到并操作记录ID
AcDbLinetypeTable *pLinetypeTbl;
AcDbObjectId ltId;
acdbHostApplicationServices()->workingDatabase()
->getSymbolTable(pLinetypeTbl, AcDb::kForRead);
if ((pLinetypeTbl->getAt("DASHED", ltId))!= Acad::eOk)
{ acutPrintf("\n未发现DASHED线型使用CONTINUOUS线型");
// 每一个不完全空的图形数据库的线型表中都有线型名为CONTINUOUS 的默认记录
// 试图删除该记录将会导致错误。
pLinetypeTbl->getAt("CONTINUOUS", ltId);
}
pLinetypeTbl->close();
pLayerTblRcd->setLinetypeObjectId(ltId);
pLayerTbl->add(pLayerTblRcd);
pLayerTblRcd->close();
pLayerTbl->close();
} else {
pLayerTbl->close();
acutPrintf("\nlayer already exists");
}
}
以上只是对ACAD图形数据库的最基本介绍,图形数据库知识是ARX程序设计的基础和核心,以后还要对此进行更为深入的解释。今天就先说这些了。下一篇文章将对以上两个例子进行逐语句的详细解释,并且讨论与之相关的一些内容。另外,还要简单地介绍VC6和VC.NET的ARX程序不同之处。
ObjectARX程序设计入门相关推荐
- [笔记][mooc]《程序设计入门—C语言》
程序设计入门-C语言 (幕课课程笔记) Mac环境搭建 terminal > "gcc" >确认,安装 > gcc || gcc --version 本课程程序的 ...
- 【转】Unix环境高级程序设计入门----文件系统的相关编程(上)
Unix环境高级程序设计入门 ----文件系统的相关编程(上) 一.关于目录 不管是何种操作系统,一提到其中的文件系统首先想到的自然是目录和文件.在Unix系统中一切皆可视为文件,目录是一种特殊的文件 ...
- 汇编程序设计入门(安装+debug调试实例)
汇编程序设计入门(安装+debug调试实例) 一.汇编环境安装 1.安装dosbox https://www.dosbox.com/download.php?main=1 2.下载和安装masm ht ...
- Ajax程序设计入门
Ajax程序设计入门 一.使用Ajax的主要原因 1.通过适当的Ajax应用达到更好的用户体验: 2.把以前的一些服务器负担的工作转嫁到客户端,利于客户端闲置的处理能力来处理,减轻服务器和带宽的负担, ...
- 翁恺c语言程序设计入门期末,程序设计入门-C语言 翁恺.doc
第 PAGE \* MERGEFORMAT 39 页 共 NUMPAGES \* MERGEFORMAT 39 页 程序设计入门-C语言 浙大 翁恺循环类型编程源代码1.#include int ma ...
- c语言程序设计入门教程视频教学
c语言教程视频讲座简介: 沉睡者IT:c语言程序设计入门教程视频教学培训课程内容介绍: 程序设计是一门基础课程.对于计算机相关专业而言,程序设计是专业基础知识,是进一步学习其他专业知识的第一步阶梯:对 ...
- C语言程序设计入门教程
C语言程序设计入门教程 目录 语言分类 C语言特点 最简单的C语言程序 注释方式 C语言程序的结构 程序设计的任务阶段 选择结构程序设计 关系运行算符 逻辑运算符 switch语句 条件运算符 数据类 ...
- 《Python程序设计入门与实践》219道课后习题答案
适用教材:Python程序设计入门与实践 I S B N:978-7-5606-5960-2 作 者:董付国 页 数:319页 例题数量:73个 演示代码:200段(不含例题代码) 习题数 ...
- javaweb程序设计入门
断断续续的读了java程序设计入门.最近要读完了.主要说了http servlet jsp javabean 涉及到了反射
最新文章
- USB基础---设备、配置、接口、端点和字符串描述符
- txt文件导入mysql--转
- android中文api(85)——HorizontalScrollView
- 第五课 vim基本用法、bash编程初步和for循环
- mysql 安装导航_ubuntu下安装Mysql
- 修改linux引导文件系统,修改/etc/fstab文件加快Linux系统的启动速度
- 翻山越岭上uvaoj
- 灰色理论 光滑度处理 matlab,基于灰色理论的电子设备寿命预测研究
- PROTEL PCB放置汉字
- 使用hashcat破解Windows账户密码
- 微信小程序选项卡 点击导航内容切换 滑动内容导航切换
- 【计算机网络学习笔记16】网络新技术
- 40页PPT,让你了解智能物联网应用场景需求与未来发展趋势
- 小米获取屏幕高度不准确-小米获取屏幕高度的兼容方案
- python转换js_将节点js转换为python-seri
- 测试额外任务而撒旦法 速度速度发撒旦法
- 第2章	无人艇局部危险避障算法研究
- Java fx 变速播放音乐_QVE音频剪辑如何调整音频播放速度?音乐变速方法说明
- 微信运动刷步怎么用?微信运动刷步使用教程[多图]
- win配置pm2开机自启node项目