Вкладка на ленте (Ribbon) AutoCad средствами .Net (C#)

Автор Тема: Вкладка на ленте (Ribbon) AutoCad средствами .Net (C#)  (Прочитано 29501 раз)

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

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

  • ADN OPEN
  • Сообщений: 31
  • Карма: 0
Всем добрый день.
Столкнулся с проблемой реализации кода на C# в среде Visual Studio 2015 при создании библиотеке классов С# (.dll).
Данный код взят с сайта: «Хабрахабр»
Ссылка: https://habrahabr.ru/post/263373/
Тема: «Строим свою вкладку на ленте (Ribbon) AutoCad средствами .Net (C#)».

При сборке в Visual Studio 2015 кода ошибок нет.


Необходимые библиотеки для сборки подгружены:


При подключении к AutoCAD 2013 (x64) выводит ошибку.


Код - C# [Выбрать]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. // Acad
  6. using Autodesk.AutoCAD.Runtime;
  7. using Autodesk.AutoCAD.ApplicationServices;
  8. using Autodesk.Windows;
  9. using acadApp = Autodesk.AutoCAD.ApplicationServices.Application;
  10.  
  11. namespace ACadRibbon
  12. {
  13.     public class ExampleRibbon : IExtensionApplication
  14.     {
  15.         // Инициализация нашего плагина
  16.         public void Initialize()
  17.         {
  18.             /* ленту грузим с помощью обработчика событий:
  19.              * Этот вариант нужно использовать, если ваш плагин
  20.              * стоит в автозагрузке, т.к. он (плагин) инициализируется
  21.              * до построения ленты
  22.              */
  23.             //Autodesk.Windows.ComponentManager.ItemInitialized += new EventHandler(ComponentManager_ItemInitialized);
  24.             // Т.к. мы грузим плагин через NETLOAD, то строим вкладку в ленте сразу
  25.             BuildRibbonTab();
  26.         }
  27.         // Происходит при закрытии автокада
  28.         public void Terminate()
  29.         {
  30.             // Тут в принципе ничего не требуется делать
  31.         }
  32.         /* Обработчик события
  33.          * Следит за событиями изменения окна автокада.
  34.          * Используем его для того, чтобы "поймать" момент построения ленты,
  35.          * учитывая, что наш плагин уже инициализировался
  36.          */
  37.         void ComponentManager_ItemInitialized(object sender, Autodesk.Windows.RibbonItemEventArgs e)
  38.         {
  39.             // Проверяем, что лента загружена
  40.             if (Autodesk.Windows.ComponentManager.Ribbon != null)
  41.             {
  42.                 // Строим нашу вкладку
  43.                 BuildRibbonTab();
  44.                 //и раз уж лента запустилась, то отключаем обработчик событий
  45.                 Autodesk.Windows.ComponentManager.ItemInitialized -= new EventHandler <RibbonItemEventArgs> (ComponentManager_ItemInitialized);
  46.             }
  47.         }
  48.         // Построение вкладки
  49.         void BuildRibbonTab()
  50.         {
  51.             // Если лента еще не загружена
  52.             if (!isLoaded())
  53.             {
  54.                 // Строим вкладку
  55.                 CreateRibbonTab();
  56.                 // Подключаем обработчик событий изменения системных переменных
  57.                 acadApp.SystemVariableChanged += new SystemVariableChangedEventHandler(acadApp_SystemVariableChanged);
  58.             }
  59.         }
  60.         // Проверка "загруженности" ленты
  61.         bool isLoaded()
  62.         {
  63.             bool _loaded = false;
  64.             RibbonControl ribCntrl = Autodesk.Windows.ComponentManager.Ribbon;
  65.             // Делаем итерацию по вкладкам ленты
  66.             foreach (RibbonTab tab in ribCntrl.Tabs)
  67.             {
  68.                 // И если у вкладки совпадает идентификатор и заголовок, то значит вкладка загружена
  69.                 if (tab.Id.Equals("RibbonExample_ID") & tab.Title.Equals("RibbonExample"))
  70.                 { _loaded = true; break; }
  71.                 else _loaded = false;
  72.             }
  73.             return _loaded;
  74.         }
  75.         /* Удаление своей вкладки с ленты
  76.          * В данном примере не используем
  77.          */
  78.         void RemoveRibbonTab()
  79.         {
  80.             try
  81.             {
  82.                 RibbonControl ribCntrl = Autodesk.Windows.ComponentManager.Ribbon;
  83.                 // Делаем итерацию по вкладкам ленты
  84.                 foreach (RibbonTab tab in ribCntrl.Tabs)
  85.                 {
  86.                     if (tab.Id.Equals("RibbonExample_ID") & tab.Title.Equals("RibbonExample"))
  87.                     {
  88.                         // И если у вкладки совпадает идентификатор и заголовок, то удаляем эту вкладку
  89.                         ribCntrl.Tabs.Remove(tab);
  90.                         // Отключаем обработчик событий
  91.                         acadApp.SystemVariableChanged -= new SystemVariableChangedEventHandler(acadApp_SystemVariableChanged);
  92.                         // Останавливаем итерацию
  93.                         break;
  94.                     }
  95.                 }
  96.             }
  97.             catch (Autodesk.AutoCAD.Runtime.Exception ex)
  98.             {
  99.                 Autodesk.AutoCAD.ApplicationServices.Application.
  100.                   DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.Message);
  101.             }
  102.         }
  103.         /* Обработка события изменения системной переменной
  104.          * Будем следить за системной переменной WSCURRENT (текущее рабочее пространство),
  105.          * чтобы наша вкладка не "терялась" при изменение рабочего пространства
  106.          */
  107.         void acadApp_SystemVariableChanged(object sender, SystemVariableChangedEventArgs e)
  108.         {
  109.             if (e.Name.Equals("WSCURRENT")) BuildRibbonTab();
  110.         }
  111.         // Создание нашей вкладки
  112.         void CreateRibbonTab()
  113.         {
  114.             try
  115.             {
  116.                 // Получаем доступ к ленте
  117.                 RibbonControl ribCntrl = Autodesk.Windows.ComponentManager.Ribbon;
  118.                 // добавляем свою вкладку
  119.                 RibbonTab ribTab = new RibbonTab();
  120.                 ribTab.Title = "RibbonExample"; // Заголовок вкладки
  121.                 ribTab.Id = "RibbonExample_ID"; // Идентификатор вкладки
  122.                 ribCntrl.Tabs.Add(ribTab); // Добавляем вкладку в ленту
  123.                 // добавляем содержимое в свою вкладку (одну панель)
  124.                 addExampleContent(ribTab);
  125.                 // Делаем вкладку активной (не желательно, ибо неудобно)
  126.                 //ribTab.IsActive = true;
  127.                 // Обновляем ленту (если делаете вкладку активной, то необязательно)
  128.                 ribCntrl.UpdateLayout();
  129.             }
  130.             catch (System.Exception ex)
  131.             {
  132.                 Autodesk.AutoCAD.ApplicationServices.Application.
  133.                   DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.Message);
  134.             }
  135.         }
  136.         // Строим новую панель в нашей вкладке
  137.         void addExampleContent(RibbonTab ribTab)
  138.         {
  139.             try
  140.             {
  141.                 // создаем panel source
  142.                 RibbonPanelSource ribSourcePanel = new RibbonPanelSource();
  143.                 ribSourcePanel.Title = "RibbonExample";
  144.                 // теперь саму панель
  145.                 RibbonPanel ribPanel = new RibbonPanel();
  146.                 ribPanel.Source = ribSourcePanel;
  147.                 ribTab.Panels.Add(ribPanel);
  148.                 // создаем пустую tooltip (всплывающая подсказка)
  149.                 RibbonToolTip tt;
  150.                 // создаем split button
  151.                 RibbonSplitButton risSplitBtn = new RibbonSplitButton();
  152.                 /* Для RibbonSplitButton ОБЯЗАТЕЛЬНО надо указать
  153.                  * свойство Text, а иначе при поиске команд в автокаде
  154.                  * будет вылетать ошибка.
  155.                  */
  156.                 risSplitBtn.Text = "RibbonSplitButton";
  157.                 // Ориентация кнопки
  158.                 risSplitBtn.Orientation = System.Windows.Controls.Orientation.Vertical;
  159.                 // Размер кнопки
  160.                 risSplitBtn.Size = RibbonItemSize.Large;
  161.                 // Показывать изображение
  162.                 risSplitBtn.ShowImage = true;
  163.                 // Показывать текст
  164.                 risSplitBtn.ShowText = true;
  165.                 // Стиль кнопки
  166.                 risSplitBtn.ListButtonStyle = Autodesk.Private.Windows.RibbonListButtonStyle.SplitButton;
  167.                 risSplitBtn.ResizeStyle = RibbonItemResizeStyles.NoResize;
  168.                 risSplitBtn.ListStyle = RibbonSplitButtonListStyle.List;
  169.                 /* Далее создаем две кнопки и добавляем их
  170.                  * не в панель, а в RibbonSplitButton
  171.                  */
  172.                 #region Кнопка-пример №1
  173.                 // Создаем новый экземпляр подсказки
  174.                 tt = new RibbonToolTip();
  175.                 // Отключаем вызов справки (в данном примере её нету)
  176.                 tt.IsHelpEnabled = false;
  177.                 // Создаем кнопку
  178.                 RibbonButton ribBtn = new RibbonButton();
  179.                 /* В свойство CommandParameter (параметры команды)
  180.                  * и в свойство Command (отображает команду) подсказки
  181.                  * пишем вызываемую команду
  182.                  */
  183.                 ribBtn.CommandParameter = tt.Command = "_Line";
  184.                 // Имя кнопки
  185.                 ribBtn.Name = "ExampleButton1";
  186.                 // Заголовок кнопки и подсказки
  187.                 ribBtn.Text = tt.Title = "Кнопка-пример №1";
  188.                 // Создаем новый (собственный) обработчик команд (см.ниже)
  189.                 ribBtn.CommandHandler = new RibbonCommandHandler();
  190.                 // Ориентация кнопки
  191.                 ribBtn.Orientation = System.Windows.Controls.Orientation.Horizontal;
  192.                 // Размер кнопки
  193.                 ribBtn.Size = RibbonItemSize.Large;
  194.                 /* Т.к. используем размер кнопки Large, то добавляем
  195.                  * большое изображение с помощью специальной функции (см.ниже)
  196.                  */
  197.                 ribBtn.LargeImage = LoadImage("icon_32");
  198.                 // Показывать картинку
  199.                 ribBtn.ShowImage = true;
  200.                 // Показывать текст
  201.                 ribBtn.ShowText = true;
  202.                 // Заполняем содержимое всплывающей подсказки
  203.                 tt.Content = "Я кнопочка №1. Нажми меня и я нарисую отрезок";
  204.                 // Подключаем подсказку к кнопке
  205.                 ribBtn.ToolTip = tt;
  206.                 // Добавляем кнопку в RibbonSplitButton
  207.                 risSplitBtn.Items.Add(ribBtn);
  208.                 #endregion
  209.                 // Делаем текущей первую кнопку
  210.                 risSplitBtn.Current = ribBtn;
  211.                 // Далее создаем вторую кнопку по аналогии с первой
  212.                 #region Кнопка-пример №2
  213.                 tt = new RibbonToolTip();
  214.                 tt.IsHelpEnabled = false;
  215.                 ribBtn = new RibbonButton();
  216.                 ribBtn.CommandParameter = tt.Command = "_Pline";
  217.                 ribBtn.Name = "ExampleButton2";
  218.                 ribBtn.Text = tt.Title = "Кнопка-пример №2";
  219.                 ribBtn.CommandHandler = new RibbonCommandHandler();
  220.                 ribBtn.Orientation = System.Windows.Controls.Orientation.Horizontal;
  221.                 ribBtn.Size = RibbonItemSize.Large;
  222.                 ribBtn.LargeImage = LoadImage("icon_32");
  223.                 ribBtn.ShowImage = true;
  224.                 ribBtn.ShowText = true;
  225.                 tt.Content = "Я кнопочка №2. Нажми меня и я нарисую полилинию";
  226.                 ribBtn.ToolTip = tt;
  227.                 risSplitBtn.Items.Add(ribBtn);
  228.                 #endregion
  229.                 // Добавляем RibbonSplitButton в нашу панель
  230.                 ribSourcePanel.Items.Add(risSplitBtn);
  231.                 // Создаем новую строку
  232.                 RibbonRowPanel ribRowPanel = new RibbonRowPanel();
  233.                 // Создаем третью кнопку по аналогии с предыдущими.
  234.                 // Отличие только в размере кнопки (и картинки)
  235.                 #region Кнопка-пример №3
  236.                 tt = new RibbonToolTip();
  237.                 tt.IsHelpEnabled = false;
  238.                 ribBtn = new RibbonButton();
  239.                 ribBtn.CommandParameter = tt.Command = "_Circle";
  240.                 ribBtn.Name = "ExampleButton3";
  241.                 ribBtn.Text = tt.Title = "Кнопка-пример №3";
  242.                 ribBtn.CommandHandler = new RibbonCommandHandler();
  243.                 ribBtn.Orientation = System.Windows.Controls.Orientation.Vertical;
  244.                 ribBtn.Size = RibbonItemSize.Standard;
  245.                 ribBtn.Image = LoadImage("icon_16");
  246.                 ribBtn.ShowImage = true;
  247.                 ribBtn.ShowText = false;
  248.                 tt.Content = "Я кнопочка №3. Нажми меня и я нарисую кружочек";
  249.                 ribBtn.ToolTip = tt;
  250.                 ribRowPanel.Items.Add(ribBtn);
  251.                 #endregion
  252.                 // Добавляем строку в нашу панель
  253.                 ribSourcePanel.Items.Add(ribRowPanel);
  254.             }
  255.             catch (System.Exception ex)
  256.             {
  257.                 Autodesk.AutoCAD.ApplicationServices.Application.
  258.                   DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.Message);
  259.             }
  260.         }
  261.         // Получение картинки из ресурсов
  262.         // Данная функция найдена на просторах интернет
  263.         System.Windows.Media.Imaging.BitmapImage LoadImage(string ImageName)
  264.         {
  265.             return new System.Windows.Media.Imaging.BitmapImage(
  266.                 new Uri("pack://application:,,,/ACadRibbon;component/" + ImageName + ".png"));
  267.         }
  268.         /* Собственный обраотчик команд
  269.          * Это один из вариантов вызова команды по нажатию кнопки
  270.          */
  271.         class RibbonCommandHandler : System.Windows.Input.ICommand
  272.         {
  273.             public bool CanExecute(object parameter)
  274.             {
  275.                 return true;
  276.             }
  277.             public event EventHandler CanExecuteChanged;
  278.             public void Execute(object parameter)
  279.             {
  280.                 Document doc = acadApp.DocumentManager.MdiActiveDocument;
  281.                 if (parameter is RibbonButton)
  282.                 {
  283.                     // Просто берем команду, записанную в CommandParameter кнопки
  284.                     // и выпоняем её используя функцию SendStringToExecute
  285.                     RibbonButton button = parameter as RibbonButton;
  286.                     acadApp.DocumentManager.MdiActiveDocument.SendStringToExecute(
  287.                         button.CommandParameter + " ", true, false, true);
  288.                 }
  289.             }
  290.         }
  291.     }
  292. }
  293.  

