ADN Open CIS
Сообщество программистов Autodesk в СНГ

13/01/2014

Контекстное меню ручек с использованием AcDbMultiModesGripPE

Это пример проекта, который реализует контекстное меню ручек для собственного примитива с использованием класса AcDbMultiModesGripPE. Он демонстрирует использование мультирежимных ручек, которые выполняют ввод в зависимости от собственного примитива.

Чтобы было веселее, я создал собственный примитив, который напоминает дерево. Контекстное меню его ручек показывает два режима: "Spring" (весна) and "Winter" (зима). После того как собственный примитив дерева создан, контекстное меню появляется, когда курсор оказывается возле ручки (ручка становится «теплой»). Выбор "Spring" (весна) приводит к тому, что у дерева появляются листья, а при выборе "Winter" (зима) дерево сбрасывает листья.

В нашем случае, так как режимы не связаны с редактированием при помощи ручек и нам не нужно начинать редактирование перетаскиванием за ручку, тип днйствия будет установлен как команда. После выбора режима, вызывается команда AutoCAD. В командной реализации, мы гарантируем, что дерево обновится на основе режима, который был выбран. Мне бы хотелось, чтобы иметь галочку в контекстном меню рядом с текущим режимом, но в API нет способа это сделать в настоящее время и мы добавили это пожелание в wish-list для команды инженеров.

Вот соответствующий код, а полный проект примера можно скачать по ссылке ниже:

