|
本篇演示了创建新的层表记录、删除已有的层表记录、使用“颜色”对话框设置某一图层的颜色,以及导出和导入所有图层及特性的方法,基本涵盖了所有的层表操作。
2. 思路
创建新的图层,实际上就是创建一个新的层表记录,并将其添加到层表中。
修改图层的颜色,可以从层表中获得指定的记录,然后使用 AcDbLayerTableRecord 类的setColor 函数设置层表记录的颜色。
删除一个图层,需要首先从层表中获得指定的层表记录,然后将层表记录设置一个“删除”的标记。
导出图层列表和图层特性,需要使用层表遍历器访问每一个层表记录,将层表记录的名称、颜色、线型和线宽以“,”作分隔符连接成一个 CString 类型的字符串对象,然后使用 CStdioFile 类的 WriteString 函数写入到文本文件中。
导入图层列表的步骤和导出的步骤完全相反,先使用 CstdioFile 类的 ReadString 函数逐行读取文本文件的内容,以“,”作分隔符解析出图层名称、颜色、线型和线宽,并在当前图形中加入这些图层。
3. 步骤
(1) 新建一个 CLayerOper 类, 添加 NewLayer 函数
由于要在块表中添加新的块表记录,在获得块表的时候需要将其以“写”模式打开,对
应于代码中就是在 getLayerTable 函数中使用了 AcDb::kForWrite 参数。向块表添加新的记录
之前,可以使用 has 函数判断图形中是否已经包含了同名的层。
//新建图层
static void NewLayer(); //新建图层
//新建图层
void CLayerOper::NewLayer()
{
// 提示用户输入新建图层的名称
TCHAR layerName[100];
if (acedGetString(Adesk::kFalse, _T("\n输入新图层的名称:"), layerName) != RTNORM)
{
return;
}
// 获得当前图形的层表
AcDbLayerTable *pLayerTbl;
acdbHostApplicationServices()->workingDatabase()->getLayerTable(pLayerTbl, AcDb::kForWrite);
// 是否已经包含指定的层表记录
if (pLayerTbl->has(layerName))
{
pLayerTbl->close();
return;
}
// 创建新的层表记录
AcDbLayerTableRecord *pLayerTblRcd;
pLayerTblRcd = new AcDbLayerTableRecord();
pLayerTblRcd->setName(layerName);
// 将新建的层表记录添加到层表中
AcDbObjectId layerTblRcdId;
pLayerTbl->add(layerTblRcdId, pLayerTblRcd);
//AcDbDatabase 类的 setClayer 函数能够设置图形的当前图层。
acdbHostApplicationServices()->workingDatabase()->setClayer(layerTblRcdId);
pLayerTblRcd->close();
pLayerTbl->close();
}
(2) 修改指定图层的颜色: 添加新类 CModifyLayer, 添加 ModifyLayerColor 函数
在获得特定的块表记录指针时,使用了 AcDbLayerTable 类的 getAt 函数,并且使用 AcDb::kForWrite 参数,将块表记录以“写”模式打开。
AcedSetColorDialog 函数能够弹出 [选择颜色 对话框] ,并且返回用户选择的结果,
AcCmColor 代表颜色对象,可以通过颜色索引来构建一个新的颜色对象。
该函数定义为:
Adesk::Boolean acedSetColorDialog(
int& nColor, //nColor 参数指定了显示【选择颜色】对话框时的默认颜色,并且在函数返回值后保存用户选择的新颜色
Adesk::Boolean bAllowMetaColor, //bAllowMetaColor 参数限定在【选择颜色】对话框中是否可以选择“随层”或“随块”
int nCurLayerColor); //nCurLayerColor 参数指定当前图层的颜色。
AcCmColor //代表颜色对象,可以通过颜色索引来构建一个新的颜色对象。
//通过颜色索引,可以将【选择颜色】对话框的结果设置为指定图层的颜色,
其相关代码为:
AcCmColor color;
color.setColorIndex(nNewColor);
pLayerTblRcd->setColor(color);
void ModifyLayerColor(); //修改图层颜色
//修改图层颜色
void CModifyLayer::ModifyLayerColor()
{
// 提示用户输入要修改的图层名称
TCHAR layerName[100];
if (acedGetString(Adesk::kFalse, _T("\n输入图层的名称:"), layerName) != RTNORM)
{
return;
}
// 获得当前图形的层表
AcDbLayerTable *pLayerTbl;
acdbHostApplicationServices()->workingDatabase()->getLayerTable(pLayerTbl, AcDb::kForRead);
// 判断是否包含指定名称的层表记录
if (!pLayerTbl->has(layerName))
{
pLayerTbl->close();
return;
}
// 获得指定层表记录的指针
AcDbLayerTableRecord *pLayerTblRcd;
pLayerTbl->getAt(layerName, pLayerTblRcd, AcDb::kForWrite);
// 弹出“颜色”对话框
AcCmColor oldColor = pLayerTblRcd->color();
int nCurColor = oldColor.colorIndex(); // 图层修改前的颜色
int nNewColor = oldColor.colorIndex(); // 用户选择的颜色
if (acedSetColorDialog(nNewColor, Adesk::kFalse, nCurColor))
{
AcCmColor color;
color.setColorIndex(nNewColor);
pLayerTblRcd->setColor(color);
}
// 关闭
pLayerTblRcd->close();
pLayerTbl->close();
}
(3) 删除一个数据库对象非常简单:将其以“写”模式打开,调用 AcDbObject 类的 erase 函数,最后关闭该对象
void DelLayer(); //删除图层
//删除图层
void CModifyLayer::DelLayer()
{
// 提示用户输入要修改的图层名称
TCHAR layerName[100];
if (acedGetString(Adesk::kFalse, _T("\n输入图层的名称:"), layerName) != RTNORM)
{
return;
}
// 获得当前图形的层表
AcDbLayerTable *pLayerTbl;
acdbHostApplicationServices()->workingDatabase()->getLayerTable(pLayerTbl, AcDb::kForRead);
// 判断是否包含指定名称的层表记录
if (!pLayerTbl->has(layerName))
{
pLayerTbl->close();
return;
}
// 获得指定层表记录的指针
AcDbLayerTableRecord *pLayerTblRcd;
pLayerTbl->getAt(layerName, pLayerTblRcd, AcDb::kForWrite);
pLayerTblRcd->erase(); // 为其设置“删除”标记
pLayerTblRcd->close();
pLayerTbl->close();
}
(4) 将当前图形中存在的所有图层及其特性导出到一个文本文件中, 添加函数 ExportLayer()
CStdioFile 类的 Open 函数能够打开指定位置的文件,这里使用 CFile::modeCreate 作为打开标记,能够在指定的位置创建文件。
最终的结果是将图层的信息以“图层名称,颜色,线型,线宽”格式输出,因此在获得图层的名称和特性之后,关键在于将这些特性组合成一个 CString 类型的变量。所幸, CString 类提供了“+”运算符,能够将两个字符串连接起来组成一个新的字符串,例如:
strLayerInfo += strLineWeight;
像文件中写入字符串使用了 CStdioFile 类的 WriteString 函数,注意需要单独写入一个换行字符,保证每个图层的特性单独成行。
void ExportLayer(); //导出图层到文本文档
//导出图层到文本文档
void CModifyLayer::ExportLayer()
{
// 创建所要导出的文本文件
CStdioFile f;
CFileException e;
TCHAR *pFileName = _T("C:\\layers.txt");
if (!f.Open(pFileName, CFile::modeCreate | CFile::modeWrite, &e))
{
acutPrintf(_T("\n创建导出文件失败!"));
return;
}
// 获得层表指针
AcDbLayerTable *pLayerTbl;
AcDbLayerTableRecord *pLayerTblRcd;
acdbHostApplicationServices()->workingDatabase()->getLayerTable(pLayerTbl, AcDb::kForRead);
// 使用遍历器访问每一条层表记录
AcDbLayerTableIterator *pItr;
pLayerTbl->newIterator(pItr);
for (pItr->start(); !pItr->done(); pItr->step())
{
pItr->getRecord(pLayerTblRcd, AcDb::kForRead);
// 输出图层的信息
CString strLayerInfo; // 图层名称
TCHAR *layerName;
pLayerTblRcd->getName(layerName);
strLayerInfo = layerName;
free(layerName);
strLayerInfo += ","; // 分隔符
CString strColor; // 图层颜色
AcCmColor color = pLayerTblRcd->color();
strColor.Format(_T("%d"), color.colorIndex());
strLayerInfo += strColor;
strLayerInfo += ",";
CString strLinetype; // 图层线型
AcDbLinetypeTableRecord *pLinetypeTblRcd;
acdbOpenObject(pLinetypeTblRcd, pLayerTblRcd->linetypeObjectId(), AcDb::kForRead);
TCHAR *linetypeName;
pLinetypeTblRcd->getName(linetypeName);
pLinetypeTblRcd->close();
strLinetype = linetypeName;
free(linetypeName);
strLayerInfo += strLinetype;
strLayerInfo += ",";
CString strLineWeight; // 图层的线宽
AcDb::LineWeight lineWeight = pLayerTblRcd->lineWeight();
strLineWeight.Format(_T("%d"), lineWeight);
strLayerInfo += strLineWeight;
// 将图层特性写入到文件中
f.WriteString(strLayerInfo);
f.WriteString(_T("\n"));
pLayerTblRcd->close();
}
delete pItr;
pLayerTbl->close();
}
(5) 按照文本文件中的图层列表在当前图形中创建图层,并且符合图层列表中的各项特性:
使用 CFile::modeRead 参数调用 CstdioFile 类的 Open 函数,打开指定位置的文本文件,然后使用 ReadString 函数逐行读取文本文件中的内容。
读取一行文本之后,需要根据分隔符(“,”)来解析出图层的名称、颜色、线型和线宽,使用 GetFieldText 函数来实现.
Cstring 类提供了一系列用于查找字符或者切割字符串的函数,使得解析字符串变量非常简单。例如:
Find 函数能在指定的字符串中查找匹配子串的第一个位置,
Mid 函数则能解析出指定字符串中指定长度的子串。
该函数的实现代码为:
//解析文本(图层的名称、颜色、线型和线宽)
BOOL GetFieldText(CString strLineText, CStringArray &fields); //解析文本(图层的名称、颜色、线型和线宽)
//解析文本(图层的名称、颜色、线型和线宽)
BOOL CModifyLayer::GetFieldText(CString strLineText, CStringArray &fields)
{
if (strLineText.Find(_T(","), 0) == -1) // 如果找不到英文逗号,函数退出
{
return FALSE;
}
int nLeftPos = 0, nRightPos = 0; // 查找分隔符的起始位置
while ((nRightPos = strLineText.Find(_T(","), nRightPos)) != -1)
{
fields.Add(strLineText.Mid(nLeftPos, nRightPos - nLeftPos));
nLeftPos = nRightPos + 1;
nRightPos++;
}
// 最后一个列的数据
fields.Add(strLineText.Mid(nLeftPos));
return TRUE;
}
获得某一图层的名称、颜色、线型和线宽之后,就可以创建新的层表记录,并且使用
setColor 函数设置图层的颜色,
setLinetypeObjectId 函数设置图层的线型,
setLineWeight 函数设置图层的线宽。
//从文本文档到导入图层
void ImportLayer(); //从文本文档到导入图层
//从文本文档到导入图层
void CModifyLayer::ImportLayer()
{
// 打开所要导入的文本文件
CStdioFile f;
CFileException e;
TCHAR *pFileName = _T("C:\\layers.txt");
if (!f.Open(pFileName, CFile::modeRead, &e))
{
acutPrintf(_T("\n打开导入文件失败!"));
return;
}
// 获得层表指针
AcDbLayerTable *pLayerTbl;
AcDbLayerTableRecord *pLayerTblRcd;
acdbHostApplicationServices()->workingDatabase()->getLayerTable(pLayerTbl, AcDb::kForWrite);
// 读取文件中的每一行数据
CString strLineText; // 一行文字
while (f.ReadString(strLineText))
{
// 跳过空行
if (strLineText.IsEmpty())
continue;
// 解析出图层名称、颜色、线型和线宽
CStringArray layerInfos;
if (!GetFieldText(strLineText, layerInfos))
continue;
// 创建新的层表记录,或者打开存在的块表记录
AcDbLayerTableRecord *pLayerTblRcd;
AcDbObjectId layerTblRcdId;
if (pLayerTbl->has(layerInfos.GetAt(0)))
{
pLayerTbl->getAt(layerInfos.GetAt(0), layerTblRcdId);
}else
{
pLayerTblRcd = new AcDbLayerTableRecord();
pLayerTblRcd->setName(layerInfos.GetAt(0));
pLayerTbl->add(layerTblRcdId, pLayerTblRcd);
pLayerTblRcd->close();
}
acdbOpenObject(pLayerTblRcd, layerTblRcdId, AcDb::kForWrite);
// 设置层表记录的颜色
AcCmColor color;
Adesk::UInt16 colorIndex = _wtol(layerInfos.GetAt(1));
color.setColorIndex(colorIndex);
pLayerTblRcd->setColor(color);
// 设置线型
AcDbLinetypeTable *pLinetypeTbl;
AcDbObjectId linetypeId;
acdbHostApplicationServices()->workingDatabase()->getLinetypeTable(pLinetypeTbl, AcDb::kForRead);
if (pLinetypeTbl->has(layerInfos.GetAt(2)))
{
pLinetypeTbl->getAt(layerInfos.GetAt(2), linetypeId);
}else
{
pLinetypeTbl->getAt(_T("Continous"), linetypeId);
}
pLayerTblRcd->setLinetypeObjectId(linetypeId);
pLinetypeTbl->close();
// 设置线宽
AcDb::LineWeight lineWeight = (AcDb::LineWeight)_wtol(layerInfos.GetAt(3));
pLayerTblRcd->setLineWeight(lineWeight);
pLayerTblRcd->close();
}
pLayerTbl->close();
}
(6) 在acrxEntryPoint.cpp中
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyNewLayer, MyNewLayer, ACRX_CMD_MODAL, NULL) //新建图层
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyDelLayer, MyDelLayer, ACRX_CMD_MODAL, NULL) //删除图层
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyModifyLayerColor, MyModifyLayerColor, ACRX_CMD_MODAL, NULL) //插入图层
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyExportLayer, MyExportLayer, ACRX_CMD_MODAL, NULL) //导出图层
ACED_ARXCOMMAND_ENTRY_AUTO(CArxConfigApp, MidasMyGroup, MyImportLayer, MyImportLayer, ACRX_CMD_MODAL, NULL) //导入图层
//当前项目中注册命令 新建/删除/插入/导出/导入
static void MidasMyGroupMyNewLayer()
{
CLayerOper m_layerOper;
m_layerOper.NewLayer();
}
static void MidasMyGroupMyDelLayer()
{
CModifyLayer m_modifyLayer;
m_modifyLayer.DelLayer();
}
static void MidasMyGroupMyModifyLayerColor()
{
CModifyLayer m_modifyLayer;
m_modifyLayer.ModifyLayerColor();
}
static void MidasMyGroupMyExportLayer()
{
CModifyLayer m_modifyLayer;
m_modifyLayer.ExportLayer();
}
static void MidasMyGroupMyImportLayer()
{
CModifyLayer m_modifyLayer;
m_modifyLayer.ImportLayer();
}
|
|