当前位置: 代码迷 >> 综合 >> [转]ObjectARX 使用 AcDbMultiModesGripPE 夹点上下文菜单
  详细解决方案

[转]ObjectARX 使用 AcDbMultiModesGripPE 夹点上下文菜单

热度:70   发布时间:2023-12-23 22:28:41.0

转载 https://www.cnblogs.com/edata/p/16062438.html

篇一:使用 AcDbMultiModesGripPE 夹点上下文菜单

作者 Balaji Ramamoorthy

原链接 http://adndevblog.typepad.com/autocad/2013/12/grip-context-menu-using-acdbmultimodesgrippe.html

这是一个使用 AcDbMultiModesGripPE 为自定义实体实现夹点上下文菜单的示例项目。它演示了使用多模式夹点来获取与自定义实体相关的输入。

为了让它变得有趣,我创建了一个类似于树的自定义实体。它的夹点上下文菜单显示两种模式 - “春季”和“冬季”。创建树自定义实体后,当夹点变热时将出现上下文菜单。选择“春天”将确保树有叶子,选择“冬天”将使树脱落叶子。

在这种情况下,模式与夹点编辑无关,并且由于我们不希望夹点在单击时开始拖动,因此将模式的动作类型设置为命令。选择模式后,AutoCAD 将调用该命令。在命令实现中,我们确保树根据选择的模式更新其显示。我希望在当前模式旁边有一个复选标记,但 API 目前没有办法做到这一点,我们的工程团队为它创建了一个愿望清单项目。

这是相关代码,完整的示例项目可以从下面的链接下载:

示例项目下载 multimodegrip_simplesample

图片展示