Код - C++: [Выделить]
  1. // Файл заголовка
  2. // TreeMultiModesGripPE.h
  3. #pragma once
  4. #include "dbMultiModesGrip.h"
  5. class AdskTreeMultiModesGripPE : public AcDbMultiModesGripPE
  6. {
  7. private:
  8.     static AcDbMultiModesGripPE::GripMode _currentGripMode;
  9.     static AcDbObjectId _lastModifiedEntId;
  10.  
  11. public:
  12.     ACRX_DECLARE_MEMBERS(AdskTreeMultiModesGripPE);
  13.  
  14.     AdskTreeMultiModesGripPE();
  15.     ~AdskTreeMultiModesGripPE();
  16.     static AcDbObjectId getLastModifiedEntId();
  17.  
  18.     virtual bool getGripModes(AcDbEntity* pThis,
  19.                               AcDbGripData* pGripData,
  20.                               AcArray<GripMode>& modes,
  21.                               unsigned int& curMode) const;
  22.  
  23.     virtual unsigned int mode(AcDbEntity* pThis,
  24.                               AcDbGripData* pGripData) const;
  25.  
  26.     virtual AcDbMultiModesGripPE::GripMode modeEx(
  27.                 AcDbEntity* pThis,
  28.                 AcDbGripData* pGripData) const;
  29.  
  30.     virtual bool setMode(
  31.                 AcDbEntity* pThis,
  32.                 AcDbGripData* pGripData,
  33.                 unsigned int newMode);
  34.  
  35.     virtual AcDbMultiModesGripPE::GripType gripType(
  36.             AcDbEntity* pThis, AcDbGripData* pGripData) const;
  37.  
  38.     virtual void reset(AcDbEntity* pThis);
  39. };
  40.  
  41.  
  42. // Файл реализации
  43. // TreeMultiModesGripPE.cpp
  44.  
  45. #include "StdAfx.h"
  46. #include "dbMultiModesGrip.h"
  47. #include "TreeMultiModesGripPE.h"
  48. #include "AdskTree.h"
  49.  
  50. ACRX_CONS_DEFINE_MEMBERS(AdskTreeMultiModesGripPE,
  51.                          AcDbMultiModesGripPE, 1);
  52.  
  53. AcDbMultiModesGripPE::GripMode
  54.                     AdskTreeMultiModesGripPE::_currentGripMode;
  55.  
  56. AcDbObjectId AdskTreeMultiModesGripPE::_lastModifiedEntId
  57.                                         = AcDbObjectId::kNull;
  58.  
  59. AdskTreeMultiModesGripPE::AdskTreeMultiModesGripPE()
  60. {
  61.     // Режим ручки по-умолчанию
  62.     _currentGripMode.Mode = 0;
  63.     _currentGripMode.DisplayString = AcString("Spring");
  64. }
  65.  
  66. AdskTreeMultiModesGripPE::~AdskTreeMultiModesGripPE()
  67. {
  68. }
  69.  
  70. // Возвращаем возможные режимы ручки
  71. bool AdskTreeMultiModesGripPE::getGripModes(
  72.                                 AcDbEntity* pThis,
  73.                                 AcDbGripData* pGripData,
  74.                                 AcArray<GripMode>& modes,
  75.                                 unsigned int& curMode) const
  76. {
  77.     GripMode gripMode1;
  78.     gripMode1.Mode = 0;
  79.     gripMode1.DisplayString = AcString("Spring");
  80.     gripMode1.ActionType = GripActionType::kCommand;
  81.     gripMode1.CommandString = AcString("ModeSwitchCmd ");
  82.  
  83.     modes.append(gripMode1);
  84.  
  85.     GripMode gripMode2;
  86.     gripMode2.Mode = 1;
  87.     gripMode2.DisplayString = AcString("Winter");
  88.     gripMode2.ActionType = GripActionType::kCommand;
  89.     gripMode2.CommandString = AcString("ModeSwitchCmd ");
  90.  
  91.     modes.append(gripMode2);
  92.  
  93.     curMode = 0;
  94.  
  95.     return true;
  96. }
  97.  
  98. // Получаем идентификатор текущего режима.
  99. unsigned int AdskTreeMultiModesGripPE::mode(
  100.                                 AcDbEntity* pThis,
  101.                                 AcDbGripData* pGripData) const
  102. {
  103.     return _currentGripMode.Mode;
  104. }
  105.  
  106. // Возвращаем текущий режим.
  107. AcDbMultiModesGripPE::GripMode
  108.     AdskTreeMultiModesGripPE::modeEx(
  109.             AcDbEntity* pThis, AcDbGripData* pGripData) const
  110. {
  111.     return _currentGripMode;
  112. }
  113.  
  114. // Устанавливаем текущий режим.
  115. bool AdskTreeMultiModesGripPE::setMode(
  116.             AcDbEntity* pThis,
  117.             AcDbGripData* pGripData,
  118.             unsigned int newMode)
  119. {
  120.     _currentGripMode.Mode = newMode;
  121.  
  122.     AcDbObjectId entId = pThis->id();
  123.     AdskTree *pTree = AdskTree::cast(pThis);
  124.  
  125.     switch(newMode)
  126.     {
  127.         case 0:
  128.             acutPrintf(ACRX_T("\nВесна, листочки растут!"));
  129.  
  130.             _currentGripMode.DisplayString = AcString("Spring");
  131.             pTree->setSeason(AcString("Spring"));
  132.             // Для обновления графики
  133.             _lastModifiedEntId = pTree->id();
  134.  
  135.             break;
  136.  
  137.         case 1:
  138.             acutPrintf(ACRX_T("\nЗима, листочки опадают!"));
  139.  
  140.             _currentGripMode.DisplayString = AcString("Winter");
  141.             pTree->setSeason(AcString("Winter"));
  142.             // Для обновления графики
  143.             _lastModifiedEntId = pTree->id();
  144.  
  145.             break;
  146.     }
  147.     return true;
  148. }
  149.  
  150. // Получаем тип ручки для заданной ручки.
  151. AcDbMultiModesGripPE::GripType
  152. AdskTreeMultiModesGripPE::gripType(
  153.             AcDbEntity* pThis, AcDbGripData* pGripData) const
  154. {
  155.     return AcDbMultiModesGripPE::GripType::kPrimary; 
  156. }
  157.  
  158. // Получаем objectId примитива дерево для
  159. // обновления графики
  160. AcDbObjectId AdskTreeMultiModesGripPE::getLastModifiedEntId()
  161. {
  162.     return _lastModifiedEntId;
  163. }
  164.  
  165. // Сбрасываем текущий режим в значение по-умолчанию
  166. void AdskTreeMultiModesGripPE::reset(AcDbEntity* pThis)
  167. {
  168.     _currentGripMode.Mode = 0;
  169.     _currentGripMode.DisplayString = AcString("Spring");
  170. }
  171.  
  172.  
  173.  
  174. // Файл заголовка собственного примитива
  175. // AsdkTree.h
  176.  
  177. #pragma once
  178.  
  179. #ifdef MULTIMODEGRIPSIMPLESAMPLE_MODULE
  180. #define DLLIMPEXP __declspec(dllexport)
  181. #else
  182. #define DLLIMPEXP
  183. #endif
  184.  
  185. //-----------------------------------------------------------------------------
  186. #include "dbmain.h"
  187.  
  188. //-----------------------------------------------------------------------------
  189. class DLLIMPEXP AdskTree : public AcDbEntity
  190. {
  191.  
  192. public:
  193.     ACRX_DECLARE_MEMBERS(AdskTree) ;
  194.  
  195. protected:
  196.     static Adesk::UInt32 kCurrentVersionNumber ;
  197.  
  198. private:
  199.     AcGePoint3d _basePoint;
  200.     AcString _season;
  201.  
  202.     void BuildSubTree(
  203.         AcGeLineSeg3d *pMainBranch,
  204.         int level,
  205.         AcGiWorldDraw *mode,
  206.         Adesk::Boolean flower = Adesk::kFalse);
  207.  
  208. public:
  209.     AdskTree () ;
  210.     virtual ~AdskTree () ;
  211.  
  212.     // Sets the season status
  213.     void setSeason(AcString season);
  214.  
  215.     // Sets the insertion point
  216.     void setBasePoint(AcGePoint3d basePoint);
  217.  
  218.     //----- AcDbObject protocols
  219.     //- Dwg Filing protocol
  220.     virtual Acad::ErrorStatus
  221.                     dwgOutFields (AcDbDwgFiler *pFiler) const ;
  222.     virtual Acad::ErrorStatus
  223.                         dwgInFields (AcDbDwgFiler *pFiler) ;
  224.  
  225.     //----- AcDbEntity protocols
  226.     //- Graphics protocol
  227. protected:
  228.     virtual Adesk::Boolean subWorldDraw (AcGiWorldDraw *mode) ;
  229.     virtual Acad::ErrorStatus
  230.                     subTransformBy(const AcGeMatrix3d& xform);
  231.  
  232.     //- Grip points protocol
  233.     virtual Acad::ErrorStatus subGetGripPoints (
  234.                                 AcDbGripDataPtrArray &grips,
  235.                                 const double curViewUnitSize,
  236.                                 const int gripSize,
  237.                                 const AcGeVector3d &curViewDir,
  238.                                 const int bitflags) const ;
  239.  
  240.     virtual Acad::ErrorStatus subMoveGripPointsAt (
  241.         const AcDbVoidPtrArray &gripAppData,
  242.         const AcGeVector3d &offset, const int bitflags) ;
  243. };
  244.  
  245. #ifdef MULTIMODEGRIPSIMPLESAMPLE_MODULE
  246. ACDB_REGISTER_OBJECT_ENTRY_AUTO(AdskTree)
  247. #endif
  248.  
  249.  
  250. // Файл реализация собственного примитива
  251. // AdskTree.cpp
  252.  
  253. #include "StdAfx.h"
  254. #include "AdskTree.h"
  255.  
  256. Adesk::UInt32 AdskTree::kCurrentVersionNumber =1 ;
  257.  
  258. ACRX_DXF_DEFINE_MEMBERS (
  259.     AdskTree, AcDbEntity,
  260.     AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,
  261.     AcDbProxyEntity::kNoOperation, ADSKTREE,
  262. ADSKMULTIMODEGRIPSIMPLESAMPLEAPP
  263. |Product Desc:     A description for your object
  264. |Company:          Your company name
  265. |WEB Address:      Your company WEB site address
  266. )
  267.  
  268. AdskTree::AdskTree () : AcDbEntity ()
  269. {
  270.     _basePoint = AcGePoint3d::kOrigin;
  271.     _season = AcString("Spring");
  272. }
  273.  
  274. AdskTree::~AdskTree ()
  275. {
  276. }
  277.  
  278. //----- AcDbObject protocols
  279. //- Dwg Filing protocol
  280. Acad::ErrorStatus AdskTree::dwgOutFields(AcDbDwgFiler *pFiler)
  281.                                                     const {
  282.     assertReadEnabled () ;
  283.     //----- Save parent class information first.
  284.     Acad::ErrorStatus es =AcDbEntity::dwgOutFields (pFiler) ;
  285.     if ( es != Acad::eOk )
  286.         return (es) ;
  287.     //----- Object version number needs to be saved first
  288.     if ( (es =pFiler->writeUInt32
  289.             (AdskTree::kCurrentVersionNumber)) != Acad::eOk )
  290.         return (es) ;
  291.  
  292.     //----- Output params
  293.     pFiler->writePoint3d(_basePoint);
  294.  
  295.     return (pFiler->filerStatus ()) ;
  296. }
  297.  
  298. Acad::ErrorStatus AdskTree::dwgInFields(AcDbDwgFiler *pFiler)
  299. {
  300.     assertWriteEnabled () ;
  301.     //----- Read parent class information first.
  302.     Acad::ErrorStatus es =AcDbEntity::dwgInFields (pFiler) ;
  303.     if ( es != Acad::eOk )
  304.         return (es) ;
  305.     //----- Object version number needs to be read first
  306.     Adesk::UInt32 version =0 ;
  307.     if ( (es =pFiler->readUInt32 (&version)) != Acad::eOk )
  308.         return (es) ;
  309.     if ( version > AdskTree::kCurrentVersionNumber )
  310.         return (Acad::eMakeMeProxy) ;
  311.  
  312.     //----- Read params
  313.     pFiler->readPoint3d(&_basePoint);
  314.  
  315.     return (pFiler->filerStatus ()) ;
  316. }
  317.  
  318.  
  319. //----- AcDbEntity protocols
  320. Adesk::Boolean AdskTree::subWorldDraw (AcGiWorldDraw *mode)
  321. {
  322.     assertReadEnabled () ;
  323.  
  324.     AcGeLineSeg3d mainBranch(
  325.         _basePoint,
  326.         AcGePoint3d(_basePoint.x,_basePoint.y+10.0,_basePoint.z));
  327.  
  328.     AcDbLine *pLine1 = new AcDbLine(
  329.             mainBranch.startPoint(), mainBranch.endPoint());
  330.     mode->geometry().draw(pLine1);
  331.     delete pLine1;
  332.  
  333.     int level = 0;
  334.     BuildSubTree(&mainBranch, level, mode);
  335.  
  336.     return (AcDbEntity::subWorldDraw (mode)) ;
  337. }
  338.  
  339. void AdskTree::setBasePoint(AcGePoint3d basePoint)
  340. {
  341.     _basePoint = basePoint;
  342. }
  343.  
  344. void AdskTree::setSeason(AcString season)
  345. {
  346.     _season = season;
  347. }
  348.  
  349. void AdskTree::BuildSubTree(AcGeLineSeg3d *pMainBranch,
  350.                             int level,
  351.                             AcGiWorldDraw *mode,
  352.                             Adesk::Boolean flower)
  353. {
  354.     if(mode->isDragging() && level >= 2)
  355.         return; // Облегчаем для перетаскивания
  356.  
  357.     if(level >= 3)
  358.     {
  359.         if(_season == AcString("Spring"))
  360.         {
  361.             AcDbCircle *pLeaf = new AcDbCircle(
  362.                 pMainBranch->endPoint(),
  363.                 AcGeVector3d::kZAxis,
  364.                 pMainBranch->length() * 0.2);
  365.  
  366.             if(flower)
  367.                 pLeaf->setColorIndex(1);
  368.             else
  369.                 pLeaf->setColorIndex(2);
  370.             mode->geometry().draw(pLeaf);
  371.             delete pLeaf;
  372.         }
  373.         return;
  374.     }
  375.  
  376.     int subLevel = level + 1;
  377.     AcGePoint3d sp = AcGePoint3d::kOrigin;
  378.     AcGePoint3d ep = AcGePoint3d::kOrigin;
  379.     AcGeInterval intrvl;
  380.     pMainBranch->getInterval(intrvl, sp, ep);
  381.     double len = pMainBranch->length();
  382.  
  383.     AcGePoint3dArray pts;
  384.     pMainBranch->getSamplePoints(5, pts);
  385.  
  386.     const double PI = 3.1415926535897932385;
  387.     int cnt = 1;
  388.     if(level == 0)
  389.         cnt = 2;
  390.     for(;cnt < 5; cnt++)
  391.     {
  392.         AcGeVector3d dir = pMainBranch->direction().normalize();
  393.         AcGePoint3d refPt1 = pts[cnt];
  394.  
  395.         if(cnt == 4)
  396.         {
  397.             AcGePoint3d refPt2 = refPt1 + (len * 0.5) * dir;
  398.  
  399.             AcGeLineSeg3d branch1(refPt1, refPt2);
  400.             AcDbLine *pBranchLine1 = new AcDbLine(refPt1, refPt2);
  401.             mode->geometry().draw(pBranchLine1);
  402.             delete pBranchLine1;
  403.             BuildSubTree(&branch1, subLevel, mode, Adesk::kTrue);
  404.         }
  405.         else
  406.         {
  407.             AcGePoint3d refPt2 = refPt1 +
  408.                 (len * 0.5) * dir.transformBy(
  409.                 AcGeMatrix3d::rotation(    PI * 0.25,
  410.                                         AcGeVector3d::kZAxis,
  411.                                         refPt1
  412.                                        ));
  413.  
  414.             AcGeLineSeg3d branch1(refPt1, refPt2);
  415.             AcDbLine *pBranchLine1 = new AcDbLine(refPt1, refPt2);
  416.             mode->geometry().draw(pBranchLine1);
  417.             delete pBranchLine1;
  418.             BuildSubTree(&branch1, subLevel, mode);
  419.  
  420.             dir = pMainBranch->direction().normalize();
  421.             refPt2 = refPt1 + (len * 0.5) *
  422.                 dir.transformBy(AcGeMatrix3d::rotation(
  423.                 -PI * 0.25, AcGeVector3d::kZAxis, refPt1));
  424.  
  425.             AcGeLineSeg3d branch2(refPt1, refPt2);
  426.             AcDbLine *pBranchLine2 = new AcDbLine(refPt1, refPt2);
  427.             mode->geometry().draw(pBranchLine2);
  428.             delete pBranchLine2;
  429.             BuildSubTree(&branch2, subLevel, mode);
  430.         }
  431.     }
  432. }
  433.  
  434. Acad::ErrorStatus AdskTree::subGetGripPoints (
  435.     AcDbGripDataPtrArray &grips,
  436.     const double curViewUnitSize,
  437.     const int gripSize, 
  438.     const AcGeVector3d &curViewDir,
  439.     const int bitflags ) const
  440. {
  441.     assertReadEnabled () ;
  442.  
  443.     AcDbGripData *pGripData = new AcDbGripData();
  444.     pGripData->setGripPoint(_basePoint);
  445.     grips.append(pGripData);
  446.  
  447.     return Acad::eOk;
  448. }
  449.  
  450. Acad::ErrorStatus AdskTree::subMoveGripPointsAt (
  451.     const AcDbVoidPtrArray &gripAppData,
  452.     const AcGeVector3d &offset,
  453.     const int bitflags)
  454. {
  455.     assertWriteEnabled () ;
  456.  
  457.     _basePoint += offset;
  458.  
  459.     return Acad::eOk;
  460. }
  461.  
  462. Acad::ErrorStatus AdskTree::subTransformBy(
  463.                                     const AcGeMatrix3d& xform)
  464. {
  465.     assertWriteEnabled();
  466.     _basePoint.transformBy(xform);
  467.     return (AcDbEntity::subTransformBy(xform));
  468. }
  469.  
  470.  
  471.  
  472. // Использование
  473. // acrxEntryPoint.cpp
  474.  
  475. #include "resource.h"
  476. #include "AdskTree.h"
  477.  
  478. #include "stdafx.h"
  479. #include "dbMultiModesGrip.h"
  480. #include "TreeMultiModesGripPE.h"
  481.  
  482. static AdskTreeMultiModesGripPE *pMyMultiModeGrips = NULL;
  483.  
  484. #define szRDS _RXST("Adsk")
  485.  
  486. //----- ObjectARX EntryPoint
  487. class CMultiModeGripSimpleSampleApp : public AcRxArxApp {
  488.  
  489. public:
  490.     CMultiModeGripSimpleSampleApp () : AcRxArxApp () {}
  491.  
  492.     virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
  493.         // TODO: Load dependencies here
  494.  
  495.         // You *must* call On_kInitAppMsg here
  496.         AcRx::AppRetCode retCode
  497.                             =AcRxArxApp::On_kInitAppMsg(pkt) ;
  498.  
  499.         AdskTreeMultiModesGripPE::rxInit();
  500.         AdskTree::rxInit();
  501.         acrxBuildClassHierarchy();
  502.  
  503.         // TODO: Add your initialization code here
  504.         if(pMyMultiModeGrips == NULL)
  505.         {
  506.             pMyMultiModeGrips = new AdskTreeMultiModesGripPE();
  507.             AdskTree::desc()->addX(
  508.                                 AcDbMultiModesGripPE::desc(),
  509.                                 pMyMultiModeGrips);
  510.         }
  511.  
  512.         return (retCode) ;
  513.     }
  514.  
  515.     virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
  516.         // TODO: Add your code here
  517.  
  518.         // You *must* call On_kUnloadAppMsg here
  519.         AcRx::AppRetCode retCode
  520.                         = AcRxArxApp::On_kUnloadAppMsg (pkt) ;
  521.  
  522.         // TODO: Unload dependencies here
  523.         if(pMyMultiModeGrips != NULL)
  524.         {
  525.             delete pMyMultiModeGrips;
  526.             pMyMultiModeGrips = NULL;
  527.         }
  528.         return (retCode) ;
  529.     }
  530.  
  531.     virtual void RegisterServerComponents () {
  532.     }
  533.  
  534.  
  535.     // "Tree" – команда для создания дерева
  536.     static void AdskMultiModeGripSimpleSampleTREE(void)
  537.     {
  538.         ads_point pt;
  539.         if (RTNORM != acedGetPoint(
  540.                     NULL, L"\nУкажите базовую точку для дерева: ", pt))
  541.             return;
  542.  
  543.         AcGePoint3d insertionPt = asPnt3d( pt );
  544.  
  545.         AdskTree *pTree = new AdskTree();
  546.         pTree->setDatabaseDefaults();
  547.         pTree->setBasePoint(insertionPt);
  548.         PostToDb(pTree);
  549.     }
  550.  
  551.     // Добавление примитива к DB
  552.     static Acad::ErrorStatus PostToDb(AcDbEntity* pEnt)
  553.     {
  554.         AcDbDatabase *pDb
  555.             = acdbHostApplicationServices()->workingDatabase();
  556.         AcDbObjectId objId;
  557.  
  558.         Acad::ErrorStatus      es;
  559.         AcDbBlockTable*        pBlockTable;
  560.         AcDbBlockTableRecord*  pSpaceRecord;
  561.  
  562.         pDb->getBlockTable(pBlockTable, AcDb::kForRead);
  563.         pBlockTable->getAt( ACDB_MODEL_SPACE,
  564.                             pSpaceRecord,
  565.                             AcDb::kForWrite);
  566.         es = pSpaceRecord->appendAcDbEntity(objId, pEnt);
  567.         es = pEnt->close();
  568.         es = pSpaceRecord->close();
  569.         es = pBlockTable->close();
  570.  
  571.         return es;
  572.     }
  573.  
  574.     // Команда для обновления графики при изменении режима ручки
  575.     // Она необходима для синхронизации графики с выбранным режимом
  576.     static void AdskMultiModeGripSimpleSampleModeSwitchCmd(void)
  577.     {
  578.         AcDbObjectId entId
  579.             = AdskTreeMultiModesGripPE::getLastModifiedEntId();
  580.  
  581.         AcApDocument *pActiveDoc
  582.                         = acDocManager->mdiActiveDocument();
  583.         AcDbDatabase *pDb = pActiveDoc->database();
  584.  
  585.         if(entId.isNull())
  586.             return;
  587.  
  588.         AcDbEntity* pEnt = NULL;
  589.         acdbOpenAcDbEntity(pEnt, entId, AcDb::kForWrite);
  590.         pEnt->recordGraphicsModified();
  591.         pEnt->close();
  592.         acedUpdateDisplay();
  593.     }
  594. } ;
  595.  
  596. //-----------------------------------------------------------------------------
  597. IMPLEMENT_ARX_ENTRYPOINT(CMultiModeGripSimpleSampleApp)
  598.  
  599. ACED_ARXCOMMAND_ENTRY_AUTO(CMultiModeGripSimpleSampleApp,
  600.                            AdskMultiModeGripSimpleSample,
  601.                            TREE,
  602.                            TREE,
  603.                            ACRX_CMD_TRANSPARENT,
  604.                            NULL)
  605. ACED_ARXCOMMAND_ENTRY_AUTO(CMultiModeGripSimpleSampleApp,
  606.                            AdskMultiModeGripSimpleSample,
  607.                            ModeSwitchCmd,
  608.                            ModeSwitchCmd,
  609.                            ACRX_CMD_TRANSPARENT,
  610.                            NULL)

Загрузить MultiModeGrip_SimpleSample

А вот и картинка собственного примитива «дерева» в двух режимах:

 

Источник: http://adndevblog.typepad.com/autocad/2013/12/grip-context-menu-using-acdbmultimodesgrippe.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=453

Опубликовано 13.01.2014
Отредактировано 13.01.2014 в 04:04:44