Как заменить стандартную команду своей?

Автор Тема: Как заменить стандартную команду своей?  (Прочитано 6531 раз)

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

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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Здравствуйте!
Вроде довольно простой, казалось бы, вопрос. Есть даже специальная команда "_Undefine". И в LISP есть такая возможность, насколько я помню. А вот в .NET что-то я не нашёл сходу этой возможности! Гугл выдал такой результат: http://through-the-interface.typepad.com/through_the_interface/2007/03/replacing_the_o.html. Но это же просто использование команды! Неужели нет в NET.API встроенных средств для этого?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Многое зависит от того, что это за команда. Пример:

Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5.  
  6. [assembly: ExtensionApplication(typeof(Rivilis.RefEditSubst))]
  7. [assembly: CommandClass(typeof(Rivilis.RefEditSubst))]
  8.  
  9. namespace Rivilis
  10. {
  11.     public class RefEditSubst : IExtensionApplication
  12.     {
  13.         void IExtensionApplication.Initialize()
  14.         {
  15.             // Preloading AutoCAD RefEdit command arx-file
  16.             SystemObjects.DynamicLinker.LoadModule("AcRefEd.arx", false, false);
  17.         }
  18.  
  19.         void IExtensionApplication.Terminate()
  20.         {
  21.             // Do plug-in application clean up here
  22.         }
  23.  
  24.         //------------------------------------------------
  25.         //     Command group MUST be "ACAD_MAIN"
  26.         //------------------------------------------------
  27.  
  28.         [CommandMethod("ACAD_MAIN", "RefEdit", CommandFlags.UsePickSet)]
  29.         public void RefEdit() // This method can have any name
  30.         {
  31.             Document doc = Application.DocumentManager.MdiActiveDocument;
  32.             Editor ed = doc.Editor;
  33.             ed.WriteMessage("MyRefEdit..");
  34.             if (doc.Name.Contains("Test"))
  35.             {
  36.                 ed.WriteMessage("selected ref..");
  37.             }
  38.             else
  39.             {
  40.                 doc.SendStringToExecute("_ACAD_REFEDIT.REFEDIT ", true, false, false);
  41.             }
  42.         }
  43.     }
  44. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Т.е., я правильно понял, что достаточно просто своей команде дать имя стандартной и она её заменит?
Многое зависит от того, что это за команда.
Да всё та же: AECOBJECTVIEWER

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Т.е., я правильно понял, что достаточно просто своей команде дать имя стандартной и она её заменит?
Нужна пара условий:
1. Соответствующий arx/dll-файл, стандартной команды должен быть загружен до определения своей команды (т.е. в методе Initialize)
2. Группа твоей команды должна совпадать с группой стандартной команды. Я проверял в C3D 2016:
Код - INI [Выбрать]
  1. Команда: ARX
  2. Задайте параметр [Файлы/Группы/Команды/кЛассы/Службы/Загрузить/Выгрузить]: К
  3. Какие команды вывести <*>: aecobj*
  4. Команды, зарегистрированные модулями ARX:
  5. Группа команд 'AecUtilities70'
  6.     AECOBJECTDISPLAY, OBJECTDISPLAY
  7.     AECOBJECTVIEWER, OBJECTVIEWER
Т.е. группа: AecUtilities70
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Вот это подарок! Спасибо большое!

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Вот это подарок! Спасибо большое!
Ты сначала проверь. Возможно не всё так просто.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Пока не получается:
Не удалось загрузить сборку. Сведения об ошибке: Autodesk.AutoCAD.Runtime.Exception: eDuplicateKey
   в Autodesk.AutoCAD.Runtime.CommandClass.AddCommand(ICommandLineCallable ca, MethodInfo mi)
   в Autodesk.AutoCAD.ApplicationServices.AutoCADApplicationHolder.Initialize(Assembly assembly)
   в Autodesk.AutoCAD.ApplicationServices.ExtensionLoader.ProcessAssembly(Assembly assembly)
Пробую вот так:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.EditorInput;
  3. using Autodesk.AutoCAD.Runtime;
  4.  
  5. namespace Rivilis
  6. {
  7.     public class RefEditSubst : IExtensionApplication
  8.     {
  9.         void IExtensionApplication.Initialize()
  10.         {
  11.             SystemObjects.DynamicLinker.LoadModule("AecUtilities.arx", false, false);
  12.         }
  13.  
  14.         void IExtensionApplication.Terminate()
  15.         {
  16.             // Do plug-in application clean up here
  17.         }
  18.        
  19.         [CommandMethod("AECUTILITIES70", "AECOBJECTVIEWER", CommandFlags.UsePickSet)]
  20.         public void RunCmd() // This method can have any name
  21.         {
  22.             Document doc = Application.DocumentManager.MdiActiveDocument;
  23.             Editor ed = doc.Editor;
  24.             Application.ShowAlertDialog("It's my command!");          
  25.         }
  26.     }
  27. }
Здесь используется имя "AECOBJECTVIEWER", я пробовал и просто "OBJECTVIEWER" - результат тот же.

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

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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Отладка не ловит эту ошибку. Initialize отрабатывает без ошибок. Я так понимаю, что DLL пытается зарегистрировать команду, а Civil не даёт это сделать.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
С добавлением своей команды можно еще поиграться. Есть метод для динамического определения своей команды:
Код - C# [Выбрать]
  1. // Autodesk.AutoCAD.Internal.Utils
  2. public unsafe static void AddCommand(string cmdGroupName, string cmdGlobalName, string cmdLocalName, CommandFlags cmdFlags, CommandCallback func);
А так можно удалить зарегистрированную команду:
Код - C# [Выбрать]
  1. // Autodesk.AutoCAD.Internal.Utils
  2. public unsafe static void RemoveCommand(string cmdGroupName, string cmdGlobalName);
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Да, это то что нужно!  :) Вот так работает:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.Runtime;
  3.  
  4. namespace Rivilis
  5. {
  6.     public class RefEditSubst : IExtensionApplication
  7.     {
  8.         void IExtensionApplication.Initialize()
  9.         {
  10.             SystemObjects.DynamicLinker.LoadModule("AecUtilities.arx", false, false);
  11.             Autodesk.AutoCAD.Internal.Utils.RemoveCommand("AECUTILITIES70", "AECOBJECTVIEWER");
  12.         }
  13.  
  14.         void IExtensionApplication.Terminate()
  15.         {          
  16.         }
  17.        
  18.         [CommandMethod("OBJECTVIEWER", CommandFlags.UsePickSet)]
  19.         public void RunCmd()
  20.         {
  21.             Application.ShowAlertDialog("It's my command!");          
  22.         }
  23.     }
  24. }



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

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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Я хочу использовать стандартную, но перед этим мне надо передать свой набор объектов. С событиями никак не получается стабильной работы - то вылезает извечная проблема "Выполняется команда Enter прервать или Повтор", то сбрасывается предвыбор, то ещё какая-то беда. Вот придумал сделать свою команду, которая будет формировать набор, а потом запускать стандартную команду.

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

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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
М-да... Я думал, что этот метод действует аналогично Undefined, и я смогу вызвать стандартную команду с помощью подчёркивания и точки. Но нет, удаляет команду полностью. Хороший метод. И, в общем-то, задачу, озвученную в вопросе выполняет. Но работает не так как мне надо...

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Попробуй убрать
Код - C# [Выбрать]
  1. Autodesk.AutoCAD.Internal.Utils.RemoveCommand("AECUTILITIES70", "AECOBJECTVIEWER");
