明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 2712|回复: 14

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

[复制链接]
发表于 2023-9-10 15:11:11 | 显示全部楼层 |阅读模式
大佬们,请教一个问题,我new了一个AcDbBlockReference,是个动态块,添加到模型空间再修改new的动态块的翻转属性值,结果源块就变了


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


代码如下


  1.             //插入新的动态块
  2.             AcDbBlockReference* pBlkRef = new AcDbBlockReference(point, idBlkDef);
  3.             //写入模型空间中
  4.             AcDbObjectId idClonedBlock = EntityUtil::AddToModelSpace(pBlkRef);            
  5.             if (AcDbObjectId::kNull == idClonedBlock)
  6.             {
  7.               delete pBlkRef;
  8.               return;
  9.             }
  10.             //设置属性
  11.             Acad::ErrorStatus es = acdbOpenObject(pBlkRef, idClonedBlock, AcDb::kForWrite);
  12.             if (Acad::eOk == es)
  13.             {
  14.               AcDbDynBlockReference dynBlock(pBlkRef);
  15.               if (dynBlock.isDynamicBlock())
  16.               {
  17.                 AcDbDynBlockReferencePropertyArray DynBlkRefPropArray;//动态块参照属性数组
  18.                 dynBlock.getBlockProperties(DynBlkRefPropArray);
  19.                 AcDbDynBlockReferenceProperty DynBlockReferenceProp;  //动态块参照属性

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

  26.                   if (strName.Find(_T("翻转")) >= 0)
  27.                   {
  28.                     Acad::ErrorStatus es = DynBlockReferenceProp.setValue(short(1));
  29.                     if (Acad::eOk != es)
  30.                     {
  31.                       acutPrintf(_T("\n设置【%s】属性值失败,错误代码:%s"), strName, acadErrorStatusText(es));
  32.                     }
  33.                     break;
  34.                   }
  35.                 }
  36.               }
  37.               pBlkRef->downgradeOpen();
  38.               pBlkRef->close();
  39.             }