// Header
// TreeMultiModesGripPE.h#pragma once#include "dbMultiModesGrip.h"class AdskTreeMultiModesGripPE : public AcDbMultiModesGripPE
{
private:static AcDbMultiModesGripPE::GripMode _currentGripMode;static AcDbObjectId _lastModifiedEntId;public:ACRX_DECLARE_MEMBERS(AdskTreeMultiModesGripPE);AdskTreeMultiModesGripPE();~AdskTreeMultiModesGripPE();static AcDbObjectId getLastModifiedEntId();virtual bool getGripModes(AcDbEntity* pThis, AcDbGripData* pGripData, AcArray<GripMode>& modes, unsigned int& curMode) const;virtual unsigned int mode(AcDbEntity* pThis, AcDbGripData* pGripData) const;virtual AcDbMultiModesGripPE::GripMode modeEx(AcDbEntity* pThis, AcDbGripData* pGripData) const;virtual bool setMode(AcDbEntity* pThis, AcDbGripData* pGripData, unsigned int newMode);virtual AcDbMultiModesGripPE::GripType gripType(AcDbEntity* pThis, AcDbGripData* pGripData) const;virtual void reset(AcDbEntity* pThis);
};// Implementation
// TreeMultiModesGripPE.cpp#include "StdAfx.h"
#include "dbMultiModesGrip.h"
#include "TreeMultiModesGripPE.h"
#include "AdskTree.h"ACRX_CONS_DEFINE_MEMBERS(AdskTreeMultiModesGripPE, AcDbMultiModesGripPE, 1);AcDbMultiModesGripPE::GripMode AdskTreeMultiModesGripPE::_currentGripMode;AcDbObjectId AdskTreeMultiModesGripPE::_lastModifiedEntId = AcDbObjectId::kNull;AdskTreeMultiModesGripPE::AdskTreeMultiModesGripPE()
{// Default grip mode_currentGripMode.Mode = 0;_currentGripMode.DisplayString = AcString("Spring");
}AdskTreeMultiModesGripPE::~AdskTreeMultiModesGripPE()
{
}// Returns the possible grip modes
bool AdskTreeMultiModesGripPE::getGripModes(AcDbEntity* pThis, AcDbGripData* pGripData, AcArray<GripMode>& modes, unsigned int& curMode) const 
{GripMode gripMode1;gripMode1.Mode = 0;gripMode1.DisplayString = AcString("Spring");gripMode1.ActionType = GripActionType::kCommand;gripMode1.CommandString = AcString("ModeSwitchCmd ");modes.append(gripMode1);GripMode gripMode2;gripMode2.Mode = 1;gripMode2.DisplayString = AcString("Winter");gripMode2.ActionType = GripActionType::kCommand;gripMode2.CommandString = AcString("ModeSwitchCmd ");modes.append(gripMode2);curMode = 0;return true;
}// Gets the current mode identifier.
unsigned int AdskTreeMultiModesGripPE::mode(AcDbEntity* pThis, AcDbGripData* pGripData) const
{return _currentGripMode.Mode; 
}// Return the current mode.
AcDbMultiModesGripPE::GripMode AdskTreeMultiModesGripPE::modeEx(AcDbEntity* pThis, AcDbGripData* pGripData) const 
{return _currentGripMode;
}// Sets the current mode.
bool AdskTreeMultiModesGripPE::setMode(AcDbEntity* pThis, AcDbGripData* pGripData, unsigned int newMode)
{_currentGripMode.Mode = newMode;AcDbObjectId entId = pThis->id();AdskTree *pTree = AdskTree::cast(pThis);switch(newMode){case 0:acutPrintf(ACRX_T("\nSpring season, growing leaves !"));_currentGripMode.DisplayString = AcString("Spring"); pTree->setSeason(AcString("Spring"));// For graphics update_lastModifiedEntId = pTree->id();break;case 1:acutPrintf(ACRX_T("\nWinter season, shedding leaves !"));_currentGripMode.DisplayString = AcString("Winter");pTree->setSeason(AcString("Winter"));// For graphics update_lastModifiedEntId = pTree->id();break;}return true;
}// Gets the grip type of a given grip.
AcDbMultiModesGripPE::GripType 
AdskTreeMultiModesGripPE::gripType(AcDbEntity* pThis, AcDbGripData* pGripData) const 
{return AcDbMultiModesGripPE::GripType::kPrimary;  
}// To retrieve the objectId of the tree entity 
// for graphics update
AcDbObjectId AdskTreeMultiModesGripPE::getLastModifiedEntId()
{return _lastModifiedEntId;
}// resets current mode to default 
void AdskTreeMultiModesGripPE::reset(AcDbEntity* pThis)
{_currentGripMode.Mode = 0;_currentGripMode.DisplayString = AcString("Spring");
}// Header for custom entity
// AsdkTree.h#pragma once#ifdef MULTIMODEGRIPSIMPLESAMPLE_MODULE
#define DLLIMPEXP __declspec(dllexport)
#else
#define DLLIMPEXP
#endif//-----------------------------------------------------------------------------
#include "dbmain.h"//-----------------------------------------------------------------------------
class DLLIMPEXP AdskTree : public AcDbEntity 
{public:ACRX_DECLARE_MEMBERS(AdskTree) ;protected:static Adesk::UInt32 kCurrentVersionNumber ;private:AcGePoint3d _basePoint;AcString _season;void BuildSubTree(AcGeLineSeg3d *pMainBranch, int level, AcGiWorldDraw *mode, Adesk::Boolean flower = Adesk::kFalse);public:AdskTree () ;virtual ~AdskTree () ;// Sets the season statusvoid setSeason(AcString season);// Sets the insertion pointvoid setBasePoint(AcGePoint3d basePoint);//----- AcDbObject protocols//- Dwg Filing protocolvirtual Acad::ErrorStatus dwgOutFields (AcDbDwgFiler *pFiler) const ;virtual Acad::ErrorStatus dwgInFields (AcDbDwgFiler *pFiler) ;//----- AcDbEntity protocols//- Graphics protocol
protected:virtual Adesk::Boolean subWorldDraw (AcGiWorldDraw *mode) ;virtual Acad::ErrorStatus subTransformBy(const AcGeMatrix3d& xform);//- Grip points protocolvirtual Acad::ErrorStatus subGetGripPoints (AcDbGripDataPtrArray &grips, const double curViewUnitSize, const int gripSize, const AcGeVector3d &curViewDir, const int bitflags) const ;virtual Acad::ErrorStatus subMoveGripPointsAt (const AcDbVoidPtrArray &gripAppData, const AcGeVector3d &offset, const int bitflags) ;
};#ifdef MULTIMODEGRIPSIMPLESAMPLE_MODULE
ACDB_REGISTER_OBJECT_ENTRY_AUTO(AdskTree)
#endif// Implementation of the custom entity
// AdskTree.cpp #include "StdAfx.h"
#include "AdskTree.h"Adesk::UInt32 AdskTree::kCurrentVersionNumber =1 ;ACRX_DXF_DEFINE_MEMBERS (AdskTree, AcDbEntity,AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, AcDbProxyEntity::kNoOperation, ADSKTREE,
ADSKMULTIMODEGRIPSIMPLESAMPLEAPP
|Product Desc:     A description for your object
|Company:          Your company name
|WEB Address:      Your company WEB site address
)AdskTree::AdskTree () : AcDbEntity () 
{_basePoint = AcGePoint3d::kOrigin; _season = AcString("Spring");
}AdskTree::~AdskTree () 
{
}//----- AcDbObject protocols
//- Dwg Filing protocol
Acad::ErrorStatus AdskTree::dwgOutFields(AcDbDwgFiler *pFiler) const {assertReadEnabled () ;//----- Save parent class information first.Acad::ErrorStatus es =AcDbEntity::dwgOutFields (pFiler) ;if ( es != Acad::eOk )return (es) ;//----- Object version number needs to be saved firstif ( (es =pFiler->writeUInt32 (AdskTree::kCurrentVersionNumber)) != Acad::eOk )return (es) ;//----- Output paramspFiler->writePoint3d(_basePoint);return (pFiler->filerStatus ()) ;
}Acad::ErrorStatus AdskTree::dwgInFields(AcDbDwgFiler *pFiler)
{assertWriteEnabled () ;//----- Read parent class information first.Acad::ErrorStatus es =AcDbEntity::dwgInFields (pFiler) ;if ( es != Acad::eOk )return (es) ;//----- Object version number needs to be read firstAdesk::UInt32 version =0 ;if ( (es =pFiler->readUInt32 (&version)) != Acad::eOk )return (es) ;if ( version > AdskTree::kCurrentVersionNumber )return (Acad::eMakeMeProxy) ;//----- Read paramspFiler->readPoint3d(&_basePoint);return (pFiler->filerStatus ()) ;
}//----- AcDbEntity protocols
Adesk::Boolean AdskTree::subWorldDraw (AcGiWorldDraw *mode) 
{assertReadEnabled () ;AcGeLineSeg3d mainBranch(_basePoint, AcGePoint3d(_basePoint.x,_basePoint.y+10.0,_basePoint.z));AcDbLine *pLine1 = new AcDbLine(mainBranch.startPoint(), mainBranch.endPoint());mode->geometry().draw(pLine1);delete pLine1;int level = 0;BuildSubTree(&mainBranch, level, mode);return (AcDbEntity::subWorldDraw (mode)) ;
}void AdskTree::setBasePoint(AcGePoint3d basePoint)
{_basePoint = basePoint;
}void AdskTree::setSeason(AcString season)
{_season = season;
}void AdskTree::BuildSubTree(AcGeLineSeg3d *pMainBranch, int level, AcGiWorldDraw *mode, Adesk::Boolean flower)
{if(mode->isDragging() && level >= 2)return; // Light weight for draggingif(level >= 3){if(_season == AcString("Spring")){AcDbCircle *pLeaf = new AcDbCircle(pMainBranch->endPoint(), AcGeVector3d::kZAxis, pMainBranch->length() * 0.2); if(flower)pLeaf->setColorIndex(1);elsepLeaf->setColorIndex(2); mode->geometry().draw(pLeaf);delete pLeaf;}return;}int subLevel = level + 1;AcGePoint3d sp = AcGePoint3d::kOrigin;AcGePoint3d ep = AcGePoint3d::kOrigin;AcGeInterval intrvl;pMainBranch->getInterval(intrvl, sp, ep);double len = pMainBranch->length();AcGePoint3dArray pts;pMainBranch->getSamplePoints(5, pts);const double PI = 3.1415926535897932385;int cnt = 1;if(level == 0)cnt = 2;for(;cnt < 5; cnt++){AcGeVector3d dir = pMainBranch->direction().normalize(); AcGePoint3d refPt1 = pts[cnt];if(cnt == 4){AcGePoint3d refPt2 = refPt1 + (len * 0.5) * dir;AcGeLineSeg3d branch1(refPt1, refPt2);AcDbLine *pBranchLine1 = new AcDbLine(refPt1, refPt2);mode->geometry().draw(pBranchLine1);delete pBranchLine1;BuildSubTree(&branch1, subLevel, mode, Adesk::kTrue);}else{AcGePoint3d refPt2 = refPt1 + (len * 0.5) * dir.transformBy(AcGeMatrix3d::rotation(    PI * 0.25, AcGeVector3d::kZAxis, refPt1));AcGeLineSeg3d branch1(refPt1, refPt2);AcDbLine *pBranchLine1 = new AcDbLine(refPt1, refPt2);mode->geometry().draw(pBranchLine1);delete pBranchLine1;BuildSubTree(&branch1, subLevel, mode);dir = pMainBranch->direction().normalize(); refPt2 = refPt1 + (len * 0.5) * dir.transformBy(AcGeMatrix3d::rotation(-PI * 0.25, AcGeVector3d::kZAxis, refPt1));AcGeLineSeg3d branch2(refPt1, refPt2);AcDbLine *pBranchLine2 = new AcDbLine(refPt1, refPt2);mode->geometry().draw(pBranchLine2);delete pBranchLine2;BuildSubTree(&branch2, subLevel, mode);}}
}Acad::ErrorStatus AdskTree::subGetGripPoints ( AcDbGripDataPtrArray &grips, const double curViewUnitSize, const int gripSize,  const AcGeVector3d &curViewDir, const int bitflags ) const 
{assertReadEnabled () ;AcDbGripData *pGripData = new AcDbGripData();pGripData->setGripPoint(_basePoint);grips.append(pGripData);return Acad::eOk;
}Acad::ErrorStatus AdskTree::subMoveGripPointsAt (const AcDbVoidPtrArray &gripAppData, const AcGeVector3d &offset,const int bitflags) 
{assertWriteEnabled () ;_basePoint += offset;return Acad::eOk;
}Acad::ErrorStatus AdskTree::subTransformBy(const AcGeMatrix3d& xform)
{assertWriteEnabled();_basePoint.transformBy(xform);return (AcDbEntity::subTransformBy(xform));
}// acrxEntryPoint.cpp
// Usage #include "resource.h"
#include "AdskTree.h"#include "stdafx.h"
#include "dbMultiModesGrip.h"
#include "TreeMultiModesGripPE.h"static AdskTreeMultiModesGripPE *pMyMultiModeGrips = NULL;#define szRDS _RXST("Adsk")//----- ObjectARX EntryPoint
class CMultiModeGripSimpleSampleApp : public AcRxArxApp {public:CMultiModeGripSimpleSampleApp () : AcRxArxApp () {}virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {// TODO: Load dependencies here// You *must* call On_kInitAppMsg hereAcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg(pkt) ;AdskTreeMultiModesGripPE::rxInit();AdskTree::rxInit();acrxBuildClassHierarchy();// TODO: Add your initialization code hereif(pMyMultiModeGrips == NULL){pMyMultiModeGrips = new AdskTreeMultiModesGripPE();AdskTree::desc()->addX(AcDbMultiModesGripPE::desc(), pMyMultiModeGrips);}return (retCode) ;}virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {// TODO: Add your code here// You *must* call On_kUnloadAppMsg hereAcRx::AppRetCode retCode = AcRxArxApp::On_kUnloadAppMsg (pkt) ;// TODO: Unload dependencies hereif(pMyMultiModeGrips != NULL){delete pMyMultiModeGrips;pMyMultiModeGrips = NULL;}return (retCode) ;}virtual void RegisterServerComponents () {}// "Tree" command to create a treestatic void AdskMultiModeGripSimpleSampleTREE(void){ads_point pt;if (RTNORM != acedGetPoint(NULL, L"\nSelect tree base point: ", pt))return;AcGePoint3d insertionPt = asPnt3d( pt );AdskTree *pTree = new AdskTree();pTree->setDatabaseDefaults();pTree->setBasePoint(insertionPt);PostToDb(pTree);}// Add the entity to DBstatic Acad::ErrorStatus PostToDb(AcDbEntity* pEnt){AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();AcDbObjectId objId;Acad::ErrorStatus      es;AcDbBlockTable*        pBlockTable;AcDbBlockTableRecord*  pSpaceRecord;pDb->getBlockTable(pBlockTable, AcDb::kForRead);pBlockTable->getAt( ACDB_MODEL_SPACE, pSpaceRecord, AcDb::kForWrite);es = pSpaceRecord->appendAcDbEntity(objId, pEnt);es = pEnt->close();es = pSpaceRecord->close();es = pBlockTable->close();return es;}// Command to update the graphics after the // grip mode was changed. // This will ensure a graphics is in sync with the// mode selected static void AdskMultiModeGripSimpleSampleModeSwitchCmd(void){AcDbObjectId entId = AdskTreeMultiModesGripPE::getLastModifiedEntId(); AcApDocument *pActiveDoc = acDocManager->mdiActiveDocument();AcDbDatabase *pDb = pActiveDoc->database();if(entId.isNull())return;AcDbEntity* pEnt = NULL;acdbOpenAcDbEntity(pEnt, entId, AcDb::kForWrite);pEnt->recordGraphicsModified();pEnt->close();acedUpdateDisplay();}
} ;//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CMultiModeGripSimpleSampleApp)ACED_ARXCOMMAND_ENTRY_AUTO(CMultiModeGripSimpleSampleApp, AdskMultiModeGripSimpleSample, TREE, TREE, ACRX_CMD_TRANSPARENT, NULL)
ACED_ARXCOMMAND_ENTRY_AUTO(CMultiModeGripSimpleSampleApp, AdskMultiModeGripSimpleSample, ModeSwitchCmd, ModeSwitchCmd, ACRX_CMD_TRANSPARENT,NULL) 

篇二:使自定义实体 GripMode 感知

作者 Balaji Ramamoorthy

原链接 http://adndevblog.typepad.com/autocad/2014/02/making-custom-entity-gripmode-aware.html

这是一个实现嵌入式多段线的自定义实体的示例项目。 自定义实体通过实现“subMoveGripPointsAt”方法 GripMode 来启用对嵌入式实体进行操作的 GripMode。 在附件项目中,自定义实体的夹点模式与嵌入式多段线的夹点模式相同,但如果您的自定义实体有多个嵌入式实体,您可以扩展实现以在相似的线上为自定义实体公开更多的 GripModes。

这是相关代码的一部分,示例项目可以从这里下载:

示例项目下载 multimodegrip_embeddedpolyline

//ContainerEntity.h // Custom grip app data to identify the grips 
class MyGripAppData : public AcDbObject
{
public:ACRX_DECLARE_MEMBERS(MyGripAppData) ;Adesk::UInt32 m_GripNumber;MyGripAppData(){ m_GripNumber = 0; }MyGripAppData(int gripNumber){ m_GripNumber = gripNumber; }
};// Container custom entity that embeds a polyline
class DLLIMPEXP AdskContainerEntity : public AcDbEntity 
{public:ACRX_DECLARE_MEMBERS(AdskContainerEntity) ;protected:static Adesk::UInt32 kCurrentVersionNumber ;public:AdskContainerEntity () ;virtual ~AdskContainerEntity () ;AcDbPolyline *m_pPolyline; // Embedded Polyline// GripMode for use in "subMoveGripPointsAt" // which is GripMode aware. Adesk::UInt32 m_pCurrentGripMode; // To remove or to add after depending on the GripModeAdesk::UInt32 m_iVertexNumber;    // Coordinates of the new vertex point to // add if the GripMode is "Add Vertex"AcGePoint2d m_NewVertexCoord;     protected:virtual Adesk::Boolean subWorldDraw (AcGiWorldDraw *mode) ;virtual Acad::ErrorStatus subTransformBy(const AcGeMatrix3d& xform);Acad::ErrorStatus dwgInFields (AcDbDwgFiler *pFiler);Acad::ErrorStatus dwgOutFields (AcDbDwgFiler *pFiler) const;//- Grip points protocolvirtual Acad::ErrorStatus subGetGripPoints (AcDbGripDataPtrArray &grips, const double curViewUnitSize, const int gripSize, const AcGeVector3d &curViewDir, const int bitflags) const ;virtual Acad::ErrorStatus subMoveGripPointsAt(const AcDbVoidPtrArray& gripAppData, const AcGeVector3d& offset, const int bitflags);
};// ContainerEntity.cpp : Implementation of AdskContainerEntityAdskContainerEntity::AdskContainerEntity () : AcDbEntity () 
{m_pPolyline = NULL;m_pCurrentGripMode = 0;m_iVertexNumber = 0;
}AdskContainerEntity::~AdskContainerEntity () 
{if (m_pPolyline){delete m_pPolyline;m_pPolyline = 0;}
}Acad::ErrorStatus AdskContainerEntity::dwgInFields(AcDbDwgFiler *pFiler) 
{assertWriteEnabled () ;Acad::ErrorStatus es = AcDbEntity::dwgInFields (pFiler) ;if ( es != Acad::eOk )return (es) ;Adesk::UInt32 version =0 ;if ( (es =pFiler->readUInt32 (&version)) != Acad::eOk )return (es) ;if ( version > AdskContainerEntity::kCurrentVersionNumber)return (Acad::eMakeMeProxy) ;// Read paramsAdesk::UInt32 numVerts = 0;pFiler->readUInt32(&numVerts);AcGePoint3dArray points;for(int i = 0; i < numVerts; i++){AcGePoint3d pt;pFiler->readPoint3d(&pt);points.append(pt);}if (m_pPolyline){delete m_pPolyline;m_pPolyline = 0;}m_pPolyline = new AcDbPolyline(numVerts);         m_pPolyline->setDatabaseDefaults();for(int i = 0; i < numVerts; i++){AcGePoint3d pt(points[i]);m_pPolyline->addVertexAt(i, AcGePoint2d(pt.x, pt.y));}return (pFiler->filerStatus ()) ;
}Acad::ErrorStatus AdskContainerEntity::dwgOutFields (AcDbDwgFiler *pFiler) const 
{assertReadEnabled () ;Acad::ErrorStatus es = AcDbEntity::dwgOutFields (pFiler) ;if ( es != Acad::eOk )return (es) ;if ( (es =pFiler->writeUInt32 (AdskContainerEntity::kCurrentVersionNumber)) != Acad::eOk )return (es) ;// Output paramsif(m_pPolyline){Adesk::UInt32 numVerts = m_pPolyline->numVerts();pFiler->writeUInt32(numVerts);for(int i = 0; i < numVerts; i++){AcGePoint3d pt;m_pPolyline->getPointAt(i, pt);pFiler->writePoint3d(pt); }}return (pFiler->filerStatus ()) ;
}Adesk::Boolean AdskContainerEntity::subWorldDraw (AcGiWorldDraw *mode) 
{assertReadEnabled () ;// Draw the polylineif(m_pPolyline)mode->geometry().pline (*m_pPolyline);return (AcDbEntity::subWorldDraw (mode)) ;
}Acad::ErrorStatus AdskContainerEntity::subGetGripPoints(AcDbGripDataPtrArray &grips, const double curViewUnitSize, const int gripSize,  const AcGeVector3d &curViewDir, const int bitflags ) const 
{assertReadEnabled () ;// Return the vertices of the embedded polyline as // grip pointsif(m_pPolyline){Adesk::UInt32 numVerts = m_pPolyline->numVerts();for(int i = 0; i < numVerts; i++){AcGePoint3d pt;m_pPolyline->getPointAt(i, pt);AcDbGripData * pGripData = new AcDbGripData();pGripData->setAppData(new MyGripAppData(i));pGripData->setGripPoint(pt); grips.append(pGripData);}}return Acad::eOk;
}// Grip mode aware implementation of subMoveGripPointsAt
// Depending on the current grip mode, it stretches / adds or
// removes vertices from the embedded polylineAcad::ErrorStatus AdskContainerEntity::subMoveGripPointsAt(const AcDbVoidPtrArray& gripAppData, const AcGeVector3d& offset, const int bitflags){assertWriteEnabled () ;if(m_pPolyline){switch(m_pCurrentGripMode){case 0: // Stretch {for (int i = 0; i < gripAppData.length(); i++){MyGripAppData *pMyGripAppData = static_cast<MyGripAppData *>(gripAppData.at(i));if(pMyGripAppData != NULL){int num = pMyGripAppData->m_GripNumber;AcGePoint3d pt;m_pPolyline->getPointAt(num, pt);AcGeMatrix3d mat = AcGeMatrix3d::kIdentity;mat = mat.translation(offset);pt = pt.transformBy(mat);m_pPolyline->setPointAt(num, AcGePoint2d(pt.x, pt.y));}}break;}case 1: // Add Vertex{m_pPolyline->addVertexAt(m_iVertexNumber+1, AcGePoint2d(m_NewVertexCoord.x, m_NewVertexCoord.y));// Reset to default GripModem_pCurrentGripMode = 0; break;}case 2: // Remove Vertex{if(m_iVertexNumber < m_pPolyline->numVerts())m_pPolyline->removeVertexAt(m_iVertexNumber); // Reset to default GripModem_pCurrentGripMode = 0; break;}}}return Acad::eOk;}Acad::ErrorStatus AdskContainerEntity::subTransformBy(const AcGeMatrix3d& xform)
{assertWriteEnabled();// Transform the polylineif(m_pPolyline)m_pPolyline->transformBy(xform);return (AcDbEntity::subTransformBy(xform));
}// ContainerEntityMultiModesGripPE.h#include "dbMultiModesGrip.h"// GripModePE implementation for the custom entity
// This exposes 3 gripmodes. 
// Stretch vertex
// Add Vertex
// Remove Vertex
class AdskContainerEntityMultiModesGripPE : public AcDbMultiModesGripPE
{
private:static AcDbMultiModesGripPE::GripMode _currentGripMode;public:ACRX_DECLARE_MEMBERS(AdskContainerEntityMultiModesGripPE);AdskContainerEntityMultiModesGripPE();~AdskContainerEntityMultiModesGripPE();static AcDbObjectId getLastModifiedEntId();static Adesk::UInt32 getVertexNumberToAdd();virtual bool getGripModes(    AcDbEntity* pThis, AcDbGripData* pGripData, AcArray<GripMode>& modes, unsigned int& curMode) const;virtual unsigned int mode(    AcDbEntity* pThis, AcDbGripData* pGripData) const;virtual AcDbMultiModesGripPE::GripMode modeEx(AcDbEntity* pThis, AcDbGripData* pGripData) const;virtual bool setMode(    AcDbEntity* pThis, AcDbGripData* pGripData, unsigned int newMode);virtual AcDbMultiModesGripPE::GripType gripType(AcDbEntity* pThis, AcDbGripData* pGripData) const;virtual void reset(AcDbEntity* pThis);
};// ContainerEntityMultiModesGripPE.cpp
// GripModePE implementation for the custom entity
// This exposes 3 gripmodes. 
// Stretch vertex
// Add Vertex
// Remove VertexAdskContainerEntityMultiModesGripPE::AdskContainerEntityMultiModesGripPE()
{// Default grip mode : Stretch Vertex_currentGripMode.Mode = 0;_currentGripMode.DisplayString = AcString("Stretch Vertex");
}AdskContainerEntityMultiModesGripPE::~AdskContainerEntityMultiModesGripPE()
{
}// Returns the possible grip modes
// Stretch vertex
// Add Vertex
// Remove Vertex
bool AdskContainerEntityMultiModesGripPE::getGripModes(AcDbEntity* pThis, AcDbGripData* pGripData, AcArray<GripMode>& modes, unsigned int& curMode) const 
{// "Stretch Vertex" modeGripMode gripMode1;gripMode1.Mode = 0;gripMode1.DisplayString = AcString("Stretch Vertex");gripMode1.ActionType = AcDbMultiModesGripPE::kDragOn;modes.append(gripMode1);// "Add Vertex" modeGripMode gripMode2;gripMode2.Mode = 1;gripMode2.DisplayString = AcString("Add Vertex");gripMode2.ActionType = AcDbMultiModesGripPE::kImmediate;modes.append(gripMode2);// "Remove Vertex" mode to be available only if there are // more than 2 vertices in the polyline.AdskContainerEntity *pContEnt = AdskContainerEntity::cast(pThis);if(pContEnt->m_pPolyline != NULL){if(pContEnt->m_pPolyline->numVerts() > 2){GripMode gripMode3;gripMode3.Mode = 2;gripMode3.DisplayString = AcString("Remove Vertex");gripMode3.ActionType = AcDbMultiModesGripPE::kImmediate;modes.append(gripMode3);}}// "Stretch Vertex" is the current modecurMode = 0;return true;
}// Gets the current mode identifier.
unsigned int AdskContainerEntityMultiModesGripPE::mode(AcDbEntity* pThis, AcDbGripData* pGripData) const
{return _currentGripMode.Mode; 
}// Return the current mode.
AcDbMultiModesGripPE::GripMode 
AdskContainerEntityMultiModesGripPE::modeEx(AcDbEntity* pThis, AcDbGripData* pGripData) const 
{return _currentGripMode;
}// Sets the current mode.
bool AdskContainerEntityMultiModesGripPE::setMode(AcDbEntity* pThis, AcDbGripData* pGripData, unsigned int newMode)
{bool retStatus = true;_currentGripMode.Mode = newMode;AcDbObjectId entId = pThis->id();AdskContainerEntity *pContEnt = AdskContainerEntity::cast(pThis);pContEnt->m_pCurrentGripMode = newMode;switch(newMode){case 0:{_currentGripMode.DisplayString = AcString("Stretch Vertex"); break;}case 1:{_currentGripMode.DisplayString = AcString("Add Vertex");// Create a temporary copy of the embedded Polyline for jigging purposesAcDbPolyline *pPolyTemp = AcDbPolyline::cast(pContEnt->m_pPolyline->clone());MyGripAppData *pMyGripAppData = static_cast<MyGripAppData *>(pGripData->appData());if(pMyGripAppData != NULL){// Adding vertex requires a JigPolyLineVertexAddJig *pPolyAddVertedJig = new PolyLineVertexAddJig(pPolyTemp, pMyGripAppData->m_GripNumber);AcEdJig::DragStatus status = pPolyAddVertedJig->doIt();if(status != AcEdJig::kCancel){pContEnt->m_iVertexNumber = pMyGripAppData->m_GripNumber;pContEnt->m_NewVertexCoord = pPolyAddVertedJig->AddedVertex();}else{// Cancel setting the GripMode as the // Jig was canceled retStatus = false; }delete pPolyAddVertedJig;}break;}case 2:{_currentGripMode.DisplayString = AcString("Remove Vertex");MyGripAppData *pMyGripAppData = static_cast<MyGripAppData *>(pGripData->appData());if(pMyGripAppData != NULL){pContEnt->m_iVertexNumber = pMyGripAppData->m_GripNumber;}break;}}return retStatus;
}// Gets the grip type of a given grip.
AcDbMultiModesGripPE::GripType AdskContainerEntityMultiModesGripPE::gripType(AcDbEntity* pThis, AcDbGripData* pGripData) const 
{return AcDbMultiModesGripPE::kPrimary;  
}// resets current mode to default 
void AdskContainerEntityMultiModesGripPE::reset(AcDbEntity* pThis)
{_currentGripMode.Mode = 0;_currentGripMode.DisplayString = AcString("Stretch Vertex");
}// PolyLineVertexAddJig.h
// Polyline jig for adding a new vertexclass PolyLineVertexAddJig : public AcEdJig
{
public:PolyLineVertexAddJig();~PolyLineVertexAddJig();PolyLineVertexAddJig(AcDbPolyline *pPoly, Adesk::UInt32 vertexToAdd);AcEdJig::DragStatus doIt();virtual DragStatus sampler();virtual Adesk::Boolean update();AcGePoint2d AddedVertex();virtual AcDbEntity* entity() const;private:AcDbPolyline *m_pPoly;Adesk::UInt32 m_nVertexToAdd;AcGePoint3d vertexPointTemp;AcGePoint3d vertexPoint;Adesk::Boolean addNew;
};// PolyLineVertexAddJig.cpp#include "StdAfx.h"
#include "PolyLineVertexAddJig.h"PolyLineVertexAddJig::PolyLineVertexAddJig()
{m_pPoly = NULL;vertexPointTemp = AcGePoint3d::kOrigin;vertexPoint = AcGePoint3d::kOrigin;addNew = Adesk::kTrue;
}PolyLineVertexAddJig::PolyLineVertexAddJig(AcDbPolyline *pPoly, Adesk::UInt32 vertexToAdd)
{// Polyline to jigm_pPoly = pPoly;// Index to mark the position of the new vertexm_nVertexToAdd = vertexToAdd;// To keep track of the coordinates during jiggingvertexPointTemp = AcGePoint3d::kOrigin;vertexPoint = AcGePoint3d::kOrigin;// To know if we already added a vertex during jiggingaddNew = Adesk::kTrue;
}PolyLineVertexAddJig::~PolyLineVertexAddJig()
{// Cleanupif(m_pPoly){delete m_pPoly;m_pPoly = NULL;}
}// Start the jig
AcEdJig::DragStatus PolyLineVertexAddJig::doIt()
{AcEdJig::DragStatus stat = AcEdJig::kCancel;if(m_pPoly){setDispPrompt(ACRX_T("\n Select vertex point : "));stat = drag();}return stat;
}AcEdJig::DragStatus PolyLineVertexAddJig::sampler()
{DragStatus stat;setUserInputControls((UserInputControls)(AcEdJig::kAccept3dCoordinates| AcEdJig::kNoNegativeResponseAccepted| AcEdJig::kNoZeroResponseAccepted));// Get a point input for the coordinatesstat = acquirePoint(vertexPoint);if (vertexPointTemp != vertexPoint)vertexPointTemp = vertexPoint;else if (stat == AcEdJig::kNormal)return AcEdJig::kNoChange;return stat;
}Adesk::Boolean PolyLineVertexAddJig::update()
{if(m_pPoly){if(addNew){// First time, add a new vertexm_pPoly->addVertexAt(m_nVertexToAdd+1, AcGePoint2d(vertexPoint.x, vertexPoint.y));}else{ // Update the coordinates of the // previously added vertexif(m_nVertexToAdd < m_pPoly->numVerts()){m_pPoly->setPointAt(m_nVertexToAdd+1, AcGePoint2d(vertexPoint.x, vertexPoint.y));}}}if(addNew)addNew = Adesk::kFalse;return Adesk::kTrue;
}AcDbEntity* PolyLineVertexAddJig::entity() const
{return m_pPoly;
}// To get the coordinates of the vertex added by this jig
AcGePoint2d PolyLineVertexAddJig::AddedVertex()
{return AcGePoint2d(vertexPoint.x, vertexPoint.y);
}