И вместо
Код - C# [Выбрать]
  1. [CommandMethod("AECUTILITIES70", "AECOBJECTVIEWER", CommandFlags.UsePickSet)]
поставить
Код - C# [Выбрать]
  1. [CommandMethod("ACAD_MAIN", "AECOBJECTVIEWER", CommandFlags.UsePickSet)]
Это только предположение.
Если сработает подмена команды, то через "_AECUTILITIES70.AECOBJECTVIEWER" можно будет запустить "родную" команду.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Попробовал ACAD_MAIN, и просто без указания пространства имён. Ошибки при загрузке DLL не возникает, но и команда не переопределяется. Точнее даже не команда, а действие по выбору пункта в контекстном меню. Если бы этот инструмент вызывался кнопкой на ленте, то сработало бы (посмотрел настройки в файле адаптации). А в контекстном меню, видимо, прописана команда с пространством имён.
Наверное, попробую в понедельник на свежую голову ещё повоевать с командными событиями, может удастся всё-таки через них сделать. Сейчас уже мозг отказывается работать...

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А в контекстном меню, видимо, прописана команда с пространством имён.
А вот это крайне мало вероятно. Она скорее всего прописана или как _AECOBJECTVIEWER или как _OBJECTVIEWER. ARXDBG тебе в руки. :-)
Проверил, что после _UNDEFINE OBJECTVIEWER из контекстного меню она на запускается (C3D 2016)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Дмитрий Загорулькин 19-02-2018, 01:25:53

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5. using Autodesk.AutoCAD.Internal;
  6.  
  7. [assembly: ExtensionApplication(typeof(Rivilis.MyObjectViewer))]
  8. [assembly: CommandClass(typeof(Rivilis.MyObjectViewer))]
  9.  
  10. namespace Rivilis
  11. {
  12.   public class MyObjectViewer : IExtensionApplication
  13.   {
  14.     void IExtensionApplication.Initialize()
  15.     {
  16.       // Preloading AecUtilities.arx
  17.       if (!Utils.IsCommandDefined("AecObjectViewer"))
  18.        SystemObjects.DynamicLinker.LoadModule("AecUtilities.arx", false, false);
  19.       Utils.AddCommand("ACAD_MAIN", "AecObjectViewer", "ObjectViewer", CommandFlags.UsePickSet | CommandFlags.Redraw, MyObjectViewerHandler);
  20.     }
  21.  
  22.     void IExtensionApplication.Terminate()
  23.     {
  24.       // Do plug-in application clean up here
  25.     }
  26.    
  27.     public static void MyObjectViewerHandler() // This method can have any name
  28.     {
  29.       Document doc = Application.DocumentManager.MdiActiveDocument;
  30.       Editor ed = doc.Editor;
  31.       ed.WriteMessage("\nMyObjectViewer..");
  32.       doc.SendStringToExecute("_AecUtilities70.AecObjectViewer ", true, false, false);
  33.     }
  34.   }
  35. }

А это результат выбора из контекстного меню:


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

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Да, действительно, Вам удалось его перехитрить!  :)
Проверил - отлично работает! Спасибо!

P.S. В продолжение темы: http://adn-cis.org/forum/index.php?topic=8319
« Последнее редактирование: 20-02-2018, 13:20:24 от Дмитрий Загорулькин »