实体AcDbBlockReference :块参照,块引用数据库
块表AcDbBlockTable 数组
表记录AcDbBlockTableRecord:块定义,块表记录,app
(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)插入块参照:块定义不是一个实体,而是一种对实体的描述,经过定义块得到;块参照则是一种实体,图形窗口中显示的“块”都是块参照,经过插入块得到。this
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 中的“属性” ) ,能够直接建立该类的一个对象,而后将其添加到块表记录中。3d
// 建立一个属性 输入直径 AcDbAttributeDefinition *pAttDef = new AcDbAttributeDefinition(ptEnd, "20", "直径", "输入直径"); // 向块表记录中添加实体 pBlkTblRcd->appendAcDbEntity(entId, pAttDef);
(4)插入带属性的块参照:包含块参照和属性两个部分,属性不能直接存在于图形窗口中,而必须依附于块参照存在。指针
插入一个普通的块参照后,使用遍历器遍历块参照对应的块表记录,若是找到一个属性定义,就建立一个属
性,而且附加到块参照上。code
// 判断指定的块表记录是否包含属性定义 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)查看块定义的图标orm
得到指定的块表记录的预览图像
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);