ObjectARX完美实现一次拖动多个实体(下)
2011-06-26 18:03
671 查看
这次我们来实现一次拖动多个数据库中已存在的实体,就象AuoCAD里的Move、Rotate、Mirror等命令一样。其中的临时实体类具有一定的通用性,只要给它传入不同的变换矩阵就能实现相应的功能。而Jig类的例子则是一个简单的移动示例,大约相当于Move命令的简化版。
临时实体类:
用于移动的Jig类:
测试命令:
临时实体类:
//辅助实体类 //适用于拖动数据库中已经存在的实体,通常是一个选择集选择的实体集 class CDatabaseJigEntity : public AcDbEntity { public: CDatabaseJigEntity(const AcDbObjectIdArray & ids) : m_Ids(ids){} ~CDatabaseJigEntity(){} virtual Adesk::Boolean worldDraw (AcGiWorldDraw *mode); void setXform(const AcGeMatrix3d & xform){ m_Xform = xform; } BOOL transform(); BOOL transformedCopy(); private: AcDbObjectIdArray m_Ids; //保存所有拖动对象的ID AcGeMatrix3d m_Xform;//变换矩阵 }; Adesk::Boolean CDatabaseJigEntity::worldDraw(AcGiWorldDraw *mode) { //这个地方是关键! mode->geometry().pushModelTransform(m_Xform); AcDbEntity* pEnt; for (int i = 0; i < m_Ids.length(); i++) { //绘制实体无需写打开 if (Acad::eOk == acdbOpenObject(pEnt, m_Ids[i],AcDb::kForRead)) { mode->geometry().draw(pEnt); pEnt->close(); } } //这句不能少,恢复现场 mode->geometry().popModelTransform(); return (AcDbEntity::worldDraw (mode)) ; } //用于拖动结束后,将实体变换到新位置 BOOL CDatabaseJigEntity::transform() { AcTransaction * pTrans = acTransactionManagerPtr() ->startTransaction(); if (NULL == pTrans) return FALSE; AcDbEntity *pEnt; AcDbObject *pObj; for (int i= 0; i < m_Ids.length(); i++) { if (Acad::eOk != pTrans ->getObject(pObj, m_Ids[i], AcDb::kForWrite)) { acTransactionManagerPtr() ->abortTransaction(); return FALSE; } pEnt = AcDbEntity::cast(pObj); pEnt ->transformBy(m_Xform); } acTransactionManagerPtr() ->endTransaction(); return TRUE; } //用于拖动结束后,将实体复制到新位置 BOOL CDatabaseJigEntity::transformedCopy() { AcTransaction * pTrans = acTransactionManagerPtr() ->startTransaction(); if (NULL == pTrans) return FALSE; AcDbEntity *pEnt; AcDbEntity *pNewEnt; AcDbObject *pObj; AcDbBlockTableRecord *pBlkRec; AcDbObjectId blkRecId; for (int i= 0; i < m_Ids.length(); i++) { if (Acad::eOk != pTrans ->getObject(pObj, m_Ids[i], AcDb::kForRead)) { acTransactionManagerPtr() ->abortTransaction(); return FALSE; } pEnt = AcDbEntity::cast(pObj); if (0 == i) { blkRecId = pEnt ->blockId(); if (Acad::eOk != pTrans ->getObject(pObj, blkRecId, AcDb::kForWrite)) { acTransactionManagerPtr() ->abortTransaction(); return FALSE; } pBlkRec = AcDbBlockTableRecord::cast(pObj); } pEnt ->getTransformedCopy(m_Xform, pNewEnt); pBlkRec ->appendAcDbEntity(pNewEnt); acTransactionManagerPtr() ->addNewlyCreatedDBRObject(pNewEnt); } acTransactionManagerPtr() ->endTransaction(); return TRUE; }
用于移动的Jig类:
//移动实体的拖动类 class CMoveJig : public AcEdJig { public: CMoveJig(const AcGePoint3d & fromPoint) : m_pEnt(NULL), m_FromPoint(fromPoint), m_ToPoint(fromPoint){} ~CMoveJig(); void doIt(const AcDbObjectIdArray & ids, bool bCopy = false); virtual DragStatus sampler(); virtual Adesk::Boolean update(); virtual AcDbEntity* entity() const; private: CDatabaseJigEntity *m_pEnt; AcGePoint3d m_FromPoint; AcGePoint3d m_ToPoint; AcGeMatrix3d m_Xform; }; CMoveJig::~CMoveJig() { if ( NULL != m_pEnt) { delete m_pEnt; m_pEnt = NULL; } } AcEdJig::DragStatus CMoveJig::sampler() { DragStatus stat; setUserInputControls((UserInputControls) (AcEdJig::kAccept3dCoordinates | AcEdJig::kNoNegativeResponseAccepted | AcEdJig::kNoZeroResponseAccepted | AcEdJig::kNullResponseAccepted )); static AcGePoint3d pointTemp; stat = acquirePoint(m_ToPoint, m_FromPoint); if (pointTemp != m_ToPoint) pointTemp = m_ToPoint; else if (stat == AcEdJig::kNormal) stat = AcEdJig::kNoChange; return stat; } Adesk::Boolean CMoveJig::update() { m_Xform.setToTranslation(m_ToPoint - m_FromPoint); m_pEnt ->setXform(m_Xform); return Adesk::kTrue; } AcDbEntity * CMoveJig::entity() const { return m_pEnt; } void CMoveJig::doIt(const AcDbObjectIdArray &ids, bool bCopy /*= false*/) { if ( 0 == ids.length() ) { return; } if (NULL != m_pEnt) { delete m_pEnt; m_pEnt = NULL; } m_pEnt = new CDatabaseJigEntity(ids); setDispPrompt(_T("/n移动到: ")); if ( AcEdJig::kNormal == drag() ) { if (bCopy) { m_pEnt ->transformedCopy(); } else { m_pEnt ->transform(); } } delete m_pEnt; m_pEnt = NULL; }
测试命令:
static void ZDXMyJig_jigmove(void) { ads_name ename; ads_point pt; ads_name ss; int rt; if (rt = acedSSGet(NULL, NULL, NULL, NULL, ss) == RTCAN) return; long len; acedSSLength(ss, &len); if (0 == len) return; AcDbObjectId id; //acdbGetObjectId(id,ename); AcDbObjectIdArray ids; for (int i = 0; i < len; i++) { acedSSName(ss, i , ename); acdbGetObjectId(id, ename); ids.append(id); } acedSSFree(ss); acedGetPoint(NULL, L"/n起点:", pt); CMoveJig * pJig = new CMoveJig(asPnt3d(pt)); pJig ->doIt(ids); }
相关文章推荐
- ObjectARX完美实现一次拖动多个实体(上)
- objectARx实现多个实体的拖动效果
- app-framework学习--完美解决scroller 拖动问题实现局部滚动
- 用objectARX实现了一个复杂实体的Jig
- app-framework学习--完美解决scroller 拖动问题实现局部滚动
- Android实现GridView的item长按拖动删除完美实现(带动画效果)
- VC编程完美实现树型控件的拖动
- javascript完美实现图片拖动改变顺序
- Android实现GridView的item长按拖动删除完美实现(带动画效果)
- (转)树型控件拖动的完美实现
- js实现完美拖拽效果可拖动层与回放拖动规迹并显示拖动距离参数
- Android SeekBar 禁止拖动和点击的实现(可能是最简单完美的实现)
- js实现完美拖拽效果可拖动层与回放拖动规迹并显示拖动距离参数
- Android FlingGallery类完美手势拖动实现
- iOS实现自定义进度条、拖动条效果
- Android 实现音乐剪切功能 可以选择起始点和结束点 也可以同时拖动块级元素
- 纯javascript对撤销和重写(undo、redo)的完美实现,适用于任何页面元素操作
- Windows Mobile上实现可拖动的窗口
- asp.net 中实现页面每隔一分钟刷新一次的效果
- C++ Builder 实现控件的拖动-停靠操作