Как пользоваться функцией acedCommandC

Автор Тема: Как пользоваться функцией acedCommandC  (Прочитано 9526 раз)

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

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

  • ADN OPEN
  • Сообщений: 45
  • Карма: 0
Здравствуйте!
Как правильно пользоваться функцией acedCommandC?

Перевожу программу на AutoCAD 2015
По возможности заменил функции acedCommand на acedCommandS и acedCmdS, но в нескольких случаях необходим
ввод данных пользователем, поэтому альтернативы команде acedCommandC нет.
Требуется чтобы пользователь видел объект в процессе перемещения, поворота или вставки в определенную точку.


Проблема в том, что acedCommandC правильно выполняется только в случае
1) если acedCommandC одна единственная. Все последующие вызовы acedCommandC  игнорируются.
2) если acedCommandC самая последняя в исполняемой функции. AutoCAD не дожидается завершения
ввода пользователем, программа выполняется дальше. В связи с этим программа выполняется или неправильно
(поскольку пользователь еще не ввел данные) или вылетает со сбоем AutoCAD (поскольку отсутствуют данные
которые должен был ввести пользователь).

Для отладки, добавил в программу вывод промежуточных строк. Функция обратного вызова (для
первой функции acedCommandC) запрашивается только после того, как завершилось выполнение
команды из которой вызывалась acedCommandC.
При этом если в команде имеется несколько функций acedCommandC - все кроме первой проигнорированы,
как будто их вообще в программе не было.
При этом совершенно безразлично, вызывается acedCommandC из одной функции или из нескольких,
вызывается только первая.


Как сделать, чтобы AutoCAD дожидался завершения ввода пользователем в acedCommandC и только после этого
переходил к выполнению следующей в программе команды???

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как пользоваться функцией acedCommandC
« Ответ #1 : 21-11-2016, 01:30:20 »
но в нескольких случаях необходим
ввод данных пользователем, поэтому альтернативы команде acedCommandC нет.
1. Альтернатива есть всегда! Советую напрочь отказаться от acedCmdX/acedCommandX. В данном случае нужно воспользоваться AcEdJig для позиционирования, поворота, масштабирования и т.д.
2. После запуска acedCommandC весь остальной код функции должен выполнятся в функции обратного вызова после завершения команды - только так можно добиться синхронности.
Вот пример, когда последовательно запускаются три команды (_PLINE, _3DPOLY, _ARC):

Код - C++ [Выбрать]
  1. //-----------------------------------------------------------------------------
  2. //----- acrxEntryPoint.cpp
  3. //-----------------------------------------------------------------------------
  4. #include "StdAfx.h"
  5. #include "resource.h"
  6. #include "acedCmdNF.h "
  7.  
  8. //-----------------------------------------------------------------------------
  9. #define szRDS _RXST("")
  10.  
  11. //-----------------------------------------------------------------------------
  12. //----- ObjectARX EntryPoint
  13. class CTestCommandCApp : public AcRxArxApp {
  14. public:
  15.   CTestCommandCApp() : AcRxArxApp() {}
  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.   static Adesk::Boolean isCommandActive(const ACHAR *cmd)
  29.   {
  30.     struct resbuf rb;
  31.     acedGetVar(L"CMDNAMES", &rb);
  32.     if (wcsstr(rb.resval.rstring, cmd))
  33.       return Adesk::kTrue;
  34.     return Adesk::kFalse;
  35.   }
  36.   // Функция обратного вызова
  37.   static int MyCallback(void *pData)
  38.   {
  39.     ACHAR *cmd = static_cast<ACHAR *>(pData);
  40.  
  41.     if (acedCmdCWasCancelled())
  42.     {
  43.       acutPrintf(L"\nКоманда %s прервана...", cmd);
  44.       return 0;
  45.     }
  46.     if (isCommandActive(cmd))
  47.     {
  48.       int res = acedCommandC(&MyCallback, pData, RTSTR, PAUSE, RTNONE);
  49.       acedCallBackOnCancel();
  50.       acutPrintf(L"\nMyPlineCallback: Команда %s активна. res=%d", cmd, res);
  51.       return 1;
  52.     }
  53.     CommandIsDone(cmd);
  54.     if (wcsstr(L"PLINE", cmd)) {
  55.       // Теперь можно запустить вторую команду
  56.       acedCommandC(&MyCallback, L"3DPOLY", RTSTR, L"_.3DPOLY", RTSTR, PAUSE, RTNONE);
  57.     }
  58.     else if (wcsstr(L"3DPOLY", cmd)) {
  59.       // Теперь можно запустить третью команду
  60.       acedCommandC(&MyCallback, L"ARC", RTSTR, L"_.ARC", RTSTR, PAUSE, RTNONE);
  61.     }
  62.     return 0;
  63.   }
  64.  
  65.   static void CommandIsDone(const ACHAR *cmd)
  66.   {
  67.     acutPrintf(L"\nКоманда %s завершена...", cmd);
  68.   }
  69.   static void RivilisMyCommand() {
  70.     acedCommandC(&MyCallback, L"PLINE", RTSTR, L"_.PLINE", RTSTR, PAUSE, RTNONE);
  71.   }
  72.  
  73. };
  74.  
  75. //-----------------------------------------------------------------------------
  76. IMPLEMENT_ARX_ENTRYPOINT(CTestCommandCApp)
  77.  
  78. ACED_ARXCOMMAND_ENTRY_AUTO(CTestCommandCApp, Rivilis, MyCommand, MyCommand, ACRX_CMD_MODAL, NULL)

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

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

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

  • ADN OPEN
  • Сообщений: 45
  • Карма: 0