复制代码





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
 楼主| 发表于 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后的块,附上文件和代码



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

  14.     //查看是否为动态块参照
  15.     AcDbDynBlockReference cDynBlkRef(idBlk);
  16.     if (cDynBlkRef.isDynamicBlock())
  17.     {
  18.       //打开块参照对象
  19.       AcGeMatrix3d mat;
  20.       AcGePoint3d ptInset;
  21.       AcDbEntity* pEnt = NULL;
  22.       if (Acad::eOk != acdbOpenObject(pEnt, idBlk, AcDb::kForRead))
  23.       {
  24.         acedSSFree(ss);
  25.         acutRelRb(rb);
  26.         return;
  27.       }

  28.       AcDbBlockReference* pRef = AcDbBlockReference::cast(pEnt);
  29.       if (pRef)
  30.       {
  31.         mat = pRef->blockTransform();
  32.         ptInset = pRef->position();
  33.       }
  34.       pEnt->close();

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

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

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

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

  68.         if (AcDbObjectId::kNull == Database::PostToModelSpace(pBlkRef))
  69.         {
  70.           delete pBlkRef;
  71.           //acedSSFree(ss);
  72.           //acutRelRb(rb);
  73.           //return;
  74.         }
  75.       }
  76.     }
  77.     acedSSFree(ss);
  78.   }
  79.   acutRelRb(rb);
  80. }
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2023-9-12 14:40:38 | 显示全部楼层
我用以下代码,测试好像是可以的

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

  5. Acad::ErrorStatus es = Acad::eOk;
  6. AcDbObjectId eId;
  7. es = acdbGetObjectId(eId, ename);
  8. if (es != Acad::eOk) return;
  9. AcDbEntity* pEnt = NULL;
  10. es = acdbOpenObject(pEnt, eId, AcDb::kForRead);
  11. if (es != Acad::eOk) return;
  12. if (pEnt->isA() != AcDbBlockReference::desc())
  13. {
  14.     acutPrintf(_T("\n选择的对象不是块参照."));
  15.     pEnt->close();
  16.     return;
  17. }
  18. AcDbBlockReference *pBlkRef = AcDbBlockReference::cast(pEnt);
  19. // 从块参照的对象id初始化动态块
  20. AcDbDynBlockReference* pDynBlkRef = new AcDbDynBlockReference(pBlkRef->objectId());
  21. // 关闭实体对象,不关闭将无法修改属性
  22. pEnt->close();
  23. if (pDynBlkRef)
  24. {
  25.     // 打开块参照对象
  26.     AcGeMatrix3d mat;
  27.     AcGePoint3d ptInset;
  28.     mat = pBlkRef->blockTransform();
  29.     ptInset = pBlkRef->position();
  30.     AcDbDynBlockReferencePropertyArray DynBlkRefPropArray; // 动态块参照属性数组
  31.     pDynBlkRef->getBlockProperties(DynBlkRefPropArray);
  32.     AcDbDynBlockReferenceProperty DynBlockReferenceProp;   // 动态块参照属性
  33.     for (int i = 0; i < DynBlkRefPropArray.length(); ++i)
  34.     {
  35.         DynBlockReferenceProp = DynBlkRefPropArray.at(i);
  36.         CString strName = DynBlockReferenceProp.propertyName().kwszPtr();  // 属性名
  37.         if (strName.Find(_T("翻转")) == -1)
  38.             continue;
  39.         es = DynBlockReferenceProp.setValue(short(1));
  40.         if (Acad::eOk != es)
  41.         {
  42.             acutPrintf(_T("\n设置【%s】属性值失败,错误代码:%s"), strName, acadErrorStatusText(es));
  43.         }
  44.     }
  45.     AcDbObjectId idBlkDef = pDynBlkRef->dynamicBlockTableRecord();
  46.     delete pDynBlkRef; // 记得删除
  47.     // 插入新的动态块
  48.     AcDbBlockReference* pNewBlkRef = new AcDbBlockReference(ptInset, idBlkDef);
  49.     Database::PostToModelSpace(pNewBlkRef);
  50. }
复制代码


 楼主| 发表于 2023-9-12 15:14:55 | 显示全部楼层
gzxl 发表于 2023-9-12 14:40
我用以下代码,测试好像是可以的



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


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2023-9-10 15:36:52 | 显示全部楼层
在for下面加上一行更新代码,试下什么结果。
for (int i = 0; i < DynBlkRefPropArray.length(); i++)
{
    //...
}
pBlkRef->recordGraphicsModified();

如果不行的话,可能要上传个dwg。
发表于 2023-9-10 19:07:06 | 显示全部楼层
520key 发表于 2023-9-10 17:04
加上这句后,源块没有问题了,但是New的块有问题了,1是源块,2是NEW后的块,附上文件和代码

那就再加一句代码
dynBlock.resetBlock();
pBlkRef->recordGraphicsModified();
 楼主| 发表于 2023-9-10 23:42:49 | 显示全部楼层
gzxl 发表于 2023-9-10 19:07
那就再加一句代码
dynBlock.resetBlock();
pBlkRef->recordGraphicsModified();

加上dynBlock.resetBlock();后就重置了,设置的值也没有了,加在for前面问题也是一样的
发表于 2023-9-12 11:34:28 | 显示全部楼层
本帖最后由 gzxl 于 2023-9-12 11:52 编辑

建议您再过一遍代码。
发表于 2023-9-12 12:32:03 | 显示全部楼层
这个代码好高端
 楼主| 发表于 2023-9-12 13:55:28 | 显示全部楼层
gzxl 发表于 2023-9-12 11:34
建议您再过一遍代码。

大佬是我的代码写的有问题吗?
 楼主| 发表于 2023-9-12 14:56:33 | 显示全部楼层
gzxl 发表于 2023-9-12 14:40
我用以下代码,测试好像是可以的

大佬这里为什么要New两次呢,第一次是objectid   每二次才是动态块的块表记录
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-4-2 18:42 , Processed in 0.206833 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表