zdqwy19 发表于 2015-10-28 18:44:20

objectarx修改块内实体无效

   做了一个测试程序,试图将选中的块内直线的颜色改为红色,程序运行既不提示错误,运行过后也没有效果。不知道为什么?static void MyGroup_test_kuai ()
{
    //将选到的块内直线变成红色
    resbuf* rb = acutBuildList(RTDXF0, ACRX_T("INSERT"),RTNONE);
    int ret = RTNORM;
    ads_name result;
    ret = acedSSGet(NULL, NULL, NULL, rb, result );
    if ( ret!= RTNORM )
    {
      acedPrompt( _T("\n创建选择集失败!") );
      return;
    }
    acutRelRb(rb);
    // 对选择集进行处理
    long len;//选集元素数量
    long i=0;
    acedSSLength(result,&len);
    for(i=0; i<len; i++)
    {
      // 获得指定元素的ObjectId;
      ads_name ent;
      acedSSName(result, i, ent);
      AcDbObjectId objId;
      acdbGetObjectId(objId, ent);
      // 获得指向当前元素的指针;
      AcDbEntity *pEnt;
      //读模式打开对象
      acdbOpenAcDbEntity(pEnt, objId, AcDb::kForRead);
      if(pEnt->isKindOf(AcDbBlockReference::desc()))//块;
      {
      //插入的块数据;
      AcDbBlockReference *pBlockReference = AcDbBlockReference::cast(pEnt);
      ads_name enti;
      AcDbObjectId objId;
      objId=pBlockReference->objectId();
      struct resbuf *rbEnt; // 保存实体数据的结果缓冲区;
      struct resbuf *rbrb; // 用于遍历rbEnt的结果缓冲区;
      acdbGetAdsName(enti,objId);
      rbEnt = acdbEntGet(enti);
      rbrb = rbEnt;
      CString bk;
      while(rbrb->restype!=2) rbrb=rbrb->rbnext;
      bk=rbrb->resval.rstring;//插入的块名称;
      acutRelRb(rbrb);
      //构建块表记录遍历器
      AcDbBlockTable *pBlkTbl;
      acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl, AcDb::kForRead);
      AcDbBlockTableRecord *pBlkTblRcd; // Blk块表记录;
      pBlkTbl->getAt(bk, pBlkTblRcd, AcDb::kForRead);

      AcDbBlockTableRecordIterator *pItr; // 块表记录遍历器;
      pBlkTblRcd->newIterator(pItr);

      // 遍历块表记录,将所有的直线改为红色
      for (pItr->start(); !pItr->done(); pItr->step())
      {
          AcDbEntity *pEn;
          pItr->getEntity(pEn, AcDb::kForRead);
          if(pEn->isKindOf(AcDbLine::desc()))//直线
          {
            pEn->upgradeOpen();//将对象打开模式由读提升为写
            AcDbLine * pLine=AcDbLine::cast(pEn);
            pLine->setColorIndex(1);//将直线改为红色

            pEn->close();
          }//Circle
            
          if (pEn != NULL)
          {
            pEn->close();
          }
      }
      delete pItr;
      pBlkTblRcd->close();
      pBlkTbl->close();
      pEnt->close();
      }//块;
      if (pEnt != NULL)
      {
      pEnt->close();
      }
    }

    //acutRelRb(rb);
    acedSSFree(result);//释放选集
}

ivde 发表于 2015-10-28 22:10:08

本帖最后由 ivde 于 2015-10-28 22:13 编辑

1 Blockreference直接获取blockid不用entget
2 改完regen或更新所有blockreference

zdqwy19 发表于 2015-10-28 22:57:11

ivde 发表于 2015-10-28 22:10 static/image/common/back.gif
1 Blockreference直接获取blockid不用entget
2 改完regen或更新所有blockreference

Blockreference直接获取blockid不用entget,遍历块可以不用知道块的名称?这个没有看到实例,我也只是照着实例抄着来的。 更新所有blockreference这个还真不懂。希望能给个代码学习下!

