实体AcDbBlockReference :块参照,块引用
块表AcDbBlockTable
表记录AcDbBlockTableRecord:块定义,块表记录,
(1)创建块定义:所有的实体都保存在块表记录中,而块表记录则存储在块表中。定义块相当于增加了一个块表记录,块表记录的名称就是块定义的名称。
当前图形的块表中包含了五个记录:*Model_Space(模型空间)、*Paper_Space(图纸空间中的“布局1”)、*Paper_Space0(图纸空间中的“布局2”)、 “圆形”和“矩形” 。
void ZffCHAP3AddBlk()
{
// 获得当前图形数据库的块表
AcDbBlockTable *pBlkTbl = NULL;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl, AcDb::kForWrite);
// 创建新的块表记录
AcDbBlockTableRecord *pBlkTblRcd = new AcDbBlockTableRecord();
// 根据用户的输入设置块表记录的名称
char blkName[40];
if (acedGetString(Adesk::kFalse, "\n输入图块的名称:", blkName) != RTNORM)
{
pBlkTbl->close();
delete pBlkTblRcd;
return;
}
pBlkTblRcd->setName(blkName);
// 将块表记录添加到块表中
AcDbObjectId blkDefId;
pBlkTbl->add(blkDefId, pBlkTblRcd);
pBlkTbl->close();
// 向块表记录中添加实体
AcGePoint3d ptStart(-10, 0, 0), ptEnd(10, 0, 0);
AcDbLine *pLine1 = new AcDbLine(ptStart, ptEnd); // 创建一条直线
ptStart.set(0, -10, 0);
ptEnd.set(0, 10, 0);
AcDbLine *pLine2 = new AcDbLine(ptStart, ptEnd); // 创建一条直线
AcGeVector3d vecNormal(0, 0, 1);
AcDbCircle *pCircle = new AcDbCircle(AcGePoint3d::kOrigin,vecNormal, 6);
AcDbObjectId entId;
pBlkTblRcd->appendAcDbEntity(entId, pLine1);
pBlkTblRcd->appendAcDbEntity(entId, pLine2);
pBlkTblRcd->appendAcDbEntity(entId, pCircle);
// 关闭实体和块表记录
pLine1->close();
pLine2->close();
pCircle->close();
pBlkTblRcd->close();
}
(2)插入块参照:块定义不是一个实体,而是一种对实体的描述,通过定义块获得;块参照则是一种实体,图形窗口中显示的“块”都是块参照,通过插入块获得。
void ZffCHAP3InsertBlk()
{
acDocManager->lockDocument(curDoc());
// 获得用户输入的块定义名称
char blkName[40];
if (acedGetString(Adesk::kFalse, "\n输入图块的名称:", blkName) !=RTNORM)
return;
// 获得当前数据库的块表
AcDbBlockTable *pBlkTbl = NULL;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl, AcDb::kForWrite);
// 查找用户指定的块定义是否存在
CString strBlkDef;
strBlkDef.Format("%s", blkName);
if (!pBlkTbl->has(strBlkDef))
{
acutPrintf("\n当前图形中未包含指定名称的块定义!");
pBlkTbl->close();
return;
}
// 获得用户输入的块参照的插入点
ads_point pt;
if (acedGetPoint(NULL, "\n输入块参照的插入点:", pt) != RTNORM)
{
pBlkTbl->close();
return;
}
AcGePoint3d ptInsert = asPnt3d(pt);
// 获得用户指定的块表记录
AcDbObjectId blkDefId;
pBlkTbl->getAt(strBlkDef, blkDefId);
// 创建块参照对象
AcDbBlockReference *pBlkRef = new AcDbBlockReference(ptInsert,blkDefId);
//pBlkRef->setPosition(basePoint); //设置插入点
//pBlkRef->setRotation(0.0); //设置旋转角度
//pBlkRef->setNormal(normal);//设置法向量
// 将块参照添加到模型空间
AcDbBlockTableRecord *pBlkTblRcd = NULL;
pBlkTbl->getAt(ACDB_MODEL_SPACE, pBlkTblRcd,AcDb::kForWrite);
AcDbObjectId entId;
pBlkTblRcd->appendAcDbEntity(entId, pBlkRef);
// 关闭数据库的对象
pBlkRef->close();
pBlkTblRcd->close();
pBlkTbl->close();
acDocManager->lockDocument(curDoc());
}
(3)创建带属性的块定义:AcDbAttributeDefinition 类: AcDbText 类的一个派生类,表示属性定义对象,,属性定义是 AutoCAD的一种图形对象(对应于 AutoCAD 中的“属性” ) ,可以直接创建该类的一个对象,然后将其添加到块表记录中。
// 创建一个属性 输入直径
AcDbAttributeDefinition *pAttDef = new AcDbAttributeDefinition(ptEnd, "20", "直径", "输入直径");
// 向块表记录中添加实体
pBlkTblRcd->appendAcDbEntity(entId, pAttDef);
(4)插入带属性的块参照:包含块参照和属性两个部分,属性不能直接存在于图形窗口中,而必须依附于块参照存在。
插入一个普通的块参照后,使用遍历器遍历块参照对应的块表记录,如果找到一个属性定义,就创建一个属
性,并且附加到块参照上。
// 判断指定的块表记录是否包含属性定义
AcDbBlockTableRecord *pBlkDefRcd = NULL;
acdbOpenObject(pBlkDefRcd, blkDefId, AcDb::kForRead);
if (pBlkDefRcd->hasAttributeDefinitions())
{
AcDbBlockTableRecordIterator *pItr = NULL;
pBlkDefRcd->newIterator(pItr);
AcDbEntity *pEnt = NULL;
for (pItr->start(); !pItr->done(); pItr->step())
{
pItr->getEntity(pEnt, AcDb::kForRead);
// 检查是否是属性定义
AcDbAttributeDefinition *pAttDef = NULL;
pAttDef = AcDbAttributeDefinition::cast(pEnt);
if (pAttDef != NULL)
{
// 创建一个新的属性对象
AcDbAttribute *pAtt = new AcDbAttribute();
// 从属性定义获得属性对象的图层特性
pAtt->setPropertiesFrom(pAttDef);
// 设置属性对象的其他特性
pAtt->setInvisible(pAttDef->isInvisible());
AcGePoint3d ptBase = pAttDef->position();
ptBase += pBlkRef->position().asVector();
pAtt->setPosition(ptBase);
pAtt->setHeight(pAttDef->height());
pAtt->setRotation(pAttDef->rotation());
// 获得属性对象的Tag、Prompt和TextString
char *pStr = NULL;
pStr = pAttDef->tag();
pAtt->setTag(pStr);
free(pStr);//也可用全局函数 acutDelString 来代替
pStr = pAttDef->prompt();
acutPrintf("%s%s", "\n", pStr);
free(pStr);
pAtt->setFieldLength(30);
pAtt->setTextString("40");
// 向块参照追加属性对象
pBlkRef->appendAttribute(pAtt);
pAtt->close();
}
pEnt->close();
}
delete pItr;
}
(5)查看块定义的图标
获得指定的块表记录的预览图像
HBITMAP CPreviewBlkDlg::BlockIconToBMP(const AcDbObjectId &blkId, HDC hdc)
{
Acad::ErrorStatus es;
AcDbBlockTableRecord *pBlkTblRcd = NULL; // 块表记录的指针
AcArray<Adesk::UInt8> icon; // 保存预览图标的数组
// 获得保存块表记录的预览图标的数组
try
{
es = acdbOpenObject(pBlkTblRcd, blkId, AcDb::kForRead);
if (es != Acad::eOk)
throw 1;
if (!pBlkTblRcd->hasPreviewIcon()) // 如果块定义不包含预览图标
{
pBlkTblRcd->close();
return NULL;
}
es = pBlkTblRcd->getPreviewIcon(icon);
if (es != Acad::eOk)
throw 2;
es = pBlkTblRcd->close();
if (es != Acad::eOk)
throw 3;
}
catch (...)
{
pBlkTblRcd->close();
return NULL;
}
// 由icon数组获得可显示的位图
BITMAPINFOHEADER ih; // 位图信息头
memcpy(&ih, icon.asArrayPtr(), sizeof(ih));
size_t memsize = sizeof(BITMAPINFOHEADER) + ((1<<ih.biBitCount)* sizeof(RGBQUAD));
LPBITMAPINFO bi = (LPBITMAPINFO)malloc(memsize); // 位图信息
memcpy(bi, icon.asArrayPtr(), memsize);
HBITMAP hbm = CreateDIBitmap(hdc, &ih, CBM_INIT,icon.asArrayPtr() + memsize, bi,DIB_RGB_COLORS);
free(bi);
return hbm;
}
获得当前图形中用户定义的所有块表记录
// 获得当前图形的块表
AcDbBlockTable *pBlkTbl = NULL;
AcDbBlockTableRecord *pBlkTblRcd = NULL;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl, AcDb::kForRead);
// 遍历块表,获得用户自定义块表记录的名称,将其添加到组合框中
AcDbBlockTableIterator *pItr = NULL;
pBlkTbl->newIterator(pItr);
for (pItr->start(); !pItr->done(); pItr->step())
{
pItr->getRecord(pBlkTblRcd, AcDb::kForRead);
char *pName = NULL;
pBlkTblRcd->getName(pName);
CString strName(pName);
acutDelString(pName);
if (strName.Compare(ACDB_MODEL_SPACE) != 0 && strName.Compare(ACDB_PAPER_SPACE) != 0 && strName.Compare("*Paper_Space0"))
{
m_lstBlkDef.AddString(strName);
}
pBlkTblRcd->close();
}
delete pItr;
pBlkTbl->close();
根据选择的块定义,查找对应的预览图标、对应块参照的数量,以及块定义是否包含属性
// 显示预览图标
CPaintDC dc(this);
AcDbBlockTable *pBlkTbl = NULL;
acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl, AcDb::kForRead);
CString strBlkDefName;//定义块的名称
m_lstBlkDef.GetLBText(m_lstBlkDef.GetCurSel(), strBlkDefName);
AcDbObjectId blkTblRcdId;
Acad::ErrorStatus es = pBlkTbl->getAt(strBlkDefName, blkTblRcdId);
HBITMAP hBitmap = BlockIconToBMP(blkTblRcdId, dc.GetSafeHdc());
m_bitmap.SetBitmap(hBitmap);
// 获得块表记录的指针
AcDbBlockTableRecord *pBlkTblRcd = NULL;
pBlkTbl->getAt(strBlkDefName, pBlkTblRcd, AcDb::kForRead);
// 获得块参照的数量
AcDbBlockReferenceIdIterator *pItr = NULL;
pBlkTblRcd->newBlockReferenceIdIterator(pItr);
int number = 0;
for (pItr->start(); !pItr->done(); pItr->step())
{
number++;
}
m_strBlkRefNum.Format("%d", number);
// 获得块参照是否包含属性
if (pBlkTblRcd->hasAttributeDefinitions())
{
m_strHasAttribute = "是";
}
else
{
m_strHasAttribute = "否";
}
pBlkTblRcd->close();
pBlkTbl->close();
UpdateData(FALSE);