520key 发表于 2023-9-10 15:11:11

自定义动态快属性设置问题

大佬们,请教一个问题,我new了一个AcDbBlockReference,是个动态块,添加到模型空间再修改new的动态块的翻转属性值,结果源块就变了


1是源块,2是NEW的块,有知道的大佬能指点一下吗?


代码如下


            //插入新的动态块
            AcDbBlockReference* pBlkRef = new AcDbBlockReference(point, idBlkDef);
            //写入模型空间中
            AcDbObjectId idClonedBlock = EntityUtil::AddToModelSpace(pBlkRef);            
            if (AcDbObjectId::kNull == idClonedBlock)
            {
            delete pBlkRef;
            return;
            }
            //设置属性
            Acad::ErrorStatus es = acdbOpenObject(pBlkRef, idClonedBlock, AcDb::kForWrite);
            if (Acad::eOk == es)
            {
            AcDbDynBlockReference dynBlock(pBlkRef);
            if (dynBlock.isDynamicBlock())
            {
                AcDbDynBlockReferencePropertyArray DynBlkRefPropArray;//动态块参照属性数组
                dynBlock.getBlockProperties(DynBlkRefPropArray);
                AcDbDynBlockReferenceProperty DynBlockReferenceProp;//动态块参照属性

                for (int i = 0; i < DynBlkRefPropArray.length(); i++)
                {
                  DynBlockReferenceProp = DynBlkRefPropArray.at(i);
                  bool bShow = DynBlockReferenceProp.show();      //是否在面板中显示
                  auto type = DynBlockReferenceProp.propertyType();//属性类型
                  CString strName = DynBlockReferenceProp.propertyName().kwszPtr();//属性名

                  if (strName.Find(_T("翻转")) >= 0)
                  {
                  Acad::ErrorStatus es = DynBlockReferenceProp.setValue(short(1));
                  if (Acad::eOk != es)
                  {
                      acutPrintf(_T("\n设置【%s】属性值失败,错误代码:%s"), strName, acadErrorStatusText(es));
                  }
                  break;
                  }
                }
            }
            pBlkRef->downgradeOpen();
            pBlkRef->close();
            }




520key 发表于 2023-9-10 17:04:49

本帖最后由 520key 于 2023-9-10 17:06 编辑

