今天有一个客户给我发了一个需求,对dwg中选中的块参照进行标记,标记位置在块参照的插入点,标记是一个圆或者矩形,可以调整圆和矩形的大小。
成果如下:
代码如下:
static resbuf* AddBlockSymbolSelectCallback(const TCHAR* sz)
{
if (_tcscmp(sz, _T("S")) == 0 || _tcscmp(sz, _T("s")) == 0)
{
CAcModuleResourceOverride res;
CSymbolSettingDlg dlg;
dlg.DoModal();
}
return NULL;
}
void PluginCommand::AddBlockSymbol()
{
ACHAR kwordlist[] = { _T("S _ s") };
const TCHAR* prompts[2] = {_T("\n框选块进行标记[设置(S)]"), _T("")};
//获取系统回调函数
resbuf* (*DefaultCallback)(const TCHAR*) = NULL;
acedSSGetKwordCallbackPtr(&DefaultCallback);
acedSSSetKwordCallbackPtr(AddBlockSymbolSelectCallback);
ads_name ssname;
struct resbuf* ssfilter = acutBuildList(RTDXF0, _T("INSERT"), 0);
int ret = acedSSGet(_T(":$:K"), prompts, kwordlist, ssfilter, ssname);
acedSSSetKwordCallbackPtr(DefaultCallback);
acutRelRb(ssfilter);
if (ret != RTNORM)
return;
AcDbObjectIdArray idArray = CBaseDwg::GetObjectids(ssname);
acedSSFree(ssname);
if (idArray.isEmpty())
{
acutPrintf(_T("\n未选取到实体!!"));
return;
}
int idLength = idArray.length();
CBlockSymbol blockSymbol;
for (int i = 0; i < idLength; i++)
{
AcDbObjectId id = idArray[i];
//在块的基点进行标记
blockSymbol.AddSymbol(id);
}
}
void CBlockSymbol::AddSymbol(const AcDbObjectId& blockId)
{
AcDbObjectPointer<AcDbBlockReference> pRef;
if (Acad::eOk != pRef.open(blockId, AcDb::kForRead))
return;
AcGePoint3d pt = pRef->position();
int radius = 100, rectWidth = 100, rectHeight = 100, symbolType = 0;
CBaseFile::GetValue(_T("CSymbolSettingDlg/m_radius"), radius, 100);
CBaseFile::GetValue(_T("CSymbolSettingDlg/m_rectWidth"), rectWidth, 100);
CBaseFile::GetValue(_T("CSymbolSettingDlg/m_rectHeight"), rectHeight, 100);
CBaseFile::GetValue(_T("CSymbolSettingDlg/m_symbolType"), symbolType, 0);
if (symbolType == 0)
{
AcGeVector3d xVector = CBaseDwg::XAxis();
AcGeVector3d yVector = CBaseDwg::YAxis();
xVector.normalize();
yVector.normalize();
AcGePoint3d pt1, pt2, pt3, pt4;
pt1 = pt + xVector * rectWidth * 0.5 + yVector * rectHeight * 0.5;
pt2 = pt1 - xVector * rectWidth;
pt3 = pt2 - yVector * rectHeight;
pt4 = pt3 + xVector * rectWidth;
AcDbPolyline* poly = new AcDbPolyline;
poly->addVertexAt(0, AcGePoint2d(pt1.x, pt1.y));
poly->addVertexAt(1, AcGePoint2d(pt2.x, pt2.y));
poly->addVertexAt(2, AcGePoint2d(pt3.x, pt3.y));
poly->addVertexAt(3, AcGePoint2d(pt4.x, pt4.y));
poly->setClosed(Adesk::kTrue);
CBaseDwg::AddEntity(poly, FALSE);
poly->setLayer(acdbCurDwg()->clayer());
poly->close();
}
else
{
AcDbCircle* pCircle = new AcDbCircle(pt, CBaseDwg::ZAxis(), radius);
CBaseDwg::AddEntity(pCircle, FALSE);
pCircle->setLayer(acdbCurDwg()->clayer());
pCircle->close();
}
}
对话框类的代码就没写了,主要是里面对数据的设置和保存问题。
这种插件所用到的一些小技巧已经被很多次用到了。一个是在选择过程中可以设置,这里涉及到cad的系统选择回调函数。第二个是文件的读写,有的人喜欢写ini,有的人喜欢写txt。
最近有一个项目也是处理数据,得到一些思考。ini和txt文件对于客户来说是开放的,可以很轻松的修改某些配置数据,有好处也有不好的地方。而订制化的二进制文件或sqlite数据库对客户来说是封闭的,看不到的。这里需要进行处理。或者还可以用注册表来处理数据。
目前而言,个人所用的数据,对于内部数据,包括计算参数,建模参数等等都应该是用数据库sqlite或者mysql。其他数据优先使用订制化的二进制数据,除非客户要求自己可以修改一些数据,那就使用ini文件。