ivde 发表于 2015-10-29 08:04:47

        static void asdkMyGroupMyCommand () {
                // Put your command code here
                resbuf* rb=NULL;
                rb= acutBuildList(RTDXF0, _T("INSERT"),RTNONE);
                int ret;
                ads_name result;
                ret = acedSSGet(NULL, NULL, NULL, rb, result );
                if (ret!= RTNORM)
                {
                        acedPrompt( _T("\n创建选择集失败!") );
                        return;
                }
                acutRelRb(rb);
                long len,i=0;
                acedSSLength(result,&len);
                AcDbObjectIdArray blkIds;
                Acad::ErrorStatus es;
                ads_name ent;
                AcDbObjectId objId,blkId;
                for(i=0; i<len; i++)
                {
                        acedSSName(result, i, ent);
                        acdbGetObjectId(objId, ent);
                        AcDbEntity *pEnt=NULL;
                        es=acdbOpenAcDbEntity(pEnt, objId, AcDb::kForRead,false);
                        if (es!=Acad::eOk)
                        {
                                continue;
                        }
                        AcDbBlockReference *pBlockRef =NULL;
                        pBlockRef = AcDbBlockReference::cast(pEnt);
                        blkId=pBlockRef ->blockTableRecord();
                        if (!blkIds.contains(blkId,0))
                        {
                                blkIds.append(blkId);
                        }
                        pBlockRef->close();
                        pEnt->close();
                }
                for (int i=0;i<blkIds.logicalLength();i++)
                {
                        AcDbObjectId id=blkIds.at(i);
                        AcDbBlockTableRecordPointer btr(id,AcDb::kForWrite,false);
                        if (btr.openStatus()!=Acad::eOk)
                        {
                                continue;
                        }
                        AcDbBlockTableRecordIterator *pItr=NULL; // 块表记录遍历器;
                        btr->newIterator(pItr);
                        AcDbEntity *pEn=NULL;
                        for (pItr->start(); !pItr->done(); pItr->step())
                        {
                                pItr->getEntity(pEn, AcDb::kForRead,false);
                                if (pEn->isA()==AcDbLine::desc())
                                {
                                        pEn->upgradeOpen();
                                        pEn->setColorIndex(1,1);                                       
                                        pEn->close();
                                }
                        }                       
                        delete pItr;
                        btr.close();
                }
                acedCommand(RTSTR,_T("regen"),RTNONE);
                acedSSFree(result);//释放选集
        }

zdqwy19 发表于 2015-10-29 15:21:40

ivde 发表于 2015-10-29 08:04 static/image/common/back.gif


谢谢指导!看到您的代码感觉受益良多!另外如果不用regen如何更新所有blockreference?

ivde 发表于 2015-10-30 00:37:42

本帖最后由 ivde 于 2015-10-30 00:39 编辑

zdqwy19 发表于 2015-10-29 15:21 static/image/common/back.gif
谢谢指导!看到您的代码感觉受益良多!另外如果不用regen如何更新所有blockreference?

据说使用这两句
                actrTransactionManager->flushGraphics();
                acedUpdateDisplay();
我是没有测试成功过,可以使用一个变通方法
AcDbObjectIdArray ids;
es=btr->getBlockReferenceIds(ids,true,false);
....
if (es==Acad::eOk)
                        {
                                for (int n=0;n<ids.logicalLength();n++)
                                {
                                        AcDbObjectId bid;
                                        bid=ids.at(n);
                                        AcDbEntity* pblk=NULL;
                                        es=acdbOpenAcDbEntity(pblk,bid,AcDb::kForWrite,false);
                                        if (es==Acad::eOk)
                                        {
                                                AcDbBlockReference* pBlkr=NULL;
                                                pBlkr=AcDbBlockReference::cast(pblk);
                                                if (pBlkr!=NULL)
                                                {
                                                        AcGePoint3d pint;
                                                        pint=pBlkr->position();
                                                        pBlkr->setPosition(pint);
                                                        pBlkr->close();
                                                }
                                                pblk->close();
                                        }
                                }
                        }
相当于强制更新

zdqwy19 发表于 2015-10-30 14:50:22

ivde 发表于 2015-10-30 00:37 static/image/common/back.gif
据说使用这两句
                actrTransactionManager->flushGraphics();
                acedUpdateDisplay();


这个我找到了解决方法,打开插入块的时候
AcDbEntity* pEntity;
AcDbObjectId blkId;
acdbOpenObject( pEntity, blkId, AcDb::kForWrite );
//更改...
pEntity ->recordGraphicsModified();
pEntity ->close();
actrTransactionManager->flushGraphics();
acedUpdateDisplay();
谢谢了!
页: [1]
查看完整版本: objectarx修改块内实体无效