gzxl 发表于 2023-9-10 15:36
在for下面加上一行更新代码,试下什么结果。
for (int i = 0; i < DynBlkRefPropArray.length(); i++)
{
...
加上这句后,源块没有问题了,但是New的块有问题了,1是源块,2是NEW后的块,附上文件和代码



void CopyDynBlockRef()
{
//提示用户选择一个动态块
struct resbuf* rb = acutBuildList(RTDXF0, _T("INSERT"), RTNONE);
ads_name ss;
CString arPrompt = { _T("\n请选择一个块参照对象"),_T("\n删除了一个块参照对象") };
if (RTNORM == acedSSGet(_T(":S:$-M"), &arPrompt, NULL, rb, ss))
{
    //查看此块参照是否是动态块参照
    ads_name ent;
    acedSSName(ss, 0, ent);
    AcDbObjectId idBlk;
    acdbGetObjectId(idBlk, ent);

    //查看是否为动态块参照
    AcDbDynBlockReference cDynBlkRef(idBlk);
    if (cDynBlkRef.isDynamicBlock())
    {
      //打开块参照对象
      AcGeMatrix3d mat;
      AcGePoint3d ptInset;
      AcDbEntity* pEnt = NULL;
      if (Acad::eOk != acdbOpenObject(pEnt, idBlk, AcDb::kForRead))
      {
      acedSSFree(ss);
      acutRelRb(rb);
      return;
      }

      AcDbBlockReference* pRef = AcDbBlockReference::cast(pEnt);
      if (pRef)
      {
      mat = pRef->blockTransform();
      ptInset = pRef->position();
      }
      pEnt->close();

      //取出动态块定义的ID
      AcDbObjectId idBlkDef = AcDbObjectId::kNull;
      idBlkDef = cDynBlkRef.dynamicBlockTableRecord();
      if (idBlkDef)
      {
      //插入新的动态块
      AcDbBlockReference* pBlkRef = new AcDbBlockReference(AcGePoint3d(0, 0, 0), idBlkDef);
      pBlkRef->transformBy(mat);
      pBlkRef->setPosition(ptInset);

      AcDbDynBlockReference dynBlock(pBlkRef);
      if (dynBlock.isDynamicBlock())
      {
          AcDbDynBlockReferencePropertyArray DynBlkRefPropArray;//动态块参照属性数组
          dynBlock.getBlockProperties(DynBlkRefPropArray);
          AcDbDynBlockReferenceProperty DynBlockReferenceProp;//动态块参照属性

          for (int i = 0; i < DynBlkRefPropArray.length(); i++)
          {
            DynBlockReferenceProp = DynBlkRefPropArray.at(i);
            bool bShow = DynBlockReferenceProp.show();      //是否在面板中显示
            auto type = DynBlockReferenceProp.propertyType();//属性类型
            CString strName = DynBlockReferenceProp.propertyName().kwszPtr();//属性名

            if (strName.Find(_T("翻转")) >= 0)
            {
            Acad::ErrorStatus es = DynBlockReferenceProp.setValue(short(1));
            if (Acad::eOk != es)
            {
                acutPrintf(_T("\n设置【%s】属性值失败,错误代码:%s"), strName, acadErrorStatusText(es));
            }
            continue;
            }
          }
          pBlkRef->recordGraphicsModified();
      }

      if (AcDbObjectId::kNull == Database::PostToModelSpace(pBlkRef))
      {
          delete pBlkRef;
          //acedSSFree(ss);
          //acutRelRb(rb);
          //return;
      }
      }
    }
    acedSSFree(ss);
}
acutRelRb(rb);
}

gzxl 发表于 2023-9-12 14:40:38

我用以下代码,测试好像是可以的

ads_name ename;
ads_point pt;
if (acedEntSel(_T("\n选择一个动态块对象:"), ename, pt) != RTNORM)
    return;

Acad::ErrorStatus es = Acad::eOk;
AcDbObjectId eId;
es = acdbGetObjectId(eId, ename);
if (es != Acad::eOk) return;
AcDbEntity* pEnt = NULL;
es = acdbOpenObject(pEnt, eId, AcDb::kForRead);
if (es != Acad::eOk) return;
if (pEnt->isA() != AcDbBlockReference::desc())
{
    acutPrintf(_T("\n选择的对象不是块参照."));
    pEnt->close();
    return;
}
AcDbBlockReference *pBlkRef = AcDbBlockReference::cast(pEnt);
// 从块参照的对象id初始化动态块
AcDbDynBlockReference* pDynBlkRef = new AcDbDynBlockReference(pBlkRef->objectId());
// 关闭实体对象,不关闭将无法修改属性
pEnt->close();
if (pDynBlkRef)
{
    // 打开块参照对象
    AcGeMatrix3d mat;
    AcGePoint3d ptInset;
    mat = pBlkRef->blockTransform();
    ptInset = pBlkRef->position();
    AcDbDynBlockReferencePropertyArray DynBlkRefPropArray; // 动态块参照属性数组
    pDynBlkRef->getBlockProperties(DynBlkRefPropArray);
    AcDbDynBlockReferenceProperty DynBlockReferenceProp;   // 动态块参照属性
    for (int i = 0; i < DynBlkRefPropArray.length(); ++i)
    {
      DynBlockReferenceProp = DynBlkRefPropArray.at(i);
      CString strName = DynBlockReferenceProp.propertyName().kwszPtr();// 属性名
      if (strName.Find(_T("翻转")) == -1)
            continue;
      es = DynBlockReferenceProp.setValue(short(1));
      if (Acad::eOk != es)
      {
            acutPrintf(_T("\n设置【%s】属性值失败,错误代码:%s"), strName, acadErrorStatusText(es));
      }
    }
    AcDbObjectId idBlkDef = pDynBlkRef->dynamicBlockTableRecord();
    delete pDynBlkRef; // 记得删除
    // 插入新的动态块
    AcDbBlockReference* pNewBlkRef = new AcDbBlockReference(ptInset, idBlkDef);
    Database::PostToModelSpace(pNewBlkRef);
}

520key 发表于 2023-9-12 15:14:55

gzxl 发表于 2023-9-12 14:40
我用以下代码,测试好像是可以的



我用大佬的代码测试,是下面这个结果,1为源块,2为执行代码后的源块,3是NEW之后的块,属性刚好反了,想要达到的效果是执行代码后1 2应该是相同的基点都在左下角,New出后的块3的属性应该是2的那样基点在左上角, 我的环境是VS2022 CAD2022


gzxl 发表于 2023-9-10 15:36:52

在for下面加上一行更新代码,试下什么结果。
for (int i = 0; i < DynBlkRefPropArray.length(); i++)
{
    //...
}
pBlkRef->recordGraphicsModified();

如果不行的话,可能要上传个dwg。

gzxl 发表于 2023-9-10 19:07:06

520key 发表于 2023-9-10 17:04
加上这句后,源块没有问题了,但是New的块有问题了,1是源块,2是NEW后的块,附上文件和代码

那就再加一句代码
dynBlock.resetBlock();
pBlkRef->recordGraphicsModified();

520key 发表于 2023-9-10 23:42:49

gzxl 发表于 2023-9-10 19:07
那就再加一句代码
dynBlock.resetBlock();
pBlkRef->recordGraphicsModified();

加上dynBlock.resetBlock();后就重置了,设置的值也没有了,加在for前面问题也是一样的

gzxl 发表于 2023-9-12 11:34:28

本帖最后由 gzxl 于 2023-9-12 11:52 编辑

建议您再过一遍代码。

why1025 发表于 2023-9-12 12:32:03

这个代码好高端

520key 发表于 2023-9-12 13:55:28

gzxl 发表于 2023-9-12 11:34
建议您再过一遍代码。

大佬是我的代码写的有问题吗?

520key 发表于 2023-9-12 14:56:33

gzxl 发表于 2023-9-12 14:40
我用以下代码,测试好像是可以的

大佬这里为什么要New两次呢,第一次是objectid   每二次才是动态块的块表记录
页: [1] 2
查看完整版本: 自定义动态快属性设置问题