数据库指针是什么-贴库改版看看十库是倒退
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命令行运行LISP函数entget可以清楚的看到实体在AcDbBlockTable块表中的记录组织形式。 当然,在ObjectARX技术中,封装了数据库记录的细节,通过访问各个类的成员函数来实现对数据库的表和记录的操作。
下面详细解释AcDbDatabase数据库操作的ObjectARX技术。
1.1 新建数据库和使用已有数据库
要使用 AcDbDatabase 数据库,就像使用其他数据库一样,您必须首先声明一个数据库对象。 AcDbDatabase 类的声明调用类的构造函数:
AcDbDatabase::AcDbDatabase(boolbuildDefaultDrawing=true,boolnoDocument=false);
其中,buildDefaultDrawing参数控制是否创建包含所有默认数据记录的数据库。 该参数的默认值为true,这样在创建AcDbDatabase数据库时,AutoCAD图形数据库必须包含的基本数据元素将被包含在新建的数据库中,这些元素包括九个符号表及其初始记录(如如 0 层、STANDARD 文本样式等),命名对象字典(组字典和多行样式字典),以及必要的系统变量设置。 这使得向新创建的数据库中添加各种实体和对象成为可能。 如果将此参数指定为 false,AutoCAD 将创建一个完全空的 AcDbDatabase 数据库。 这样的 AcDbDatabase 数据库不能直接向其添加实体或对象。 它需要读取一个图形文件来扩展图形数据库,然后逐步添加或修改数据库中的实体或对象。 使用函数读入图形数据库:
AcadErrorStatusAcDbDatabase::readDwgFile(constchar*fileName);
AcDbDatabase构造函数的noDocument参数控制打开的数据库是否关联当前文档(true表示不关联当前文档,false表示关联当前文档)。 “多文档处理”部分详细讨论了此参数的使用。
这样,要使用 AcDbDatabase 数据库,如果您要创建一个新数据库并向其中添加实体或对象,请使用以下代码:
AcDbDatabase*pDb=newAcDbDatabase();
要使用现有绘图,例如“test.dwg”文件,请使用以下代码:
AcDbDatabase*pDb=newAcDbDatabase(false);
pDb->readDwgFile("test.dwg");
注意,这种情况下AcDbdatabase()的参数必须指定为false(当然0或者Adesk::kFalse都可以)。 因为在使用pDb->readDwgFile()函数时,pDb必须是一个完全空白的数据库,即即使AcDbDatabase(false); 用于新建数据库,只要对数据库进行操作,就不能再使用readDwgFile()函数,否则会导致严重的内存错误。
还有一种情况,ARX程序只对当前图数据库进行操作,在ACADR14及之前的版本和对应的ARX中使用:
AcDbDatabase*pDb=acdbCurDwg();//该函数返回当前图数据库的指针
ACAD2000以上版本也可以使用同样的方法,但推荐以下功能:
AcDbDatabase*pDb=acdbHostApplicationServices()->workingDatabase();
其实在ARX2000及以上版本中,acdbCurDwg()已经被定义为一个宏,宏扩展就是上面的函数。
1.2 使用数据库表和记录
创建或打开图数据库后数据库指针是什么,您可以获得表和记录的指针,然后对记录进行操作。 获取AcDbDatabase数据库记录指针,大致分两步:
首先,获取指向数据库表的指针。 为了获得这个指针,必须声明一个类指针,指针的类型决定了要使用的数据库表的类型(或名称)。 例如,要使用 AcDb 的块表及其记录,指针类应该这样声明:AcDbBlockTable*pBlkTbl;
然后使用AcDbDatabase类的成员函数获取表指针。 函数 getBlockTable() 可用于获取块表指针。
Acad::ErrorStatusAcDbDatabase::getBlockTable(AcDbBlockTable*&pBlkTbl,
AcDb::OpenModemode);
该函数的第一个参数是指向表引用(或地址)的指针。 用于函数输出块表指针。 另一个参数控制使用表的读写权限。
其他符号表指针的获取与块表指针的获取基本相同,请参考ARX帮助或dbsymtb.h头文件。 从ARX2000开始,在AcDbDatabase类的成员函数中,也有获取数据库中符号表指针的方法。 即使用getSymbolTable()函数,它有九个重载版本,对应九个符号表,几个重载版本之间只有第一个参数的类型不同。 例如新建一个图层,可以这样获取图层表指针:
AcDbLayerTable*pLayerTbl;
pDb->getSymbolTable(pLayerTbl,AcDb::kForWrite);//这里pDb指的是打开的数据库指针。
在使用数据库的时候,往往最后需要对数据库表中的记录进行操作,所以开表后需要获取记录指针。 所有AcDb符号表记录指针都可以通过调用对应表的getAt()函数来实现。 每个 getAt() 函数都有两个重载版本,分别输出记录 ID 或记录指针。 <你是不是太颤抖了? >
getAt() 函数的完整语法:
输出记录指针:
Acad::ErrorStatusAcDb##BASE_NAME##Table::getAt(constchar*pEntryName,
AcDb##BASE_NAME##TableRecord*&pRecord,AcDb::OpenModemode,
Adesk::BooleanopenErasedRecord=Adesk::kFalse)const;
输出记录ID:
Acad::ErrorStatusAcDb##BASE_NAME##Table::getAt(constchar*pEntryName,
AcDbObjectId&recordId,Adesk::BooleangetErasedRecord=Adesk::kFalse)const;
在实际应用中,将##BASE_NAME##替换为九个符号表的实际类型。
解释一下这里的两个参数,char*pEntryName需要输入符号表记录名,例如块表中至少有两条记录,模型空间(记录名可以用宏ACDB_MODEL_SPACE访问)和图纸空间(即 ACDB_PAPER_SPACE)。
最后,取出数据库符号表记录后,如果该表对象不再使用,应及时关闭,回收系统资源。
AcDb##BASE_NAME##Table::close();
1.3 添加和删除记录
获取到数据库记录指针或记录ID后,就可以对数据库记录进行操作,包括在数据库中增加和删除记录,提取记录中的数据,即查找记录。
向数据库中添加记录,一般的方法是调用符号表类的add()成员函数。
Acad::ErrorStatusAcDb##BASE_NAME##Table::add(AcDbSymbolTableRecord*pRecord); 或者
Acad::ErrorStatusAcDb##BASE_NAME##Table::add(AcDbObjectId&recordId,
AcDbSymbolTableRecord*pRecord);//该函数第一个参数用于输出新增的记录ID
在这里解释一下,通常我们不会使用这些方法来向模型空间添加实体。 因为模型空间本身就是AcDb块表中的一条记录,向其中添加实体只是对记录进行操作数据库指针是什么,不需要向数据库中添加记录。
1.4 图数据库实例
第一个例子来自ARX示例文档,目录\ObjectARXxxxx\docsamps\ents\ents.cpp文件演示了打开当前图数据库并添加实体对象以及层表和组字典的用法。 本例首先在当前图形数据库中创建一个线对象和一个圆对象,将圆的颜色改为红色,并与线对象组合成一个组(Group),同时也在当前图形库中添加一个新图层图形数据库。
下一个例子是对上一个例子中添加层的方法进行改进。 本例将说明操作层表和线表及其记录的方法。
无效添加层()
{AcDbLayerTable*pLayerTbl;//先声明一个空层表指针
acdbHostApplicationServices()->workingDatabase()//当前图数据库
->getSymbolTable(pLayerTbl,AcDb::kForWrite);//打开层表进行写入
if(!pLayerTbl->has("MyLayer")){//has()函数是层表类的成员函数
AcDbLayerTableRecord*pLayerTblRcd=newAcDbLayerTableRecord;//新建层表记录
pLayerTblRcd->setName("MyLayer");//设置图层名称
pLayerTblRcd->setIsFrozen(0);//图层解冻
pLayerTblRcd->setIsOff(0);//打开图层
pLayerTblRcd->setVPDFLT(0);//使用默认视口
pLayerTblRcd->setIsLocked(0);//图层解锁
AcCmColorcolor;//AcCmColor是ACAD颜色管理类
color.setColorIndex(1);
pLayerTblRcd->setColor(color);//图层颜色为红色
//为新图层设置线型,获取线型表记录的ID。
//下面的代码演示了如何获取和操作记录ID
AcDbLinetypeTable*pLinetypeTbl;
AcDbObjectIdltId;
acdbHostApplicationServices()->workingDatabase()
->getSymbolTable(pLinetypeTbl,AcDb::kForRead);
if((pLinetypeTbl->getAt("DASHED",ltId))!=Acad::eOk)
{acutPrintf("\n没有找到虚线类型,使用连续线类型");
//每个非全空图数据库的线型表中都有一条线型名为CONTINUOUS的默认记录
// 尝试删除此记录将导致错误。
pLinetypeTbl->getAt("连续",ltId);
}
pLinetypeTbl->close();
pLayerTblRcd->setLinetypeObjectId(ltId);
pLayerTbl->add(pLayerTblRcd);
pLayerTblRcd->close();
pLayerTbl->close();
}别的{
pLayerTbl->close();
acutPrintf("\nlayeralreadyexists");
}
}
以上只是对ACAD图形数据库最基本的介绍。 图形数据库知识是ARX编程的基础和核心,以后会对此做更深入的讲解。 今天就到此为止。 下一篇文章将逐句详细解释以上两个例子,并讨论一些相关内容。 另外简单介绍一下VC6和VC.NET的ARX程序的区别。