Заранее благодарен за любую помощь в решении проблемы, опыта работы с С#. NET нет, работаю с VBA.

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
1. Проверьте, что у всех ссылок стоит свойство "Копировать локально - false"
2. Какая версия Net Framework установлена для проекта?

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

  • ADN OPEN
  • Сообщений: 31
  • Карма: 0
Настройки:

1. Ссылки: Копировать локально значение «False»

2.  .NET Frumewor 4.6


Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Для 2013 автокада должен быть 4.0

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
2.  .NET Frumewor 4.6
Это 5 баллов.
Выложите в zip-архиве готовый проект. Уточните разрядность Windows/AutoCAD (32/64).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 31
  • Карма: 0
Архив приложил  :) (может ошибся с NET Frumewor 4.6)

Изображение с настроек файла.


Ссылка на архив (Яндекс диск): https://yadi.sk/d/PQt0Mmz73QtHAd

При создании проекта ставил: NET Frumewor 3.5

Прошу строга не судить, только второй день разбираюсь с Visual Studio 2015.
Очень сильно заинтересовала возможность создания плагина для AutoCAD и возможность подключения командой NETLOAD (кажется очень удобно).



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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Повторюсь:
Уточните разрядность Windows/AutoCAD (32/64).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 31
  • Карма: 0
