截图
简介
这是一个关于objectarx视频教程培训PPT(部分ppt内容已做更新升级),主要介绍了ObjectARX应用、ObjectARX概述、ObjectARX开发特点、ObjectARX类库构成等内容。培训是给新员工或现有员工传授其完成本职工作所必需的正确思维认知、基本知识和技能的过程。是一种有组织的知识传递、技能传递、标准传递、信息传递、管理训诫行为。其中以技能传递为主,侧重上岗前进行。为了达到统一的科学技术规范、标准化作业,通过目标规划设定知识和信息传递、技能熟练演练、作业达成评测、结果交流公告等现代信息化的流程,让员工通过一定的教育训练技术手段,达到预期的水平,提高目标。目前国内培训以技能传递为主,时间在侧重上岗前。
objectarx视频教程培训PPT是由红软PPT免费下载网推荐的一款培训教程PPT类型的PowerPoint.
ObjectARX Training
华中科技大学CAD中心
武汉天喻软件有限责任公司
2010年2月
ObjectARX应用的介绍
ObjectARX是一个仅在AutoCAD上进行二次开发的一套开发环境,通俗点讲就是一系列的API
ObjectARX的应用举例:
扩展AutoCAD功能
为各种工程设计开发便利的工具
ObjectARX概述
ARX——AutoCAD Runtime eXtension
DBX ——DataBase eXtension
ARX = .DLL + 2 exported functions
{ acrxEntryPoint & acrxGetApiVersion }
ObjectARX开发特点
不同的ACAD版本用不同的开发包及开发环境
ACAD2000~ACAD2002 : VC++ 6.0
ACAD2004~ACAD2006 : VS.NET 2002
ACAD2007~ACAD2009 : VS.NET 2005
ACAD2010~ : VS.NET 2008
ACAD2007开始字符串采用UNICODE编码
ARX之间不能连续依赖
A.arx依赖B.arx, B.arx依赖C.dbx,则A.arx不能加载
与ACAD已有功能地位一致
ObjectARX类库构成
AcRx:用于帮定一个应用程序以及运行类的注册和识别。
AcEd:用于注册自定义命令和AutoCAD事件通告。
AcDb:AutoCAD图形数据库。
AcGi: 用于AutoCAD 的图形类。
AcGe:用于AutoCAD 的线型和几何对象通用类。
ADS: AutoCAD 的早期版本C语言函数库。
ObjectARX类结构
类图classmap.dwg
位置:\ObjectARX 2006\classmap
用ObjectARX能做些什么?
访问、编辑和扩展AutoCAD图形数据库
和AutoCAD系统相互通信
使用MFC创建用户接口
支持多文档应用
创建自定义类和自定义实体
可以开发复杂的应用
和其他开发环境进行协作
培训安排-1
一、基础
AUTOCAD数据库结构及操作,ads_name-句柄-ID及转换,aced常用函数,WCS/UCS及转换,菜单/工具条/对话框制作
二、自定义对象
显示/存储/夹点/移动/拷贝/范围/list/捕捉点/炸开/相交点/sub事件
三、自定义对象生成与编缉
双击修改/Jig/属性页
培训安排-2
四、一些重要对象
字典/层/线型/字体样式
五、扩展数据
六、反应器
八、总结
所需基础
ACAD基本操作
C++
VC
MFC(界面)
COM(属性页等)
STL(提高效率)
AutoCAD图形数据库概述
AutoCAD图形实际上是一系列存放在一个AcDbDatabase类型的对象中的AcDb对象。
一个dwg就是一个数据库
具备数据库的基本组织结构。
包括九个符号表和一个命名对象词典
AutoCAD图形数据库结构
AcDbDatabase数据库
|------AcDb符号表
| |------块表(AcDbBlockTable)
| |------尺寸标注样式表(AcDbDimStyleTable)
| |------层表(AcDbLayerTable)
| |------线型表(AcDbLinetypeTable)
| |------已注册应用程序表(AcDbRegAppTable)
| |------字体样式表(AcDbTextStyleTable)
| |------用户坐标系表(AcDbUCSTable)
| |------视口表(AcDbViewportTable)
| |------视图表(AcDbViewTable)
|-------命名对象词典
访问:AcDbDatabase::getSymbolTable
向数据库中添加实体
Acad::ErrorStatus addEntityToModelSpace(AcDbEntity * pEnt, AcDbObjectId & EntId)
{
Acad::ErrorStatus eRet;
AcDbDatabase * pDb = acdbHostApplicationServices()->workingDatabase();
AcDbBlockTable *pBlockTable;
eRet = pDb->getBlockTable(pBlockTable, AcDb::kForRead);
if ( eRet != Acad::eOk)
{
return eRet;
}
AcDbBlockTableRecord *pBlockTableRecord;
eRet = pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
if ( eRet != Acad::eOk)
{
pBlockTable->close();
return eRet;
}
pBlockTable->close();
eRet = pBlockTableRecord->appendAcDbEntity(EntId, pEnt);
if ( eRet != Acad::eOk)
{
pBlockTableRecord->close();
return eRet;
}
pBlockTableRecord->close();
return Acad::eOk;
}
怎样遍历AutoCAD图形数据库?
void FindObjectId(AcDbObjectId & objId)
{
AcDbDatabase * pDb = acdbHostApplicationServices()->workingDatabase();
AcDbBlockTable *pBlockTable;
pDb->getBlockTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord *pBlockTableRecord;
pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb:: kForRead);
pBlockTable->close();
AcDbBlockTableRecordIterator *pIter;
pBlockTableRecord- >newIterator(pIter); // Create an iterator
for (pIter->start(); !pIter->done(); pIter->step())
{
….........
AcDbEntity *pEntity;
if (pIter->getEntity(pEntity, AcDb::kForRead) != Acad::eOk) continue;
If(pEntity->isKindOf(AcDbCircle::desc()) objId = pEntity->ObjectId();
}
pBlockTableRecord- >close();
}
怎样创建和使用已有的AutoCAD图形数据库?
要使用AcDbDatabase数据库,与使用其它数据库一样,首先要声明一个数据库对象。AcDbDatabase类的声明,调用类的构造函数:
AcDbDatabase ::AcDbDatabase(bool buildDefaultDrawing = true, bool noDocument = false);
其中,buildDefaultDrawing参数控制是否创建一个包括所有默认数据记录的数据库。
该参数的默认值为true,这样在AcDbDatabase数据库创建时,将在新建的数据库中包含一个AutoCAD图形数据库必须包含的基本数据要素,这些要素包括九个符号表及其初始记录(比如0层、STANDARD文字样式等),命名对象词典(组词典和多线样式词典)以及必要的系统变量设置。这样就可以向新建的数据库中添加各种实体和对象。如:AcDbDatabase *pDb= new AcDbDatabase(true);
若指定该参数为false,AutoCAD将创建一个完全空的AcDbDatabase数据库。这样的AcDbDatabase数据库不能直接向其中添加实体或对象,需读入一个图形文件来拓展该图形数据库,然后再逐步添加或修改数据库中的实体或对象。
读入图形数据库使用函数:AcadErrorStatus AcDbDatabase::readDwgFile(const char* fileName );
若要使用已有的图形,比如“test.dwg”文件,则使用下列代码:
AcDbDatabase *pDb= new AcDbDatabase(false);
pDb->readDwgFile(“test.dwg”);
AcDbDatabase构造函数的noDocument参数控制打开的数据库是否与当前文档关联,此参数用于“多文档处理”中。
注意:在这种情况下,AcDbdatabase()的参数必须指定为false(当然,0或者Adesk::kFalse都可以)。因为使用pDb->readDwgFile()函数时,pDb必须是一个完全空白的数据库,也就是说,哪怕使用了AcDbDatabase(false);新建数据库后,只要对数据库进行了操作,就不能再使用readDwgFile()函数,否则会导致严重的内存错误。
数据库对象AcDbObject概述
每一个数据库对象具有以下三种表示方法:
句柄 —— AcDbHandle
对象id —— AcDbObjectId
指针 —— AcDbObect *
三者之间的相互关系
之间相互关系和转换
1. AcDbHandle -> AcDbObjectId
AcDbDatabase ::getAcDbObjectId(&AcDbObjectId ,FALSE, AcDbHandle );
2. AcDbObjectId -> AcDbHandle
AcDbHandle = AcDbObjectId::handle ();
3.AcDbObjectId -> AcDbObject *
acdbOpenObject(AcDbObject *&,AcDbObjectId,AcDb::OpenMode);
4.AcDbObject * -> AcDbHandle
AcDbHandle = AcDbObject::getAcDbHandle();
5.ads_name 和 AcDbObjcetId
一个ads_name 是 一个包含两个long型元素的数组
这个数组的第一个元素就是AcDbObjcetId
6. ads_name 和 AcDbObjcetId相互转换
acdbGetAdsName(ads_name, objId);
acdbGetObjectId(objId, ads_name);
怎样访问数据库对象?
打开对象的方法:
acdbOpenObject() 该函数为模板函数,能打开任意对象
acdbOpenAcDbObject()
acdbOpenAcDbEntity()
打开对象的模式:
AcDb::kForRead //只读
AcDb::kForWrite //可写
AcDb::kForNotify //通知
升级和降级访问:
AcDbObject::upgradeOpen(); //升级为写
AcDbObject::downgradeOpen(); //降级为读
删除对象
AcDbObject::erase()
用事务方式访问
事务
AcTransaction * AcTransactionManager::startTransaction
AcTransactionManager::endTransaction()
AcTransactionManager::abortTransaction(),
virtual Acad::ErrorStatus getObject(AcDbObject*& obj, AcDbObjectId objectId, AcDb::OpenMode mode, bool openErasedObject = false)
对象访问限制
如果一个对象被写打开,则在关闭前不能再被读打开或写打开
如果一个对象被读打开,则在关闭前不能再被写打开,但可被读打开(一个对象最多可同时被打开128次)
对象类型识别
desc():
a static member function that returns the class descriptor object of a particular (known) class.
cast():
a static member function that returns an object of the specified type, or NULL if the object is not of the required class (or a derived class).
isKindOf():
returns whether an object belongs to the specified class (or a derived class).
isA():
returns the class descriptor object of an object whose class is unknown.
AcRxClass
例如:
AcDbEntity* curEntity = somehowGetAndOpenAnEntity();
if (curEntity->isKindOf(AcDbEllipse::desc())) { }
If(curEntity->isA() == AcDbEllipse::desc()){ }
AcDbLine * pLine = AcDbLine ::cast(curEntity )
AutoCAD里的交互
AcEd 全局函数
String, number acquisition
acedGetInt used to get an integer valueacedGetReal used to get a real valueacedGetString used to get a stringacedGetDist used to get the distance between two points
Point, angle acquisition
acedGetAngle used to get a angle valueacedGetPoint used to pick a pointacedGetCorner
Entity selection
acedEntSel used to select a single entityacedNEntSel used to select a single, nested entityacedNEntSelP used to select a single, nested entityacedSSGet used to select multiple entities
Others
acedGetKword used to get a key wordacedInitGet used to initialize acedGetXXXX functionsacedGetFileD used to retrieve file selection from a file dialog
向ACAD发送命令
acedCommand:立即执行
acedCommand(RTSTR, "zoom", RTSTR, "e", 0);
sendStringToExecute:作为下一个命令执行
CString strCmd;
strCmd.Format("_HNBMReservedAreaModified %d %d ", (long)ReservedAreaHandle, nType);
acDocManager->sendStringToExecute(acDocManager->curDocument(), strCmd, false, true, false);
共同点:都不能执行有用户交互的命令
WCS,UCS,OCS(ECS)
规则:数据库中对象保存的点坐标是WCS坐标(建议);而一些acedXX函数(如acedGetPoint,acedEntSel等)、list命令一般是UCS坐标。
WCS与UCS相互转换
//UCS坐标系
fromrb.restype = RTSHORT;
fromrb.resval.rint = 1;
//WCS坐标系
torb.restype = RTSHORT;
torb.resval.rint = 0;
acedTrans(pt_ucs,&fromrb,&torb,FALSE,resultPt);
acdbUcs2Wcs
acdbWcs2Ucs
AcDbEntity::getEcs
UCS常用函数及类
函数:Acad::ErrorStatus acedGetCurrentUCS(AcGeMatrix3d& mat);
(以下函数和类可看作符号表的操作模式)
函数:Acad::ErrorStatus getSymbolTable(AcDbUCSTable*& pTable,AcDb::OpenMode mode);
类:AcDbUCSTable
类:AcDbUCSTableRecord
ARX应用向导
应用向导:ObjectARX 2006的在\ObjectARX 2006\utils\ObjARXWiz目录下。
功能:与MFC应用向导类似
产生工程
产生特定类及函数
ARX,DBX加载/卸载
加载
ap(appload)
arx
其它方式(lisp文件,注册表等)
卸载
ap
arx
ARX软件结构
加载:On_kInitAppMsg
卸载:On_kUnloadAppMsg
命令映射(arx2006或以上):
static void INTECAD_INTESelect(void)
{
}
ACED_ARXCOMMAND_ENTRY_AUTO(CINTECADApp, INTECAD, _INTESelect, INTESelect, ACRX_CMD_TRANSPARENT, NULL)
ARX & MFC
ObjectARX 完全支持MFC。
两个MFC基类 AdUi and AcUi。
注意:在调用资源时加上这句话 CAcModuleResourceOverride resOverride;
对话框
资源转换,多个ARX时可能需要
CAcModuleResourceOverride resOverride;
或
AfxSetResourceHandle (_hdllInstance) ;
AfxSetResourceHandle (acedGetAcadResourceInstance ()) ;
菜单与工具条
通过菜单文件
COM方式添加
例1:基本操作
建立应用程序
建立命令
实现功能:选中一实体,然后输出其信息
例2:重复产生同半径的圆
对话框输入半径
用鼠标指定圆心
数据库结构查看工具
ARXDBG工具的使用
位置:\ObjectARX 2006\samples\database\ARXDBG
文档:ArxDbg.doc
本节结束
下节将介绍自定义实体的内容
自定义对象类
一般从 AcDbObject 或AcDbEntity派生
AcDbObject:不须显示,如字典对象
AcDbEntity:可显示/操作的实体
从其他(如AcDbLine等实体类)派生:根据需要
自定义类可继续从另一个自定义继承,从而继承体系成树状结构
编写时遵守一定的规则
放在DBX工程中
自定义类特点
头文件
ACRX_DECLARE_MEMBERS
ACDB_REGISTER_OBJECT_ENTRY_AUTO
版本
CPP文件
ACRX_DXF_DEFINE_MEMBERS
AcDbProxyEntity::kNoOperation
assertReadEnabled ()与assertWriteEnabled () ;
读写控制
显示刷新
UNO/REDO
DBX加载/卸载
在ARX中调用
acrxLoadModule/acrxUnloadModule
ARX在使用DBX的LIB库时,可能会出现诸如:acrxGetApiVersion找不到或ARX加载失败的问题.解决方法:
在ARX和DBX工程中都增加def文件,文件内容如下:
EXPORTS
acrxEntryPoint PRIVATE
acrxGetApiVersion PRIVATE
自定义对象-读入/写出
作用
文件(DWG,DXF)读写
UNDO/REDO
CLONE
函数
virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* filer);
virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* filer) const;
virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* filer);
virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* filer) const;
AcDbDwgFiler
类中常用函数
virtual Acad::ErrorStatus readInt32(Adesk::Int32*)
virtual Acad::ErrorStatus writeInt32(Adesk::Int32)
virtual Acad::ErrorStatus readString(char**)
virtual Acad::ErrorStatus writeString(const char*)
virtual Acad::ErrorStatus readPoint3d(AcGePoint3d*)
virtual Acad::ErrorStatus writePoint3d(const AcGePoint3d&)
virtual Acad::ErrorStatus readAcDbHandle(AcDbHandle*)
virtual Acad::ErrorStatus writeAcDbHandle(const AcDbHandle&)
virtual Acad::ErrorStatus readBytes(void *, Adesk::UInt32)
virtual Acad::ErrorStatus writeBytes(const void *, Adesk::UInt32)
读字符串
char *str=NULL;
pFiler->readString(&str);
m_strPanelType=str;
acutDelString(str);
自定义对象-显示
函数:
virtual Adesk::Boolean worldDraw( AcGiWorldDraw* mode);
virtual void viewportDraw(AcGiViewportDraw* mode);
区别
worldDraw函数用来生成跟视图无关的几何图形,它只生成一组几何图形,其他的因为视图的变化而导致的几何图形变化都由AutoCAD来自动调整,举个例子,你生成一个立方体,这个立方体从不同的角度看所看到的外形是不一样的,但是worldDraw只生成一个角度的几何图形,其他的都由AutoCAD来自动的调整了。
viewportDraw则不同,它可以根据不同的视图生成不同的几何图形,当你的视图改变的时候,它自动将几何图形调整到正确的状态。有时候这两个函数需要配合使用,例如,如果你画圆,那就可以用worldDraw,因为无论你怎么变换视图圆还是圆。但是如果你生成一些表示立体的几何图形有时候就需要借助于viewportDraw了,因为对于立体图形来说不同的视图看到的是不一样的。举个例子来说明其区别就是worldDraw画出来的立体图形,你改变了角度(也算viewport改变)后看到的有可能就不是立体图形了,但是你用viewportDraw画出来的就不会出现这样的问题。
AcGiWorldDraw与AcGiViewportDraw
类似,但AcGiViewportDraw有视口相关的矩阵和方向函数
通过geometry得到绘图类AcGiWorldGeometry 的对象
通过subEntityTraits得到环境设置类AcGiSubEntityTraits 对象
AcGiWorldGeometry与AcGiGeometry
circle
circularArc
Polyline(多段线)
polygon
text
pline(多义线,类似于AcDbPolyline)
AcGiSubEntityTraits
常用函数
virtual void setColor(const Adesk::UInt16 color) = 0;
virtual void setTrueColor(const AcCmEntityColor& color) = 0;
virtual void setLayer(const AcDbObjectId layerId) = 0;
virtual void setLineType(const AcDbObjectId linetypeId) = 0;
virtual void setFillType(const AcGiFillType) = 0;
virtual void setLineWeight(const AcDb::LineWeight lw) = 0;
virtual void setLineTypeScale(double dScale = 1.0) = 0;
注意
一个自定义对象的不同部分可分属不同层
是否填充只针对circle,polygon等封闭图形
例1 自定义实体-读写/显示
生成一等边三角形的自定义实体
中心
外接圆半径
方位角
自定义对象-夹点
virtual Acad::ErrorStatus getGripPoints(AcGePoint3dArray& gripPoints, AcDbIntArray& osnapModes, AcDbIntArray& geomIds) const;
virtual Acad::ErrorStatus moveGripPointsAt( const AcDbIntArray& indices, const AcGeVector3d& offset);
自定义对象-移动
virtual Acad::ErrorStatus transformBy( const AcGeMatrix3d& xform);
自定义对象-拷贝
virtual Acad::ErrorStatus deepClone(AcDbObject* pOwnerObject, AcDbObject*& pClonedObject, AcDbIdMapping& idMap, Adesk::Boolean isPrimary = true) const;
virtual Acad::ErrorStatus wblockClone(AcRxObject* pOwnerObject, AcDbObject*& pClonedObject, AcDbIdMapping& idMap, Adesk::Boolean isPrimary = true) const;
自定义对象-炸开
virtual Acad::ErrorStatus explode(AcDbVoidPtrArray& entitySet) const;
自定义对象-捕捉点
virtual Acad::ErrorStatus getOsnapPoints( AcDb::OsnapMode osnapMode, int gsSelectionMark, const AcGePoint3d& pickPoint, const AcGePoint3d& lastPoint, const AcGeMatrix3d& viewXform, AcGePoint3dArray& snapPoints, AcDbIntArray& geomIds) const;
自定义对象-范围
virtual Acad::ErrorStatus getGeomExtents(AcDbExtents& extents) const;
自定义对象-list
作用:调试检查用.
virtual void list() const;
自定义对象-相交点
virtual Acad::ErrorStatus intersectWith(const AcDbEntity* pEnt,AcDb::Intersect intType,AcGePoint3dArray& points,int thisGsMarker = 0,int otherGsMarker = 0) const;
自定义对象- sub事件
virtual Acad::ErrorStatus subErase(Adesk::Boolean erasing);
virtual Acad::ErrorStatus subOpen(AcDb::OpenMode mode);
virtual Acad::ErrorStatus subClose();
理解拖动夹点与平移实体的工作方式
在拖动夹点时,ACAD调用自定义对象重载的moveGripPointsAt函数。但这时你要注意:此时的this指针指向的自定义对象A并非数据库中待修改的对象B,A只是ACAD复制的一个用于操作的临时对象,它的所有持久性(即保存到文件中的)参数与B相同,非持久性参数保持构造函数时的值。A并没有被加入到数据库中,所以在moveGripPointsAt不能通过database()函数获取数据库指针;A中的参数没有累积性,即在moveGripPointsAt中更改了一个类成员变量m的值,下一次调用moveGripPointsAt时,m的值与B中m值相同,而不是修改过的值。
transformBy与moveGripPointsAt类似。
本节结束
下节将介绍自定义对象生成与编缉
双击修改
动态生成(Jig)
属性页
实体的双击修改
在ARX工程中:从AcDbDoubleClickEdit派生并重载函数:
virtual void startEdit(AcDbEntity *pEnt, AcGePoint3d pt);
virtual void finishEdit(void);
在On_kInitAppMsg中:
if(!acrxDynamicLinker->loadModule(/*MSG0*/"ACDBLCLKEDITPE.ARX",Adesk::kFalse))
{
AfxMessageBox("'ACDBLCLKEDITPE.ARX' Load Failed");
}
// Initialize Double Click Editing
AcDbDoubleClickEdit::rxInit();
acrxBuildClassHierarchy();
TYTriangleDoubleClickEdit *pTriangleDoubleClickEdit=new TYTriangleDoubleClickEdit;
TYTriangle::desc()->addX(AcDbDoubleClickEdit::desc(),pTriangleDoubleClickEdit);
实体的双击修改
On_kUnloadAppMsg函数中:
TYTriangle::desc()->delX(AcDbDoubleClickEdit::desc());
startEdit函数
文档加锁
设置资源
显示对话框
修改实体
文档解锁
例1:自定义实体的双击修改
可改:
外接圆半径
填充
动态创建
AcEdJig
virtual DragStatus sampler () ;
virtual Adesk::Boolean update () ;
virtual AcDbEntity *entity () const ;
DragStatus drag();
AcEdJIg中的用户输入函数
DragStatus acquireString(char *str);
DragStatus acquireAngle(double &ang);
DragStatus acquireAngle(double &ang, const AcGePoint3d& basePnt);
DragStatus acquireDist(double &dist);
DragStatus acquireDist(double &dist, const AcGePoint3d& basePnt);
DragStatus acquirePoint(AcGePoint3d&);
DragStatus acquirePoint(AcGePoint3d&, const AcGePoint3d&basePnt);
注意:不能使用acedXXX函数
AcEdJig:其它函数
const char* keywordList();
void setKeywordList(const char*);
const char* dispPrompt();
void setDispPrompt(const char*, ...);
AcEdJig::CursorType specialCursorType();
void setSpecialCursorType(CursorType);
AcEdJig::UserInputControls userInputControls();
void setUserInputControls(AcEdJig::UserInputControls);
例2:动态生成自定义实体
用向导生成或手工书写
向导生成的AcEdJig派生类有错:
头文件中除去ACRX_DECLARE_MEMBERS
CPP文件中除去ACRX_CONS_DEFINE_MEMBERS
练习
自定义实体
具有N条边的多边形
画出多边形及外接圆
可输入边数N和外接圆半径
动态创建
在创建过程中显示图形
在创建过程中显示并可修改尺寸(选作)
双击修改
属性页
优点:
可批量修改多个实体的属性
操作步骤少
与ACAD的已有操作更加一致
缺点:
实现有点复杂
用户操作习惯问题
生成工程
标准ATL工程
生成ATL类
派生
接口
IDL
DBX中实体类中:
头文件:
static bool s_bHasClsid;
static CLSID s_clsid;
实现:
initCLSID()
getClassID
属性名称及分组
GetDisplayName
GetCategoryName
ShowProperty
预定义值
GetPredefinedStrings
GetPredefinedValue
显示对话框
MapPropertyToPage
IOPMPropertyDialog
字典
字典内可保存多个从AcDbObject派生的对象
可用于保存全局变量,选项设置
AcDbDictionary *pNameDict;
AcDbDictionary *pNameList;
pDb->getNamedObjectsDictionary(pNameDict,AcDb::kForWrite);
if (pNameDict->getAt("TYSOFTHNBMCAD_DICT",(AcDbObject*&)pNameList, AcDb::kForWrite) == Acad::eKeyNotFound)
{
pNameList = new AcDbDictionary;
AcDbObjectId DictId;
pNameDict->setAt("TYSOFTHNBMCAD_DICT", pNameList, DictId);
}
pNameDict->close();
///打开或创建控制信息对象
AcDbObjectId objId;
HNBMDictItem *pDictItem;
if((pNameList->getAt("TYSOFTHNBMCAD_DICT_ITEM", objId))
== Acad::eKeyNotFound)
{
pDictItem = new HNBMDictItem;
Acad::ErrorStatus err=pNameList->setAt("TYSOFTHNBMCAD_DICT_ITEM", pDictItem, objId);
if(err!=Acad::eOk)
{
acutPrintf("\nerror in set archinfo!");
delete pDictItem;
pNameList->close();
return;
}
pDictItem->close();
}
pNameList->close();
AcDbDictionary *pNameDict;
AcDbDictionary *pNameList;
pDb->getNamedObjectsDictionary(pNameDict,AcDb::kForRead);
if (pNameDict->getAt("TYSOFTHNBMCAD_DICT",(AcDbObject*&)pNameList,
AcDb::kForRead) == Acad::eKeyNotFound)
{
pNameDict->close();
return NULL;
}
pNameDict->close();
AcDbObjectId objId;
HNBMDictItem *pDictItem;
if((pNameList->getAt("TYSOFTHNBMCAD_DICT_ITEM", objId))== Acad::eKeyNotFound)
{
pNameList->close();
return NULL;
}
pNameList->close();
if (acdbOpenObject((AcDbObject*&)pDictItem, objId,AcDb::kForRead) == Acad::eOk)
{
return pDictItem;
}
层
AcDbLayerTable *pLayerTable;
es=pDB->getSymbolTable(pLayerTable, AcDb::kForWrite);
if(es!=Acad::eOk)
{
pLinetypeTable->close();
return;
}
if(!pLayerTable->has("木作线(RoomLine)"))
{
pLayerTableRecord =new AcDbLayerTableRecord;
pLayerTableRecord->setName("木作线(RoomLine)");
pLayerTableRecord->setIsFrozen(false);
pLayerTableRecord->setIsOff(false);
pLayerTableRecord->setIsLocked(false);
pLayerTableRecord->setVPDFLT(false);
color.setColorIndex(3);
pLayerTableRecord->setColor(color);
pLinetypeTable->getAt("Continuous", LinetypeId);
pLayerTableRecord->setLinetypeObjectId(LinetypeId);
pLayerTableRecord->setLineWeight(AcDb::kLnWtByLwDefault);
pLayerTable->add(pLayerTableRecord);
pLayerTableRecord->close();
}
pLayerTable->close();
线型
pDB->loadLineTypeFile("DASHED", "acad.lin");//虚线
pDB->loadLineTypeFile(“CENTER”, “acad.lin”);//中心线
AcDbLinetypeTable *pLinetypeTable=NULL;
Acad::ErrorStatus es=pDB->getSymbolTable(pLinetypeTable, AcDb::kForRead);
if(es!=Acad::eOk)
return;
AcDbLayerTable *pLayerTable;
es=pDB->getSymbolTable(pLayerTable, AcDb::kForRead);
if(es!=Acad::eOk)
{
pLinetypeTable->close();
return;
}
AcDbObjectId LinetypeId;
pLinetypeTable->getAt("CENTER", LinetypeId);
pLineTypeTable->close();
文字样式
AcDbTextStyleTable *pTextStyleTable=NULL;
Acad::ErrorStatus es=pDB->getSymbolTable(pTextStyleTable, AcDb::kForWrite);
if(es==Acad::eOk)
{
if(!pTextStyleTable->has("宋体-35"))
{
AcDbTextStyleTableRecord *pTextStyleTableRecord=new AcDbTextStyleTableRecord;
pTextStyleTableRecord->setName("宋体-35");
pTextStyleTableRecord->setFont("宋体", FALSE, FALSE, GB2312_CHARSET, DEFAULT_PITCH|FF_ROMAN);
pTextStyleTableRecord->setTextSize(3.5);
pTextStyleTableRecord->setXScale(0.8);
pTextStyleTable->add(pTextStyleTableRecord);
pTextStyleTableRecord->close();
}
if(!pTextStyleTable->has("HZ-35"))
{
AcDbTextStyleTableRecord *pTextStyleTableRecord=new AcDbTextStyleTableRecord;
pTextStyleTableRecord->setName("HZ-35");
pTextStyleTableRecord->setFileName("txt.shx");
pTextStyleTableRecord->setBigFontFileName("hztxt.shx");
pTextStyleTableRecord->setTextSize(3.5);
pTextStyleTableRecord->setXScale(0.8);
Acad::ErrorStatus es=pTextStyleTable->add(pTextStyleTableRecord);
pTextStyleTableRecord->close();
}
pTextStyleTable->close();
}
扩展数据
XData 容量受限制,只能存储<=16K
AcDbObject::xData ()
AcDbObject::setXData()
(entget( car ( entsel))' ("*") )
封装类:AcXdLocalVar
XRecord 容量不受限制
本质上没有区别,存贮的都是resbuf结构的链表
如果对象是自定义实体,存储非图形数据也可以作为该实体对象的属性存储起来
XDATA举例
(-3 ("INTECAD_HUST_CAD_CENTER" (1000 .
"BILLITEM") (1002 . "{") (1000 . "index") (1070 . 1) (1000 . "code") (1000 .
"C5A") (1000 . "name") (1000 . "E5A") (1000 . "quantity") (1000 . "G5A") (1000
. "lineblock") (1005 . "0") (1000 . "circle") (1005 . "21B") (1002 . "}") (1000
. "OBJECT") (1002 . "{") (1000 . "OBJECTID") (1000 . "BILLITEM") (1002 . "}"))))
为一链表,表头为RegAppName,每一节点为一resbuf的结构,此结构为联合数据结构,可存字符串,整数等类型
struct resbuf *pRb, *pTemp;
pRb = pObj->xData("architech_3d_code";);
if (pRb != NULL)
{
// If xdata is present, then walk to the end of the list.
for (pTemp = pRb; pTemp->rbnext != NULL; pTemp = pTemp->rbnext)
;
}
else
{
//以调用过acdbRegApp(“architech_3d_code”);
pRb = acutNewRb(AcDb::kDxfRegAppName);
pTemp = pRb;
pTemp->resval.rstring = (TCHAR*) new TCHAR[GetArchitechCodeName().GetLength() + 1];
_tcscpy(pTemp->resval.rstring, GetArchitechCodeName());
}
// Add user-specified std::TSTDSTRING to the xdata.
pTemp->rbnext = acutNewRb(AcDb::kDxfXdAsciiString);
pTemp = pTemp->rbnext;
pTemp->resval.rstring = (TCHAR*) new TCHAR[_tcslen(resString) + 1];
_tcscpy(pTemp->resval.rstring, resString);
// The following code shows the use of upgradeOpen() to change the entity from read to write.
pObj->upgradeOpen();
pObj->setXData(pRb);
acutRelRb(pRb);
XRecord创建
创建对象的扩展字典
AcDbObject::createExtensionDictionary();
AcDbObjectId AcDbObject::extensionDictionary();
生成AcDbXrecord并加入字典
AcDbXrecord *pXrec = new AcDbXrecord
acdbOpenObject(pDict, dictObjId, AcDb::kForWrite);
pDict->setAt("ASDK_XREC1", pXrec, xrecObjId);
用链表填充AcDbXrecord
pXrec->setFromRbChain(*head);
反应器
非持久性(transient Reactor)
数据库反应器:AcDbDatabaseReactor
文档反应器:AcApDocManagerReactor
其它
持久性(persistent Reactor)
数据库中的对象之间
区别:是否能保存到数据库中
持久反应器-建立
TYTriangle *pTriangle=new TYTriangle;
AcDbObjectId TriangleId;
AppendEntityToDb(pTriangle, NULL, &TriangleId);
pTriangle->close();
AcDbLine *pL=new AcDbLine(AcGePoint3d(0, 50, 0), AcGePoint3d(100, 50, 0));
AppendEntityToDb(pL);
pL->addPersistentReactor(TriangleId);
pL->close();
持久反应器-事件处理
void TYTriangle::modified (const AcDbObject* dbObj)
{
if(dbObj->isKindOf(AcDbLine::desc()))
{
AcDbLine *pLine=AcDbLine::cast(dbObj);
AcGeVector3d dir=pLine->startPoint()-pLine->endPoint();
double dblAngle=AcGeVector3d::kXAxis.angleTo(dir, AcGeVector3d::kZAxis);
Adesk::Boolean kWritable;
Acad::ErrorStatus es=upgradeFromNotify(kWritable);
if(es==Acad::eOk)
{
if(isWriteEnabled())
{
SetStartAngle(dblAngle);
}
downgradeToNotify(kWritable);
}
}
}
AutoCAD二次开发特点总结
ObjectARX:面向对象,功能强大,事实上的工业标准(类似者:ZRX,CRX)
学习材料丰富,代码多,开发人员多,交流方便,入门容易
市场需求大
进入门槛低
是用于学习和练习C++和CAD开发的不错选择
~完~
谢谢各位!
展开