Re: Как пользоваться функцией acedCommandC
« Ответ #2 : 21-11-2016, 20:41:50 »
Спасибо за пример кода.

Попробовал добавить в код  2 строки, чтобы видеть как выполняется команда

Код - C++ [Выбрать]
  1.   static void asdkSimpleToolPalette_RRR() {
  2.         acutPrintf(_T(">>> Начало команды\n\r"));
  3.         acedCommandC(&MyCallback, L"PLINE", RTSTR, L"_.PLINE", RTSTR, PAUSE, RTNONE);
  4.         acutPrintf(_T(">>> Конец команды\n\r"));
  5.   }
  6.  

Ниже результат -  программа проходит не останавливаясь до конца и только потом вызывается функция обратного вызова,
в которой вызывается первая функция - _.PLINE

Command: RRR
>>> Начало команды
>>> Конец команды
_.PLINE
Specify start point:
Current line-width is 0.0000

Если после вызова acedCommandC был бы текст программы, который должен использовать результаты введенных пользователем
данных - программа выполнилась бы некорректно.

Можно ли сделать, чтобы сначала завершалась функция acedCommandC, в которой выполняется  _PLINE, _3DPOLY, _ARC
и только после завершения команды  acedCommandC выполнялась следующая функция -  acutPrintf(_T(">>> Конец команды\n\r"));

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как пользоваться функцией acedCommandC
« Ответ #3 : 21-11-2016, 20:46:15 »
Ниже результат -  программа проходит не останавливаясь до конца и только потом вызывается функция обратного вызова,
в которой вызывается первая функция - _.PLINE
Так и должно быть - команда выполняется асинхронно.
Если после вызова acedCommandC был бы текст программы, который должен использовать результаты введенных пользователем
данных - программа выполнилась бы некорректно.
Да. Безусловно.
Можно ли сделать, чтобы сначала завершались функция acedCommandC, в которой выполняется  _PLINE, _3DPOLY, _ARC
и только после завершения команды  acedCommandC выполнялась следующая функция -  acutPrintf(_T(">>> Конец команды\n\r"));
Да. В единственном случае - если бы этот код был не там, где он у тебя, а в функции обратного вызова, о чем я уже писал выше:
2. После запуска acedCommandC весь остальной код функции должен выполнятся в функции обратного вызова после завершения команды - только так можно добиться синхронности.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 45
  • Карма: 0
Re: Как пользоваться функцией acedCommandC
« Ответ #4 : 22-11-2016, 02:21:39 »
Да уж, печально...
Не удивительно, что по использованию функции acedCommandC уже несколько лет практически отсутствует информация.
Разработчики постарались сделать функцию наиболее неудобной в использовании и им это удалось...
Разработчики писали, что функцию изменили чтобы она стала более надежной,
но похоже, что после ее "совершенствования" ее вообще никто не использует...

Попробую вписаться в указанные ограничения.

Спасибо

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Как пользоваться функцией acedCommandC
« Ответ #5 : 22-11-2016, 09:31:58 »
Вот еще один пример использования данной функции:
https://github.com/ADN-DevTech/AutoCAD-SendCommand/blob/master/ADNLongbowDemo%20-%202015/ADNLongbowDemo2015/acrxEntryPoint.cpp
От себя я могу сказать, что использовать acedCommandX следует только в случаях, когда невозможно написать свой аналог команды, что бывает достаточно редко. Всё, о чем шла речь в первом сообщение, прекрасно вписывается в концепцию AcEdJig.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 45
  • Карма: 0
Re: Как пользоваться функцией acedCommandC
« Ответ #6 : 23-11-2016, 01:51:47 »
Спасибо за ссылку и помощь.
AcEdJig обязательно посмотрю.