Система:
1. Windows 7 (x64)
2. AutoCAD 2012 (x32)

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Система:
1. Windows 7 (x64)
2. AutoCAD 2012 (x32)
Это как??? И выше шла речь про AutoCAD 2013???
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • Сообщений: 31
  • Карма: 0
Прошу прощения опечатка AutoCAD 2013 (x32)

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

  • ADN OPEN
  • Сообщений: 31
  • Карма: 0
Попробовал собрать новый проект с настройкой NET Frumewor 4.0

Сообщает об ошибке в стоке:

Код - C# [Выбрать]
  1.  40 if (Autodesk.Windows.ComponentManager.Ribbon != null)
Код - C# [Выбрать]
  1.  128 ribCntrl.UpdateLayout();


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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Прошу прощения опечатка AutoCAD 2013 (x32)
Здесь тоже опечатка? AutoCAD 2013 x32 не инсталлируется на Windows 7x64
Предлагаю начать всё с начала. Как я понимаю, вы не знакомы ни с C#, ни с AutoCAD .NET API. Поэтому не следует перепрыгивать через голову. Начните с примеров в ObjectARX SDK соответствующей версии для вашего AutoCAD и с уроков по AutoCAD .NET API. До ленты еще нужно добраться.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

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

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

  • ADN OPEN
  • Сообщений: 31
  • Карма: 0
Подключил модуль WindowsBase, пересоздал проект подключил библиотеку *.dll к AutoCAD 2013 ошибка пропала.
Просить подключить изображение: «Не удается найти ресурс "icon_32.png".»
Проблема а как подключать в Visual Studio 2015 иконки ?


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

  • ADN OPEN
  • Сообщений: 31
  • Карма: 0
Цитировать
У вас там два проекта. Зачем?

Да так пробовал разными методами и настройками решить проблему.  :-\