ObjectARX 2025(C++)插入带属性的块参照 AcDbAttribute

最近更新于 2025-04-29 08:55

环境

AutoCAD 机械版 2025
ObjectARX 2025
VS 2022(ISO C++14)

环境配置参考:https://blog.iyatt.com/?p=16480
块属性使用参考:https://blog.iyatt.com/?p=19800
自定义类使用参考:https://blog.iyatt.com/?p=16635

实现

InsertBlockWithAttribute.hpp

#pragma once
class InsertBlockWithAttribute
{
public:
    static void init();
    static void unload();
private:
    /**
     * @brief 工作命令
     */
    static void work();

    /**
     * @brief 获取块定义ID
     * @param blockName 块名称
     * @return 块定义 ID
     */
    static AcDbObjectId getBlockDefineId(AcString blockName);

    /**
     * @brief 插入带属性的块
     * @param blockDefineId 块定义ID
     * @param insertPtObj 插入点
     * @return 块参照 ID
     */
    static AcDbObjectId insertBlock(const AcDbObjectId& blockDefineId, const AcGePoint3d& insertPtObj);

    /**
     * @brief 将实体插入到模型空间中
     * @param pEnt 实体
     * @param pDb 当前工作数据库
     * @return 插入实体的 ID
     */
    static AcDbObjectId postToModalSpace(AcDbEntity* pEnt);

    /**
     * @brief 将属性定义添加到块参照中
     * @param pBlockReference 块参照
     * @param pAttributeDefinition 属性定义
     */
    static void appendAttributeToBlockReference(AcDbBlockReference* pBlockReference, AcDbAttributeDefinition* pAttributeDefinition);

    /**
     * @brief 设置块参照的属性值
     * @param pBlockReference 块参照
     * @param tag 属性标记
     * @param textVal 属性值
     */
    static void setBlockReferenceAttribute(AcDbBlockReference* pBlockReference, AcString& tag, AcString& textVal);
};

insertBlockWithAttributeProject.cpp

#include "stdafx.h"
#include "InsertBlockWithAttribute.hpp"

void InsertBlockWithAttribute::init()
{
    acedRegCmds->addCommand(L"IYATTyxTestInsertBlockWithAttribute", L"TestInsertBlockWithAttribute", L"TestInsertBlockWithAttribute", ACRX_CMD_MODAL, InsertBlockWithAttribute::work);
}

void InsertBlockWithAttribute::unload()
{
    acedRegCmds->removeGroup(L"IYATTyxTestInsertBlockWithAttribute");
}

void InsertBlockWithAttribute::work()
{
    AcString blockName = L"序号块";
    //if (acedGetString(Adesk::kFalse, L"输入要插入的块名称:", blockName) != RTNORM)
    //{
    //  return;
    //}

    AcDbObjectId blockDefineId = InsertBlockWithAttribute::getBlockDefineId(blockName);
    if (blockDefineId.isNull())
    {
        acutPrintf(L"块定义不存在!\n");
        return;
    }

    ads_point insertPt;
    if (acedGetPoint(nullptr, L"输入插入点:", insertPt) != RTNORM)
    {
        return;
    }
    AcGePoint3d insertPtObj = asPnt3d(insertPt);

    // 插入块参照
    AcDbObjectId blockReferenceId = InsertBlockWithAttribute::insertBlock(blockDefineId, insertPtObj);

    // 设置参数值
    static int num = 1;
    AcDbBlockReference* pBlockReference = nullptr;
    if (acdbOpenObject(pBlockReference, blockReferenceId, AcDb::kForWrite) == Acad::eOk)
    {
        AcString tag = L"序号";
        AcString textVal;
        textVal.format(L"%d", num);
        InsertBlockWithAttribute::setBlockReferenceAttribute(pBlockReference, tag, textVal);
        pBlockReference->close();
        ++num;
    }
}

AcDbObjectId InsertBlockWithAttribute::getBlockDefineId(AcString blockName)
{
    AcDbBlockTable* pBlockTable = nullptr;
    if (acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForRead) != Acad::eOk)
    {
        return AcDbObjectId::kNull;
    }

    AcDbObjectId blockDefineId;
    Acad::ErrorStatus es = pBlockTable->getAt(blockName.kACharPtr(), blockDefineId);
    pBlockTable->close();
    if (es == Acad::eOk)
    {
        return blockDefineId;
    }
    else
    {
        return AcDbObjectId::kNull;
    }
}

