|
[code]1. 说明
本节介绍的实例,能将当前图形中“测试”图层上所有直线对象的颜色变为红色。该实例演示了块表记录遍历器的使用,为获取图形中某一类具有相同特征的实体提供了一种方法。
2. 思路
ObjectARX 提供了一种称为遍历器的类,用来遍历(逐个访问)某一集合中所有的对象,比如,遍历当前图形中所有的图层、实体等。
如下代码, 显示了块表记录遍历器的使用要点:
//创建块表记录遍历器
AcDbBlockTableRecordIterator *pItr; //块表记录遍历器
pBlkTblRcd->newIterator(pItr);
AcDbEntity *pEnt; 遍历的临时实体指针
for (pItr->start(); !pItr->done(); pItr->step())
{
//利用遍历器获得每一个实体
pItr->getEntity(pEnt,AcDb::kForWrite);
//对pEnt所指向的实体进行各种编辑
……
//注意需要关闭实体
pEnt->close();
}
delete pItr; // 遍历器使用完毕之后一定要删除!
块表记录遍历器的使用非常简单,简单的说就是三个步骤:创建遍历器;使用遍历器遍历实体;删除遍历器。
3. 步骤
(1) 在CGeometryOper类中创建一个GetEntsOnLayer() 函数
在获得指定名称的层表记录之前,要判断当前图形中是否包含指定的图层,可以使用AcDbLayerTable::has 函数来实现。如果块表中包含与指定名称相同的层表记录,该函数返回
true ,否则返回 false 。
使用遍历器时必须注意,遍历一个集合对象要使用其对应的遍历器,例如本篇的实例遍历块表记录就是用了块表记录遍历器。声明块表记录遍历器指针之后,还要使用 newIterator 函数创建当前图形模型空间块表记录的遍历器。遍历器在使用完毕后一定要删除,否则就会引起 AutoCAD 的错误退出。
判断实体是否在指定的图层上,可以使用两种方法:
A. 使用 AcDbEntity 类的 layer 函数获得实体所在图层的名称,然后与指定图层的名称进行比较,例如( acutDelString 函数需要添加对 acutmem.h 头文件的包含):
char *layerName = pEnt->layer();
if (strcmp(layerName, _T("测试")) == 0)
{
// 执行需要的操作
……
}
acutDelString(layerName);// 释放layer函数返回的字符串所占的内存
B. 使用 AcDbEntity 类的 layerId 函数获得实体所在图层的 ID,然后与指定图层的 ID 进行比较。本篇的实例中使用的就是这样方法。
void GetEntsOnLayer();
//获取某一层上的实体("测试"图层)
void CGeometryOper::GetEntsOnLayer()
{
// 判断是否存在名称为“测试”的图层
AcDbLayerTable *pLayerTbl;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLayerTbl, AcDb::kForRead);
if (!pLayerTbl->has(_T("测试")))
{
acutPrintf(_T("\n当前图形中未包含\"测试\"图层!"));
pLayerTbl->close();
return;
}
AcDbObjectId layerId; // “测试”图层的ID
pLayerTbl->getAt(_T("测试"), layerId);
pLayerTbl->close();
// 获得当前数据库的块表
AcDbBlockTable *pBlkTbl;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLayerTbl, AcDb::kForRead);
// 获得模型空间的块表记录
AcDbBlockTableRecord *pBlkTblRcd;
pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd,AcDb::kForRead);
pBlkTbl->close();
//创建块表记录遍历器
AcDbBlockTableRecordIterator *pItr; //块表记录遍历器
pBlkTblRcd->newIterator(pItr);
AcDbEntity *pEnt; // 遍历的临时实体指针
for (pItr->start(); !pItr->done(); pItr->step())
{
//利用遍历器获得每一个实体
pItr->getEntity(pEnt,AcDb::kForWrite);
//对pEnt所指向的实体进行各种编辑
//是否在"测试"图层上
if (pEnt->layerId() == layerId)
{
// 是否是直线
AcDbLine *pLine = AcDbLine::cast(pEnt);
if (pLine != NULL)
{
pLine->setColorIndex(1); //将直线的颜色修改为红色
}
}
//注意需要关闭实体
pEnt->close();
}
delete pItr; // 遍历器使用完毕之后一定要删除!
pBlkTblRcd->close();
}
(2) 在acrxEntryPoint.cpp中
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyGetEntsOnLayer, MyGetEntsOnLayer, ACRX_CMD_MODAL, NULL) //获取某一图层并改变颜色
//当前项目中注册一个命令 GetEntsOnLayer
static void MidasMyGroupMyGetEntsOnLayer()
{
CGeometryOper m_geometryOper;
m_geometryOper.GetEntsOnLayer();
}
原文链接:https://blog.csdn.net/qq_42981953/article/details/121840963[/code] |
|