思路:
(1)使用ObjectARX向导创建一个新工程Xrecord.
注册命令AddXRecord,提示用户选择一个实体,并将一些附加的数据保存到该实体的扩展字典中。
实现函数:
static void AAAMyGroupAddRecord() {
//提示用户选择所要添加扩展记录的图形对象
AcDbEntity *pEnt = NULL;
AcGePoint3d pickPoint;
if (CSelectUtil::PromptSelectEntity(TEXT("\\n 选择所要添加扩展记录的实体"),
AcDbEntity::desc(),pEnt,pickPoint))
{
//向实体中添加扩展字典
pEnt->createExtensionDictionary(); //为实体建立扩展字典
AcDbObjectId dictObjId = pEnt->extensionDictionary(); //获得
//实体的扩展字典
pEnt->close();
//创建扩展记录实体
AcDbXrecord *pXrec = new AcDbXrecord;
//向扩展字典中添加一条记录
AcDbObjectId xRecObjId;
AcDbDictionary *pDict = NULL;
if (acdbOpenObject(pDict,dictObjId,AcDb::kForWrite) == Acad::eOk)
{
pDict->setAt(TEXT("XRecord"), pXrec, xRecObjId);
pDict->close();
}
//设置扩展记录的内容
struct resbuf* pRb = acutBuildList(AcDb::kDxfText, TEXT("测试字符串数据"),
AcDb::kDxfInt32, 12,
AcDb::kDxfReal, 3.14,
AcDb::kDxfXCoord, asDblArray(pickPoint),
RTNONE);
pXrec->setFromRbChain(*pRb); //扩展数据内容填充扩展记录对象
pXrec->close();
acutRelRb(pRb);
}
}
代码段:pDict->setAt(TEXT("XRecord"), pXrec, xRecObjId);
代码表示:如果"XRecord"还没有在字典中存在,那么这个函数就会在字典中添加新的条目,并将它添加到字典中。如果带有关键"XRecord"的条目已经存在,那么现有的条目将被删除,字典从它的反应堆列表中删除,并且它被新的值对象替换为它所处的字典。该对象的名称由"XRecord"指定。对象的objectId条目在 xRecObjId中返回。
"XRecord" | 输入字符串表示对象的搜索键名 |
pXrec | 输入指向新对象的指针以添加到字典中 |
xRecObjId | 返回新添加对象的对象ID |
其中,PromptSelectEntity函数的实现:
首先,创建一个类CSelectUtil,在此类中实现PromptSelectEntity。
函数的声明:
// 提示用户选择某个类型的实体
// 注意:调用者必须关闭实体
static bool PromptSelectEntity(const TCHAR* prompt, AcRxClass* classDesc, AcDbEntity *&pEnt, AcGePoint3d &pickPoint,
bool bOpenForWrite = true);
static bool PromptSelectEntity(const TCHAR* prompt, const std::vector<AcRxClass*> &classDescs, AcDbEntity *&pEnt,
AcGePoint3d &pickPoint, bool bOpenForWrite = true);
函数的实现:
bool CSelectUtil::PromptSelectEntity( const TCHAR* prompt, AcRxClass* classDesc, AcDbEntity *&pEnt,
AcGePoint3d &pickPoint, bool bOpenForWrite /*= true*/ )
{
std::vector<AcRxClass*> descs;
descs.push_back(classDesc);
return PromptSelectEntity(prompt, descs, pEnt, pickPoint, bOpenForWrite);
}
bool CSelectUtil::PromptSelectEntity( const TCHAR* prompt, const std::vector<AcRxClass*> &classDescs, AcDbEntity *&pEnt,
AcGePoint3d &pickPoint, bool bOpenForWrite /*= true*/ )
{
ads_name ename;
RETRY:
if (acedEntSel(prompt, ename, asDblArray(pickPoint)) != RTNORM)
{
pEnt = NULL;
return false;
}
AcDbObjectId entId;
acdbGetObjectId(entId, ename);
// 判断选择的实体是否是指定类型的实体
Acad::ErrorStatus es;
if (bOpenForWrite)
{
es = acdbOpenObject(pEnt, entId, AcDb::kForWrite);
}
else
{
es = acdbOpenObject(pEnt, entId, AcDb::kForRead);
}
assert (es == Acad::eOk);
bool bRet = false;
for (int i = 0; i < (int)classDescs.size(); i++)
{
if (pEnt->isKindOf(classDescs[i]))
{
bRet = true;
break;
}
}
if (bRet)
{
return true;
}
else
{
pEnt->close();
acutPrintf(TEXT("\\n选择的实体类型不合要求, 请再次选择..."));
goto RETRY;
}
}
添加头文件:
#include <vector>
(2)注册新命令ViewXRecord,查看扩展字典中“XRecord”元素所保存的数据。
实现函数:
static void AAAMyGroupViewXRecord() {
//提示用户选择所要查看扩展记录的图形对象
AcDbEntity *pEnt = NULL;
AcGePoint3d pickPoint;
if (CSelectUtil::PromptSelectEntity(TEXT("\\n选择所要查看扩展记录的实体:"),
AcDbEntity::desc(),pEnt,pickPoint))
{
//获得实体的扩展字典
AcDbObjectId dictObjId = pEnt->extensionDictionary();
pEnt->close();
if (dictObjId.isNull())
{
acutPrintf(TEXT("\\n 所选择的实体不包含扩展字典!"));
return;
}
//打开扩展字典,获得与关键字"XRecord"关联的扩展记录
AcDbDictionary *pDict = NULL;
AcDbXrecord *pXrec = NULL;
struct resbuf *pRb = NULL;
if (acdbOpenObject(pDict,dictObjId,AcDb::kForRead) == Acad::eOk)
{
pDict->getAt(TEXT("xRecord"), (AcDbObject*&)pXrec, AcDb::kForRead);
//获得扩展记录的数据链表并关闭扩展数据对象
pXrec->rbChain(&pRb);
pXrec->close();
pDict->close();
}
if (pRb != NULL)
{
//在命令行显示扩展记录内容
struct resbuf *pTemp = pRb;
acutPrintf(TEXT("\\n字符串类型的扩展数据是:%s"), pTemp->resval.rstring);
pTemp = pTemp->rbnext;
acutPrintf(TEXT("\\n整数类型的扩展数据是:%d"), pTemp->resval.rint);
pTemp = pTemp->rbnext;
acutPrintf(TEXT("\\n整数类型的扩展数据是:%.2f"), pTemp->resval.rreal);
pTemp = pTemp->rbnext;
acutPrintf(TEXT("\\n点坐标类型的扩展数据是:(%.2f,%.2f,%.2f)"),
pTemp->resval.rpoint[X], pTemp->resval.rpoint[Y],
pTemp->resval.rpoint[Z]);
acutRelRb(pRb);
}
}
}
(3)注册命令AddNameDict,向当前的图形数据库中添加一个字典,并在其中保存自定义数据。
实现函数为:
static void AAAMyGroupAddNameDict() {
// 获得有名对象字典,向其中添加指定的字典项
AcDbDictionary *pNameObjDict = NULL;
acdbHostApplicationServices()->workingDatabase()
->getNamedObjectsDictionary(pNameObjDict,
AcDb::kForWrite);
//检查所要添加的字典项是否已经存在
AcDbObjectId dictObjId;
AcDbDictionary *pDict = NULL;
if (pNameObjDict->getAt(TEXT("MyDict"), (AcDbObject*&)pDict,
AcDb::kForWrite)
== Acad::eKeyNotFound)
{
pDict = new AcDbDictionary;
pNameObjDict->setAt(TEXT("MyDict"), pDict, dictObjId);
pDict->close();
}
pNameObjDict->close();
//向新建的字典中添加一个图层对象
if (acdbOpenObject(pDict, dictObjId, AcDb::kForWrite) == Acad::eOk)
{
AcDbLayerTableRecord *pLayer = new AcDbLayerTableRecord();
AcCmColor color;
color.setColorIndex(20);
pLayer->setColor(color);
pLayer->setIsOff(true);
pLayer->setIsFrozen(true);
AcDbObjectId layerId;
Acad::ErrorStatus es = pDict->setAt(TEXT("LayerKey"), pLayer, layerId);
pLayer->close();
pDict->close();
}
}
(4)注册一个新命令ViewNameDict,检查当前图形中是否包含指定的用户字典,并在命令窗口中显示字典中保存的自定义数据。
实现函数:
static void AAAMyGroupViewNameDict() {
// 获得对象有名字典中指定的字典项
AcDbDictionary *pNameObjDict = NULL;
Acad::ErrorStatus es;
acdbHostApplicationServices()->workingDatabase()
->getNamedObjectsDictionary(pNameObjDict, AcDb::kForRead);
AcDbDictionary *pDict = NULL;
es = pNameObjDict->getAt(TEXT("MyDict"), (AcDbObject*&)pDict,
AcDb::kForRead);
pNameObjDict->close();
//如果不存在指定的字典项,则退出程序
if (es == Acad::eKeyNotFound)
{
acutPrintf(TEXT("\\n 不存在字典项MyDict."));
return;
}
//获得指定的对象字典中的对象
AcDbLayerTableRecord *pLayer = NULL;
if (pDict->getAt(TEXT("LayerKey"), (AcDbObject*&)pLayer, AcDb::kForRead)
== Acad::eOk)
{
//获得实体信息
int colorIndex = pLayer->color().colorIndex();
bool bOff = pLayer->isOff();
bool bFrozen = pLayer->isFrozen();
pLayer->close();
//在命令行打印实体信息
acutPrintf(TEXT("\\n 字典中的图层颜色: %d"), colorIndex);
acutPrintf(TEXT("\\n 字典中的图层是否是关闭状态: %s"), bOff ?
TEXT("是") : TEXT("否"));
acutPrintf(TEXT("\\n 字典中的图层是否是冻结状态: %s"), bFrozen ?
TEXT("是") : TEXT("否"));
}
pDict->close();
}
效果:
①在AutoCAD中加载应用程序,并执行AddXRecord,在图形窗口中选择一个实体,即可为图形添加扩展字典
②执行ViewXReocrd命令,查看扩展字典:
③利用ArxDbg工具查看:
⑥执行命令AddNameDict向图形的有名对象字典中添加用户字典。
⑦执命令ViewNameDict:
⑧ 使用ArxDbg也能观察有名对象字典的内容:
项目的完整源代码:
https://pan.baidu.com/s/13Lj9mF_08oM26oqRlMnCxg
参考资料:
张帆《AutoCAD ObjectARX(VC)开发基础与实例教程》
暂无评论内容