AcDbObjectId InsertBlockWithAttribute::insertBlock(const AcDbObjectId& blockDefineId, const AcGePoint3d& insertPtObj)
{
    // 块参照实例
    AcDbBlockReference* pBlockReference = new AcDbBlockReference(insertPtObj, blockDefineId);

    // 比例
    double scale = 1;
    AcGeScale3d scaleObj(scale, scale, scale);
    pBlockReference->setScaleFactors(scaleObj);

    // 旋转角度
    double rotation = 0;
    pBlockReference->setRotation(rotation);

    AcDbBlockTableRecord* pBlockTableRecord = nullptr;
    if (acdbOpenObject(pBlockTableRecord, pBlockReference->blockTableRecord(), AcDb::kForRead) == Acad::eOk)
    {
        // 判断块参照的块表记录中是否有属性定义
        if (pBlockTableRecord->hasAttributeDefinitions())
        {
            AcDbBlockTableRecordIterator* pBlockTableRecordIterator = nullptr;
            pBlockTableRecord->newIterator(pBlockTableRecordIterator);
            for (pBlockTableRecordIterator->start(); !pBlockTableRecordIterator->done(); pBlockTableRecordIterator->step())
            {
                AcDbEntity* pEnt = nullptr;
                if (pBlockTableRecordIterator->getEntity(pEnt, AcDb::kForRead) == Acad::eOk)
                {
                    AcDbAttributeDefinition* pAttributeDefinition = AcDbAttributeDefinition::cast(pEnt);
                    if (pAttributeDefinition)
                    {
                        InsertBlockWithAttribute::appendAttributeToBlockReference(pBlockReference, pAttributeDefinition);
                    }
                    pEnt->close();
                }
            }
            delete pBlockTableRecordIterator;
        }
    }
    pBlockTableRecord->close();
    return InsertBlockWithAttribute::postToModalSpace(pBlockReference);
}

AcDbObjectId InsertBlockWithAttribute::postToModalSpace(AcDbEntity* pEnt)
{
    assert(pEnt);

    AcDbBlockTable* pBlockTable = nullptr;
    acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTable, AcDb::kForWrite);

    AcDbBlockTableRecord* pBlockTableRecord = nullptr;
    pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord, AcDb::kForWrite);
    pBlockTable->close();

    AcDbObjectId entId;
    if (pBlockTableRecord->appendAcDbEntity(entId, pEnt) != Acad::eOk)
    {
        pBlockTableRecord->close();
        delete pEnt;
        pEnt = nullptr;
        return AcDbObjectId::kNull;
    }

    pBlockTableRecord->close();
    pEnt->close();
    return entId;
}

void InsertBlockWithAttribute::appendAttributeToBlockReference(AcDbBlockReference* pBlockReference, AcDbAttributeDefinition* pAttributeDefinition)
{
    // 创建一个属性对象
    AcDbAttribute* pAttribute = new AcDbAttribute();
    // 从块参照获取属性对象的特性
    pAttribute->setPropertiesFrom(pBlockReference);
    pAttribute->setLayer(pBlockReference->layerId());
    // 设置属性对象的其它特性
    pAttribute->setInvisible(pAttribute->isInvisible());
    pAttribute->setPosition(pAttributeDefinition->position());
    pAttribute->setHeight(pAttributeDefinition->height());
    pAttribute->setWidthFactor(pAttributeDefinition->widthFactor());
    pAttribute->setRotation(pAttributeDefinition->rotation());
    pAttribute->setHorizontalMode(pAttributeDefinition->horizontalMode());
    pAttribute->setVerticalMode(pAttributeDefinition->verticalMode());
    pAttribute->setAlignmentPoint(pAttributeDefinition->alignmentPoint());
    pAttribute->setTextStyle(pAttributeDefinition->textStyle());
    pAttribute->setAttributeFromBlock(pBlockReference->blockTransform());

    // 获取属性对象的标记、值
    pAttribute->setTag(pAttributeDefinition->tag());
    pAttribute->setFieldLength(pAttributeDefinition->fieldLength());
    pAttribute->setTextString(pAttributeDefinition->textString());

    pBlockReference->appendAttribute(pAttribute);
    pAttribute->close();
}

void InsertBlockWithAttribute::setBlockReferenceAttribute(AcDbBlockReference* pBlockReference, AcString& tag, AcString& textVal)
{
    AcDbObjectIterator* pAttributeIterator = pBlockReference->attributeIterator();
    for (pAttributeIterator->start(); !pAttributeIterator->done(); pAttributeIterator->step())
    {
        AcDbAttribute* pAttribute = nullptr;
        if (acdbOpenObject(pAttribute, pAttributeIterator->objectId(), AcDb::kForWrite) != Acad::eOk)
        {
            continue;
        }
        if (tag == pAttribute->tag())
        {
            pAttribute->setTextString(textVal.kACharPtr());
        }
        pAttribute->close();
    }
    delete pAttributeIterator;
}

创建一个块,名称为:序号块
附带一个属性定义,标记:序号
file

调试运行,执行命令 TestInsertBlockWithAttribute
file

ObjectARX 2025(C++)插入带属性的块参照 AcDbAttribute
Scroll to top

目录

打开目录