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

12/11/2018

Как определить, что lisp-функцию можно вызвать из arx-приложения?

Основное документированное средство для вызова lisp-функций из arx-приложения – это функция acedInvoke. Для того, чтобы ею воспользоваться необходимо одно из двух условий:

  1. Функция имеет имя вида C:XXX, т.е. имя аналогичное тому, как используется в AutoLisp для определения команды AutoCAD.
  2. Функция зарегистрирована при помощи lisp-функции (vl-acad-defun ‘имя_функции)

Как можно определить, что хотя бы одно из этих условий выполняется? Ниже приведён подробно документированный код:

Код - C++: [Выделить]
  1. //////////////////////////////////////////////////////////////////////////
  2. // Функция проверяет можно ли вызвать lisp-функцию с заданным именем при
  3. // помощи acedInvoke. Такая функция должна или иметь имя в виде C:XXX,
  4. // или быть зарегистрированной при помощи (vl-acad-defun 'имя_функции)
  5. //////////////////////////////////////////////////////////////////////////
  6. static bool IsLispFuncRegisteredInDocument
  7. (
  8.   AcString funcName, // Имя проверяемой функции
  9.   AcApDocument *ap = curDoc() // Документ, в котором эта
  10.   // функция должна использоваться (по умолчанию текущий документ)
  11. )
  12. {
  13.   bool findFunc = false;
  14.   __int64 ptrCurDoc = __int64(ap);
  15.   AcEdCommandIterator* pCmdItr = NULL;
  16.   AcString cmdName, grpName;
  17.   if (NULL != (pCmdItr = acedRegCmds->iterator()))
  18.   {
  19.     for (;!pCmdItr->done() && !findFunc; pCmdItr->next())
  20.     {
  21.       grpName = pCmdItr->commandGroup();
  22.       cmdName = pCmdItr->command()->localName();
  23.       //////////////////////////////////////////////////////////////////////////
  24.       // Если имя группы имеет формат "*DOC(0xNNNNNNNNNNNNNNN)", то эта группа
  25.       // относится к документу. Чтобы определить к какому именно документу она
  26.       // относится достаточно вычленить шестнадцатеричную строку, преобразовать
  27.       // её в длинное целое и сравнить с адресом документа AcApDocument.
  28.       // В случае совпадения все команды и функции работают
  29.       // в пространстве именно этого документа.
  30.       //////////////////////////////////////////////////////////////////////////
  31.       if (grpName.left(7) == ACRX_T("*DOC(0x"))
  32.       {
  33.         __int64 ptrCmdDoc;
  34.         ACHAR *docStart = const_cast<ACHAR *>(grpName.kACharPtr() + 8), *docEnd = NULL;
  35.         // Преобразуем имя группы в длинное целое
  36.         ptrCmdDoc = _wcstoi64(docStart, &docEnd, 16);
  37.         // Сравниваем адрес переданного документа и адрес документа из имени группы
  38.         if (ptrCmdDoc == ptrCurDoc)
  39.         {
  40.           // Если это lisp-функция, то у неё флаг ACRX_CMD_DEFUN
  41.           Adesk::Int32 flag = pCmdItr->command()->commandFlags();
  42.           if ((flag & ACRX_CMD_DEFUN) && !funcName.compareNoCase(cmdName))
  43.           {
  44.             findFunc = true;
  45.             break;
  46.           }
  47.         }
  48.       }
  49.     }
  50.     delete pCmdItr;
  51.   }
  52.   return findFunc;
  53. }
  54. // Для проверки функции IsLispFuncRegisteredInDocument
  55. static void RivilisCheckRegLispFunc()
  56. {
  57.   AcString sName;
  58.   if (acedGetString(FALSE, ACRX_T("\nУкажите имя функции для проверки: "), sName) != RTNORM)
  59.     return;
  60.   if (sName.isEmpty())
  61.     return;
  62.   acutPrintf(ACRX_T("\n%s %sзарегистрирована для acedInvoke"),
  63.     sName.kACharPtr(), IsLispFuncRegisteredInDocument(sName, curDoc()) ? ACRX_T("") : ACRX_T("не "));
  64. }

 

Автор: Александр Ривилис

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

Опубликовано 12.11.2018
Отредактировано 12.11.2018 в 02:26:35