Проблема с асинхронным вариантом вызова функции acedCommandC

Автор Тема: Проблема с асинхронным вариантом вызова функции acedCommandC  (Прочитано 14019 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн AlexZhurАвтор темы

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
Добрый вечер. Переношу проект с AutoCAD2002 на AutoCAD 2015. Подскажите пожалуйста как правильно переписать вариант вызова функции
 acedCommand(RTSTR, "_line", RTPOINT, asDblArray(firstPoint), RTSTR, PAUSE, RTSTR, "", 0), требующей интерактивного ввода второй точки (после ввода которой в моем случае команда должна закончиться)  на асинхронный вариант с помощью функции acedCommandC.
« Последнее редактирование: 08-03-2017, 00:01:58 от AlexZ »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexZhurАвтор темы

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
Я уже перепробовал множество вариантов, AutoCad постоянно вылетает, при этом  acedCommandС необходимо вызывать в моем случае в теле другой функции. Могли бы Вы написать пример кода с реализацией acedCommandC для моего случая (приведенного первоначального варианта acedCommand  с такими же параметрами)?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Вы написать пример кода с реализацией acedCommandC для моего случая?
Для какого случая? Если использовать acedCommandC, то весь дальнейший код должен выполняться в её callback-функции. Очень рекомендую отказаться от этой идеи.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexZhurАвтор темы

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
В моем случае  был вот такой код и все отлично работало
Код - C++ [Выбрать]
  1. if (acedCommand(RTSTR, "_line", RTPOINT, asDblArray(firstPoint), RTSTR, PAUSE, RTSTR, "", 0) == RTNORM)
  2.                 {
  3.                    
  4.          //получаем имя последнего отрисованного примитива,т.е. линии  
  5.                    acdbEntLast(name);
  6.                  //переходим от ads_name к AcDbObjectId
  7.            acdbGetObjectId(EntId,name);
  8.          //получаем указатель на примитив-линию
  9.                    acdbOpenAcDbEntity(pEnt,EntId,AcDb::kForRead);
  10.            //приводим указатель pEnt к типу AcDbLine
  11.                    secondPoint=AcDbLine::cast(pEnt)->endPoint();
  12.                    pEnt->close();
  13.            pEnt=NULL;
  14.         }
  15. else
  16.                 {.................... и т.п.    

 Какую альтернативу можно использовать или все-таки acedCommandC (если - да, то можно привести пример для моего случая?)
« Последнее редактирование: 08-03-2017, 16:19:46 от Александр Ривилис »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
1. Прочитай у меня в подписи по поводу правильного форматирования кода на форуме и соблюдай это правило.
2. Весь смысл этого кода в получении конечной точки отрезка? Почему было не воспользоваться acedGetPoint?
3. Такой код мог работать только до AutoCAD 2006. Начиная с 2007 строки нужно было передавать в unicode (т.е. L"_line" или ACRX_T("_line")).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Всё что у тебя написано может быть очень легко заменено на эту функцию без использования командных методов:
Код - C++ [Выбрать]
  1.   static void AddLine1() {
  2.     ads_point pp1, pp2;
  3.  
  4.     if (acedGetPoint(NULL, L"\nУкажите начальную точку отрезка", pp1) == RTNORM &&
  5.         acedGetPoint(pp1, L"\nУкажите конечную точку отрезка", pp2) == RTNORM)
  6.     {
  7.       AcGePoint3d pStart, pEnd;
  8.       acdbUcs2Wcs(pp1, asDblArray(pStart), false);
  9.       acdbUcs2Wcs(pp2, asDblArray(pEnd), false);
  10.       AcDbObjectPointer<AcDbLine> pLine; pLine.create();
  11.       pLine->setDatabaseDefaults();
  12.       pLine->setStartPoint(pStart); pLine->setEndPoint(pEnd);
  13.       AcDbBlockTableRecordPointer pSpace(acdbCurDwg()->currentSpaceId(), AcDb::kForWrite);
  14.       if (pSpace.openStatus() == Acad::eOk)
  15.         pSpace->appendAcDbEntity(pLine);
  16.     }
  17.   }

Тоже самое, но при помощи acedCommandC потребует создания callback-функции и весь остальной код после вызова команды нужно будет выполнять именно в этой callback-функции. Это будет очень сложно и неудобно. И понять логику работы такой программы будет почти невозможно. Поэтому acedCommandC следует использовать только тогда, когда никакие другие способы невозможны.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexZhurАвтор темы

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
 В моем случае команда используется для маркировки оборудования с помощью полки выноски:
пользователь "мышью" указывает начало линии выноски, затем начинает отрисовываться линия на курсоре и пользователь визуально видит где лучше задать вторую точку, чтобы потом добавить к ней полку. Т.е. в моем случае обязательно необходимо видеть направление отрисовки линии, до того, как будет указана вторая точка (к которой потом добавиться полка с маркировкой оборудования), чтобы выбрать оптимальное место на чертеже для полки выноски с обозначением оборудования. Вопрос - как оптимально это реализовать, без использования acedCommandC?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Вопрос - как оптимально это реализовать, без использования acedCommandC?
Тут два варианта:
1. Использовать как есть Addline1, а затем дорисовывать полку с текстом - самый простой способ:



2. Сделать полноценный класс на основе AcEdJig - можно будет сделать похоже на отрисовку мультивыноски - сложно, но всё-равно на порядок проще чем извращаться с acedCommandC
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexZhurАвтор темы

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
 Спасибо, Александр, за оперативную помощь! Первый вариант неплохой и менее трудоемкий. А можно как-то изменить цвет и стиль штрихпунктирной линии, которая временно отображается  после ввода первой точки?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
А можно как-то изменить цвет и стиль штрихпунктирной линии, которая временно отображается  после ввода первой точки?
Нет. Во всяком случае в последних версиях AutoCAD: https://knowledge.autodesk.com/support/autocad/troubleshooting/caas/sfdcarticles/sfdcarticles/How-to-disable-or-change-the-color-of-the-rubber-band-in-AutoCAD.html
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение AlexZhur 13-03-2017, 11:18:17

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Вот простейший пример с использованием AcEdJig:
Код - C++ [Выбрать]
  1. //-----------------------------------------------------------------------------
  2. //----- acrxEntryPoint.cpp
  3. //-----------------------------------------------------------------------------
  4. #include "StdAfx.h"
  5. #include "resource.h"
  6.  
  7. #define szRDS _RXST("")
  8.  
  9. //-----------------------------------------------------------------------------
  10. //----- ObjectARX EntryPoint
  11. class CAddLineApp : public AcRxArxApp {
  12.  
  13. public:
  14.   CAddLineApp() : AcRxArxApp() {}
  15.  
  16.   virtual AcRx::AppRetCode On_kInitAppMsg(void *pkt) {
  17.     AcRx::AppRetCode retCode = AcRxArxApp::On_kInitAppMsg(pkt);
  18.     return (retCode);
  19.   }
  20.  
  21.   virtual AcRx::AppRetCode On_kUnloadAppMsg(void *pkt) {
  22.     AcRx::AppRetCode retCode = AcRxArxApp::On_kUnloadAppMsg(pkt);
  23.     return (retCode);
  24.   }
  25.  
  26.   virtual void RegisterServerComponents() {     }
  27.  
  28.   class LineJig : public AcEdJig {
  29.   public:
  30.     AcGePoint3d pStartPoint;
  31.     AcGePoint3d pEndPoint;
  32.     AcDbLine *mpEntity;
  33.     AcString dispString;
  34.   public:
  35.     LineJig() : mpEntity(NULL) {};
  36.     ~LineJig() {};
  37.     DragStatus startJig()
  38.     {
  39.       setDispPrompt(dispString);
  40.       return drag();
  41.     }
  42.   protected:
  43.     virtual DragStatus sampler()  {  
  44.       return GetEndPoint();  
  45.     }
  46.     virtual Adesk::Boolean update() {  
  47.       mpEntity->setEndPoint(pEndPoint);
  48.       return true;  
  49.     }
  50.     virtual AcDbEntity *entity() const  {
  51.       return ((AcDbEntity *)mpEntity);  
  52.     }
  53.     AcEdJig::DragStatus GetEndPoint()
  54.     {
  55.       AcGePoint3d oldPnt = pEndPoint;
  56.       AcGePoint3d newPnt;
  57.  
  58.       AcEdJig::DragStatus status = acquirePoint(newPnt, oldPnt);
  59.       //- If valid input
  60.       if (status == AcEdJig::kNormal)
  61.       {
  62.         if (newPnt.isEqualTo(oldPnt))
  63.           return (AcEdJig::kNoChange);
  64.         pEndPoint = newPnt;
  65.       }
  66.       return (status);
  67.     }
  68.   };
  69.  
  70.   static void RivilisAddLine2() {
  71.     ads_point pp1;
  72.     AcGePoint3d pStart, pEnd;
  73.     if (acedGetPoint(NULL, L"\nУкажите начальную точку: ", pp1) == RTNORM)
  74.     {
  75.       acdbUcs2Wcs(pp1, asDblArray(pStart), false);
  76.       AcDbObjectPointer<AcDbLine> pLine; pLine.create();
  77.       pLine->setDatabaseDefaults();
  78.       pLine->setStartPoint(pStart); pLine->setEndPoint(pStart);
  79.       LineJig jig;
  80.       jig.mpEntity = pLine;
  81.       jig.pStartPoint = jig.pEndPoint = pStart;
  82.       jig.dispString = L"\nУкажите конечную точку: ";
  83.       if (jig.startJig() != AcEdJig::DragStatus::kNormal)
  84.         return;
  85.       pEnd = jig.pEndPoint; // Конечная точка отрезка
  86.       // Добавляем отрезок в чертеж
  87.       AcDbBlockTableRecordPointer pSpace(acdbCurDwg()->currentSpaceId(), AcDb::kForWrite);
  88.       if (pSpace.openStatus() == Acad::eOk)
  89.         pSpace->appendAcDbEntity(pLine);
  90.  
  91.     }
  92.   }
  93. };
  94.  
  95. //-----------------------------------------------------------------------------
  96. IMPLEMENT_ARX_ENTRYPOINT(CAddLineApp)
  97.  
  98. ACED_ARXCOMMAND_ENTRY_AUTO(CAddLineApp, Rivilis, AddLine2, AddLine2, ACRX_CMD_MODAL, NULL)

Так это будет выглядеть:



По большому счету в этот Jig можно было добавить и указание положения текста подписи (и соответственно полки), но это уже будет тебе "домашнее задание".


Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexZhurАвтор темы

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
 Отлично! Спасибо, Александр!!! Ваши ответы очень помогают в работе.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
AlexZ
Последний мой ответ можно считать Решением? Если да, то отметьте его.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AlexZhurАвтор темы

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
 В продолжение темы....
  Александр, могли бы Вы привести пример кода с использованием AcEdJig для вставки блока с атрибутами
(в старом проекте это было так: acedCommand(RTSTR, L"_insert", RTSTR,L"FAPR_DRCF",RTSTR,L"_Scale", RTSTR, L"100", RTSTR,  PAUSE,/*RT3DPOINT,ptInsBl,*/ RTSTR, PAUSE, RTSHORT, GetNumber()
/* атрибут */, RTSTR, GetType() /* атрибут */, RTSTR, GetMark() /* атрибут */, RTREAL, GetCCDM() /* атрибут */, RTREAL, GetCCAM() /* атрибут */, 0)), при этом точка вставки и угол поворота вводится пользователем, а блок перемещается на курсоре до момента ввода точки вставки и угла поворота соответственно. Буду Вам очень признателен.