(23)ObjectARX2015 + vs2012操作图层

1. 说明

       本篇演示了创建新的层表记录、删除已有的层表记录、使用“颜色”对话框设置某一图层的颜色,以及导出和导入所有图层及特性的方法,基本涵盖了所有的层表操作。
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();
    }

效果展示:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值