Создание плагинов для autocad с помощью net api
Предыстория
Для пробы создать предлагалось на чертеже пару объектов, а также текст вывести. Несколько дней я искал информацию об пытался и API подружиться с непривычной программой. В конце фигуры концов были нарисованы, текст выведен, а задание тестовое отправлено на проверку. И через несколько неожиданно я дней узнал, что принят! Чудеса, да и следующих.
1. Подготовка необходимых инструментов
1.1. Собственно Тут
AutoCAD все понятно. Качайте с официального Autodesk сайта, ставьте, 30 дней наслаждайтесь прекрасным Потом. инструментом узнайте цену покупки и повесьтесь. разработчиков Для действует специальная программа ADN , по можно которой получать девелоперские лицензии на продукты Стоимость. Autodesk базовой версии подписки, как сайте на указано, составляет от 700 долларов в год.
2011 SDK и ссылка для загрузки | версиями с Совместимость AutoCAD |
---|---|
2011 | 2011, 2012 |
2010 | 2010, 2011, 2012 |
2009 | 2009 |
x86 2008 | 2008, 2009 x86 |
2008 2008 | x64, 2009 x64 |
2007 | 2007, 2009, 2008 x86 |
2006 | 2006 |
2005 | 2006, 2005 |
2004 | 2004, 2005, 2006 |
2002 | 2002 |
2000i | 2000i, 2002 |
2000 | 2000i, 2000, 2002 |
R14 | R14 |
Пока перекомпилировать задачи программу с другими библиотеками у меня не Думаю. возникало, что это хорошо: перспектива отдельную создавать версию продукта для других AutoCAD выпусков не радует совершенно.
1.3. MS Visual Studio Express 2013
Можно, конечно, использовать и ранние более версии. Я начинал работу над Visual в MS проектом Studio 2010, но потом решил более на перейти современный выпуск.
1.4. Поисковик, усидчивость, смысл здравый
- AutoCAD привычных всплывающих подсказок о назначении свойства, класса или метода;
- нет подробной итоге.
В конце статьи этой приведен список ресурсов, на которых позадавать можно вопросы и, если повезет, получить на ответы них.
2. Создание проекта библиотеки
продублирую Вкратце основные этапы:
файлам DLL-файлы находятся в папке с inc именем-<наименование_архитектуры>. Так, в моем добавляю я случае ссылки на библиотеки из папки C:\ObjectARX inc\2010-win32.
Теперь в любом этого месте файла можно вместо Autodesk.ApplicationServices.AutoCAD.Application писать acadApp .
Есть провернуть смысл такую операцию с наиболее часто классами употребляемыми. Непременно так делайте, код компактнее будет и понятнее. Цинизм данного совета том в заключается, что к тому моменту, когда вы поймете наконец, какие же классы являются у вас часто наиболее употребляемыми, что-то менять будет сильно уже лень.
2.3. Написать плагина код
Все очень просто. Вначале мы необходимые указываем пространства имен. Нам потребуются первом.
Таким образом, всего необходимо три добавить ссылки:
UPD. 09.04.2018. Важное lasteran от дополнение: В новых версиях (предположительно начиная с 2013 AutoCAD) класс CommandMethod содержится не в AcDBMgd.AcCoreMgd, а в dll.dll, так что придётся ссылку добавить ещё и на эту библиотеку. Учтите если, это работаете с новой версией!
AutoCAD поподробнее про методы Initialize и можно Terminate тут (rus) и там (англ.).
объявляем, мы Наконец функцию MyCommand , которая будет команду реализовывать AutoCAD. Она обязательно должна принимать не ничего на вход и ничего не возвращать на выходе (не откуда, знаю у меня взялось это убеждение, но есть оно). Внутри этой функции можно все делать, что заблагорассудится (в пределах разумного, причем), конечно есть возможность работать как с NET .AutoCAD API, так и со стандартными классами .Например. NET, можно создать обычную форму полями с Windows ввода, отобразить ее на экране с помощью затем() , а ShowModal на основе введенных пользователем данных изменения внести в открытый в AutoCAD чертеж.
После сборки проекта этого у нас получится готовый к употреблению Загрузить.
2.4. плагин созданный плагин
Затем в открывшемся указать окне путь к файлу плагина:
Если при загрузке произошла плагина критическая ошибка, она будет консоль в выведена AutoCAD:
плагин если не смог загрузиться из-за ошибки, то перед очередного тестированием (исправленного) варианта нужно закрыть и запустить заново AutoCAD. В противном случае он может загружать отказаться плагин, даже если ошибок в уже коде не будет.Теперь, когда плагин можно, загружен выполнить нашу тестовую команду:
Работает. Теперь можно закрывать как.
2.5. Отладить плагин (необходимости при)
Процедура запуска плагина для очень отладки хорошо расписана в этом посте Финал.
Tepliuk
Решил рассказать о своем опыте работы с AutoCAD. Может быть, кому-то это поможет – ну или хотя бы интересным покажется.
Предыстория
Началось все достаточно просто: в очередной раз почувствовав острую нехватку денег, я решил, что пора бы уже начать их где-нибудь разыскивать. И вот после пары недель поиска на «Фрилансим» обнаружилась вакансия разработчика для создания программы, взаимодействующей с AutoCAD.
Скажу сразу: до того дня общаться с AutoCAD мне не доводилось. Однако объявление содержало в себе фразу «Опыт работы не требуется», которая наполнила мою душу надеждой. Я связался с разместившим вакансию человеком и получил тестовое задание.
Для пробы предлагалось создать на чертеже пару объектов, а также вывести текст. Несколько дней я искал информацию об API и пытался подружиться с непривычной программой. В конце концов фигуры были нарисованы, текст выведен, а тестовое задание отправлено на проверку. И через несколько дней я неожиданно узнал, что принят! Чудеса, да и только.
1. Подготовка необходимых инструментов
1.1. Собственно AutoCAD
Тут все понятно. Качайте с официального сайта Autodesk, ставьте, 30 дней наслаждайтесь прекрасным инструментом. Потом узнайте цену покупки и повесьтесь. Для разработчиков действует специальная программа ADN , по которой можно получать девелоперские лицензии на продукты Autodesk. Стоимость базовой версии подписки, как указано на сайте, составляет от 700 долларов в год.
1.2. ObjectARX SDK – набор библиотек, необходимых для работы с AutoCAD
Последние три-четыре версии библиотек можно бесплатно скачать тут после регистрации. Более ранние придется поискать – скажем, тут. На всякий случай продублирую список прямо здесь – не такой уж он и длинный:
ссылки для загрузки ObjectARX SDK для версий AutoCAD 2000 – 2011Версия SDK и ссылка для загрузки | Совместимость с версиями AutoCAD |
---|---|
2011 | 2011, 2012 |
2010 | 2010, 2011, 2012 |
2009 | 2009 |
2008 x86 | 2008, 2009 x86 |
2008 x64 | 2008, 2009 x64 |
2007 | 2007, 2008, 2009 x86 |
2006 | 2006 |
2005 | 2005, 2006 |
2004 | 2004, 2005, 2006 |
2002 | 2002 |
2000i | 2000i, 2002 |
2000 | 2000, 2000i, 2002 |
R14 | R14 |
Лично меня в свое время очень заинтересовал вопрос обратной совместимости ObjectARX. Как-то раз заказчик спросил: «А с какими версиями AutoCAD сможет работать программа?», и мне пришлось изрядно времени потратить на поиски ответа. В целом, ответ звучит так: «Autodesk поддерживает обратную совместимость в течение трех лет ». Какие версии совместимы между собой, можно посмотреть под спойлером выше.
Пока задачи перекомпилировать программу с другими библиотеками у меня не возникало. Думаю, что это хорошо: перспектива создавать отдельную версию продукта для других выпусков AutoCAD не радует совершенно.
1.3. MS Visual Studio 2013 Express
Великолепная IDE! Больше про нее и говорить-то нечего. Ссылок для скачивания масса – например, вот.
Можно, конечно, использовать и более ранние версии. Я начинал работу над проектом в MS Visual Studio 2010, но потом решил перейти на более современный выпуск.
1.4. Поисковик, усидчивость, здравый смысл
- нет привычных всплывающих подсказок о назначении класса, свойства или метода;
- нет подробной справки.
В итоге информацию я черпал из файлов помощи Object ARX (у меня они установлены в папку с именем C:ObjectARX 2010docs), а также из многочисленных форумов, блогов и сообществ разработчиков AutoCAD. Признаться, больше помогало последнее, чем первое. :)
В конце этой статьи приведен список ресурсов, на которых можно позадавать вопросы и, если повезет, получить на них ответы.
2. Создание проекта библиотеки
Вкратце продублирую основные этапы:
2.1. Создать проект «Библиотека классов» («Class Library»)
Эти DLL-файлы находятся в папке с именем inc-<наименование_архитектуры>. Так, в моем случае я добавляю ссылки на библиотеки из папки C:ObjectARX 2010inc-win32.
у меня дома установлена 32-разрядная ОС, у заказчика – 64-разрядная. Пока серьезных проблем с совместимостью не возникало. Но однажды я все же напоролся на то, что у меня функция возвращала Int32 , а у заказчика – Int64 . Линковщик ОЧЕНЬ расстраивался. Нужно иметь эту особенность в виду.Первое знакомство с API у меня заключалось в лихорадочных попытках скомпилировать хоть какой-нибудь из примеров, щедро разбросанных по Сети. И что сλка характерно, компилироваться они упорно не хотели, ругаясь на неизвестные пространства имен и классы. В попытках собрать свой первый проект я с горя включил в него чуть ли не все DLL-файлы, которые шли с ObjectARX. Плохой способ – так делать не надо.
То, что начинается со слова «Autodesk», – это и есть те дроиды пространства имен, которые мы ищем. Теперь осталось разыскать контейнеры, которые их содержат. Исчерпывающего перечня сопоставлений я найти не смог, поэтому все проверялось методом научного тыка. Если есть более правильный способ, было бы интересно его узнать…
А пока – вот список DLL-файлов, которые я использую в проекте, и содержащихся в них пространств имен:
Контейнер «AcMgd» (файл «AcMgd.dll»):
Контейнер «AcDbMgd» (файл «AcDbMgd.dll»):
Контейнер «AdWindows» (файл «AdWindows.dll»):
Контейнер «AcCui» (файл AcCui.dll»):
Теперь в любом месте этого файла можно вместо Autodesk.AutoCAD.ApplicationServices.Application писать acadApp .
Есть смысл провернуть такую операцию с наиболее часто употребляемыми классами. Непременно так делайте, код будет компактнее и понятнее. Цинизм данного совета заключается в том, что к тому моменту, когда вы наконец поймете, какие же классы являются у вас наиболее часто употребляемыми, что-то менять будет уже сильно лень.
2.3. Написать код плагина
Все очень просто. Вначале мы указываем необходимые пространства имен. Нам потребуются два.
Таким образом, всего необходимо добавить три ссылки:
Затем мы объявляем класс Commands . Именно он и будет «отправной точкой» плагина. Наш класс унаследован от интерфейса IExtensionApplication , поэтому в нем могут быть реализованы методы Initialize и Terminate . Первый из них автоматически выполняется при загрузке плагина, второй – при выгрузке.
AutoCAD не предоставляет разработчику возможность выгрузить плагин после того, как он будет загружен. Поэтому реально метод Terminate будет вызываться только в одном случае – при закрытии самого AutoCAD.Почитать поподробнее про методы Initialize и Terminate можно тут (rus) и там (англ.).
Чтобы «превратить» созданный метод в команду AutoCAD, применяется атрибут CommandMethod . В скобках после него указывается имя создаваемой команды, которое можно будет использовать непосредственно в среде AutoCAD.
После сборки этого проекта у нас получится готовый к употреблению плагин.
2.4. Загрузить созданный плагин
Нужно запустить AutoCAD и выполнить команду «NETLOAD»:
Затем в открывшемся окне указать путь к файлу плагина:
Если при загрузке плагина произошла критическая ошибка, она будет выведена в консоль AutoCAD:
Теперь, когда плагин загружен, можно выполнить нашу тестовую команду:
… и увидеть результат:
Работает. Теперь можно закрывать AutoCAD.
2.5. Отладить плагин (при необходимости)
Процедура запуска плагина для отладки очень хорошо расписана в этом посте Tepliuk.
Финал
Ну что же – для первого раза достаточно. Осталось привести обещанные ссылки. В посте Namolem и посте n00buK уже приведен большой объем источников; часть из них я продублирую здесь.
На этом моя статья закончена. Если ее признают годной – напишу еще несколько простых заметок о том, с чем сталкивался, как-то:
public static string disclaimer = "Автор не является профессиональным разработчиком и не обладает глубокими знаниями AutoCAD. Этот пост – просто небольшой рассказ о создания плагина.";
Когда я в свое время начинал работать с лентой, то больше всего мне помог пример, изложенный здесь. В основном я буду опираться именно на него.
Кроме того, некоторую информацию можно почерпнуть из этого поста Kean Walmsley.
Для начала вспомним, как выглядит лента в AutoCAD:
В верхней части расположен список вкладок ленты (Home, Mesh Modeling, Render. ). При выборе вкладки на ленте отображаются элементы управления этой вкладки, сгруппированные в панели (Modeling, Mesh, Solid Editing. ).
Ну что же, приступим.
1. Создание нового проекта плагина
namespace MyAutoCADDll
public class Commands : IExtensionApplication
// эта функция будет вызываться при выполнении в AutoCAD команды "TestCommand"
[CommandMethod("TestCommand")]
public void MyCommand()
// Функции Initialize() и Terminate() необходимы, чтобы реализовать интерфейс IExtensionApplication
public void Initialize()
public void Terminate()
2. Добавление ссылок на необходимые библиотеки
3. Собственно написание кода для создания новой вкладки
Чтобы создать новую вкладку на ленте, необходимо:
- создать элементы интерфейса;
- сгруппировать эти элементы в контейнеры;
- создать панели, на которых будут размещены эти контейнеры;
- создать вкладку, на которой будут размещены эти панели;
- добавить созданную вкладку на ленту AutoCAD.
Код:// эта функция будет вызываться при выполнении в AutoCAD команды «TestCommand»
[CommandMethod("TestCommand")]
public void MyCommand()
// создаем выпадающий список
Autodesk.Windows.RibbonCombo comboBox1 = new RibbonCombo();
comboBox1.Id = "_combobox1";
// создаем кнопку
Autodesk.Windows.RibbonButton button1 = new Autodesk.Windows.RibbonButton();
button1.Id = "_button1";
// создаем контейнер для элементов
Autodesk.Windows.RibbonPanelSource rbPanelSource = new Autodesk.Windows.RibbonPanelSource();
rbPanelSource.Title = "Новая панель элементов";
// добавляем в контейнер элементы управления
rbPanelSource.Items.Add(comboBox1);
rbPanelSource.Items.Add(new RibbonSeparator());
rbPanelSource.Items.Add(button1);
// создаем панель
RibbonPanel rbPanel = new RibbonPanel();
// добавляем на панель контейнер для элементов
rbPanel.Source = rbPanelSource;
// создаем вкладку
RibbonTab rbTab = new RibbonTab();
rbTab.Title = "Новая вкладка";
rbTab.Id = "HabrRibbon";
// добавляем на вкладку панель
rbTab.Panels.Add(rbPanel);
// получаем указатель на ленту AutoCAD
Autodesk.Windows.RibbonControl rbCtrl = ComponentManager.Ribbon;
// добавляем на ленту вкладку
rbCtrl.Tabs.Add(rbTab);
// делаем созданную вкладку активной ("выбранной")
rbTab.IsActive = true;
>
Собираем проект, запускаем AutoCAD, загружаем с помощью команды NETLOAD наш плагин, выполняем команду TestCommand…
Да, не самый впечатляющий результат.
Но ничего, чуть позже сделаем вкладку повеселее. А пока разберемся с тем, что уже есть.
4. Поиск элементов на ленте
Для поиска вкладки на ленте можно использовать метод ComponentManager.Ribbon.FindTab(string id). В качестве аргумента необходимо указать Id вкладки, заданный при ее создании.
Существуют аналогичные методы для поиска панели (ComponentManager.Ribbon.FindPanel(string id, bool SearchActiveTabOnly)) и прочих элементов управления (ComponentManager.Ribbon.FindItem(string id, bool SearchActiveTabOnly)).
В случае успешного нахождения элемента приведенные функции вернут соответствующий объект, иначе будет возврашено значение null.
5. Обработка нажатия кнопки
Для привязки обработчика нажатия кнопки служит свойство CommandHandler класса RibbonButton. В этом свойстве необходимо указать метод, реализующий интерфейс System.Windows.Input.ICommand.
В рамках интерфейса ICommand класс должен реализовать событие CanExecuteChanged, а также функции CanExecute и Execute.
namespace MyAutoCADDll
public class Commands : IExtensionApplication
// эта функция будет вызываться при выполнении в AutoCAD команды "TestCommand"
[CommandMethod("TestCommand")]
public void MyCommand()
// создаем выпадающий список
Autodesk.Windows.RibbonCombo comboBox1 = new RibbonCombo();
comboBox1.Id = "_combobox1";
// создаем контейнер для элементов
Autodesk.Windows.RibbonPanelSource rbPanelSource = new Autodesk.Windows.RibbonPanelSource();
rbPanelSource.Title = "Новая панель элементов";
// добавляем в контейнер элементы управления
rbPanelSource.Items.Add(comboBox1);
rbPanelSource.Items.Add(new RibbonSeparator());
rbPanelSource.Items.Add(button1);
// создаем панель
RibbonPanel rbPanel = new RibbonPanel();
// добавляем на панель контейнер для элементов
rbPanel.Source = rbPanelSource;
// создаем вкладку
RibbonTab rbTab = new RibbonTab();
rbTab.Title = "Новая вкладка";
rbTab.Id = "HabrRibbon";
// добавляем на вкладку панель
rbTab.Panels.Add(rbPanel);
// получаем указатель на ленту AutoCAD
Autodesk.Windows.RibbonControl rbCtrl = ComponentManager.Ribbon;
// добавляем на ленту вкладку
rbCtrl.Tabs.Add(rbTab);
// делаем созданную вкладку активной ("выбранной")
rbTab.IsActive = true;
>
// Функции Initialize() и Terminate() необходимы, чтобы реализовать интерфейс IExtensionApplication
public void Initialize()
public void Terminate()
// обработчик нажатия кнопки
public class CommandHandler_Button1 : System.Windows.Input.ICommand
public event EventHandler CanExecuteChanged;
public bool CanExecute(object param)
return true;
>
NB:Событие CanExecuteChanged оповещает пользователей команды о возможном изменении ее доступности для выполнения (короче говоря, работает она или не работает). Функция CanExecute позволяет узнать, доступна ли команда для выполнения в данный момент времени. А функция Execute — это собственно те действия, которые должна выполнять команда, когда ее вызвали.
В настоящем примере команда доступна всегда, и это состояние не меняется. В моей реальной задаче тоже ни разу не возникало необходимости как-то использовать первые два параметра.)
6. Взаимодействие с выпадающим списком (RibbonCombo)
6.1 Добавление, изменение, удаление элементов списка
Все элементы выпадающего списка RibbonCombo содержатся в его свойстве Items. Оно имеет тип System.Collections.ObjectModel.ObservableCollection, причем в качестве типа содержимого выступает System.Object. Таким образом, элементом коллекции может быть объект любого класса. К сожалению, если просто добавить в этот массив несколько текстовых строк, то желаемого эффекта мы не получим:
Чтобы получить приличный выпадающий список, в качестве его элементов можно использовать экземпляры рассмотренного выше класса RibbonButton:
Autodesk.Windows.RibbonButton tempRibBut1 = new Autodesk.Windows.RibbonButton();
tempRibBut1.Id = "_temp_button_1";
tempRibBut1.Text = "элемент 1";
tempRibBut1.ShowText = true;
Autodesk.Windows.RibbonButton tempRibBut2 = new Autodesk.Windows.RibbonButton();
tempRibBut2.Id = "_temp_button_2";
tempRibBut2.Text = "элемент 2";
tempRibBut2.ShowText = true;
В результате увидим вот что:
При необходимости можно использовать заложенные в ObservableCollection свойства и методы, в частности:
- метод Remove(object item) — для удаления указанного элемента;
- метод RemoveAt(int index) — для удаления элемента на указанной позиции;
- метод Clear() — для удаления всех элементов из коллекции;
- свойство Count — для получения количества элементов в коллекции.
NB:Обычно элемент списка соотносится с каким-то объектом предметной области. Чтобы иметь возможность быстро определить, с чем сопоставлен тот или иной элемент списка, можно использовать свойство Tag класса RibbonButton:
Autodesk.Windows.RibbonButton tempRibBut1 = new Autodesk.Windows.RibbonButton();
tempRibBut1.Id = "_temp_button_1";
tempRibBut1.Text = "элемент 1";
tempRibBut1.ShowText = true;
tempRibBut1.Tag = "elementTag"; // задаем тег
comboBox1.Items.Add(tempRibBut1);
Тогда при обработке элемента списка можно посмотреть, какой был задан тег:
object obj = comboBox1.Items[0];
string itemTag = (obj as RibbonButton).Tag; // "elementTag"
Можно пойти и еще дальше. Поскольку свойство Tag имеет тип System.Object, в качестве тега может выступать объект любого класса, в том числе и созданного самим программистом:
tempRibBut1.Tag = new MyClass("objectDecription");
После этого можно будет обратиться к любому свойству этого объекта:
object obj = comboBox1.Items[0];
MyClass itemTag = (obj as RibbonButton).Tag as MyClass;
string myClassDecription = itemTag.Description;
При возникновении острого желания экономить строки есть возможность писать конструкции вида
string myClassDecription = ((comboBox1.Items[0] as RibbonButton).Tag as MyClass).Description
Разумеется, в реальном коде необходимо убеждаться, что полученные значения не равны null.
6.2 Обработка события выбора элемента списка
При выборе элемента списка RibbonCombo генерируется событие CurrentChanged. Вот простой пример обработчика такого события:
namespace MyAutoCADDll
public class Commands : IExtensionApplication
// эта функция будет вызываться при выполнении в AutoCAD команды "TestCommand"
[CommandMethod("TestCommand")]
public void MyCommand()
// создаем выпадающий список
Autodesk.Windows.RibbonCombo comboBox1 = new RibbonCombo();
comboBox1.Id = "_combobox1";
// добавляем новые элементы в список
Autodesk.Windows.RibbonButton tempRibBut1 = new Autodesk.Windows.RibbonButton();
tempRibBut1.Id = "_temp_button_1";
tempRibBut1.Text = "элемент 1";
tempRibBut1.ShowText = true;
tempRibBut1.Tag = "btn1";
Autodesk.Windows.RibbonButton tempRibBut2 = new Autodesk.Windows.RibbonButton();
tempRibBut2.Id = "_temp_button_2";
tempRibBut2.Text = "элемент 2";
tempRibBut2.ShowText = true;
tempRibBut2.Tag = "btn2";
// привязываем к списку обработчик выбора нового элемента
comboBox1.CurrentChanged += comboBox1_CurrentChanged;
// создаем контейнер для элементов
Autodesk.Windows.RibbonPanelSource rbPanelSource = new Autodesk.Windows.RibbonPanelSource();
rbPanelSource.Title = "Новая панель элементов";
// добавляем в контейнер элементы управления
rbPanelSource.Items.Add(comboBox1);
rbPanelSource.Items.Add(new RibbonSeparator());
rbPanelSource.Items.Add(button1);
// создаем панель
RibbonPanel rbPanel = new RibbonPanel();
// добавляем на панель контейнер для элементов
rbPanel.Source = rbPanelSource;
// создаем вкладку
RibbonTab rbTab = new RibbonTab();
rbTab.Title = "Новая вкладка";
rbTab.Id = "HabrRibbon";
// добавляем на вкладку панель
rbTab.Panels.Add(rbPanel);
// получаем указатель на ленту AutoCAD
Autodesk.Windows.RibbonControl rbCtrl = ComponentManager.Ribbon;
// добавляем на ленту вкладку
rbCtrl.Tabs.Add(rbTab);
// делаем созданную вкладку активной ("выбранной")
rbTab.IsActive = true;
>
// Функции Initialize() и Terminate() необходимы, чтобы реализовать интерфейс IExtensionApplication
public void Initialize()
public void Terminate()
// обработчик нажатия кнопки
public class CommandHandler_Button1 : System.Windows.Input.ICommand
public event EventHandler CanExecuteChanged;
public bool CanExecute(object param)
return true;
>
7. Настройка внешнего вида элементов управления
Во-первых, элементы управления можно располагать друг под другом — это особенно удобно, если используются «узкие» элементы вроде выпадающих списков.
Во-вторых, у каждого элемента управления есть свойства, позволяющие изменять его внешний вид. Например, для выпадающего списка можно задать заголовок и ширину, для кнопки — размер (большая или маленькая) и подпись. Кроме того, можно добавить всплывающие подсказки (в примере она добавлена для третьей кнопки).
namespace MyAutoCADDll
public class Commands : IExtensionApplication
// эта функция будет вызываться при выполнении в AutoCAD команды "TestCommand"
[CommandMethod("TestCommand")]
public void MyCommand()
// создаем квадратик цвета морской волны (он будет старательно играть роль иконки)
Bitmap bmp = new Bitmap(1, 1);
bmp.SetPixel(0, 0, Color.Aquamarine);
bmp = new Bitmap(bmp, 1024, 1024);
IntPtr hBitmap = bmp.GetHbitmap();
System.Windows.Media.Imaging.BitmapSource bs =
System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
System.Windows.Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
// создаем выпадающие списки
Autodesk.Windows.RibbonCombo comboBox1 = new RibbonCombo();
comboBox1.Id = "_combobox1";
comboBox1.Width = 200;
comboBox1.Text = "Список 1";
comboBox1.ShowText = true;
Autodesk.Windows.RibbonCombo comboBox2 = new RibbonCombo();
comboBox2.Id = "_combobox2";
comboBox2.Width = 200;
comboBox2.Image = bs;
comboBox2.ShowImage = true;
// создаем кнопки
Autodesk.Windows.RibbonButton button1 = new Autodesk.Windows.RibbonButton();
button1.Id = "_button1";
Autodesk.Windows.RibbonButton button2 = new Autodesk.Windows.RibbonButton();
button2.Id = "_button2";
// создаем вертикальные панели, на которых будут размещены друг под другом выпадающие списки и кнопки
Autodesk.Windows.RibbonRowPanel RowPanel1 = new Autodesk.Windows.RibbonRowPanel();
Autodesk.Windows.RibbonRowPanel RowPanel2 = new Autodesk.Windows.RibbonRowPanel();
// размещаем в вертикальных панелях выпадающие списки и кнопки
RowPanel1.Items.Add(comboBox1);
RowPanel1.Items.Add(new RibbonRowBreak());
RowPanel1.Items.Add(comboBox2);
RowPanel2.Items.Add(button1);
RowPanel2.Items.Add(new RibbonRowBreak());
RowPanel2.Items.Add(button2);
// создаем кнопки большого размера
Autodesk.Windows.RibbonButton button3 = new Autodesk.Windows.RibbonButton();
button3.Id = "_button3";
button3.IsToolTipEnabled = true;
button3.ToolTip = "Это большая кнопка";
button3.Size = Autodesk.Windows.RibbonItemSize.Large;
button3.LargeImage = bs;
Autodesk.Windows.RibbonButton button4 = new Autodesk.Windows.RibbonButton();
button4.Id = "_button4";
button4.Text = "^___^";
button4.ShowText = true;
button4.Size = Autodesk.Windows.RibbonItemSize.Large;
button4.LargeImage = bs;
// создаем контейнеры для элементов
Autodesk.Windows.RibbonPanelSource rbPanelSource1 = new Autodesk.Windows.RibbonPanelSource();
rbPanelSource1.Title = "Новая панель элементов";
Autodesk.Windows.RibbonPanelSource rbPanelSource2 = new Autodesk.Windows.RibbonPanelSource();
rbPanelSource2.Title = "Еще одна панель";
// добавляем в контейнеры элементы управления
rbPanelSource1.Items.Add(RowPanel1);
rbPanelSource1.Items.Add(RowPanel2);
rbPanelSource1.Items.Add(new RibbonSeparator());
rbPanelSource1.Items.Add(button3);
rbPanelSource2.Items.Add(button4);
// создаем панели
RibbonPanel rbPanel1 = new RibbonPanel();
RibbonPanel rbPanel2 = new RibbonPanel();
// добавляем на панели контейнеры для элементов
rbPanel1.Source = rbPanelSource1;
rbPanel2.Source = rbPanelSource2;
// создаем вкладку
RibbonTab rbTab = new RibbonTab();
rbTab.Title = "Новая вкладка";
rbTab.Id = "HabrRibbon";
// добавляем на вкладку панели
rbTab.Panels.Add(rbPanel1);
rbTab.Panels.Add(rbPanel2);
// получаем указатель на ленту AutoCAD
Autodesk.Windows.RibbonControl rbCtrl = ComponentManager.Ribbon;
// добавляем на ленту вкладку
rbCtrl.Tabs.Add(rbTab);
// делаем созданную вкладку активной ("выбранной")
rbTab.IsActive = true;
>
// Функции Initialize() и Terminate() необходимы, чтобы реализовать интерфейс IExtensionApplication
public void Initialize()
public void Terminate()
На этом статья подходит к концу. В следующий раз напишу о работе со слоями и простыми графическими объектами.
Конструктивные замечания/пожелания приветствуются. Могу выложить примеры плагинов, упакованных в данный шаблон, но это уже не сегодня.
UPD. Обновил архив - исправил серьёзную опечатку и добавил пример группирования и отображения команд.
UPD2. Завернул в шаблон программу Александра Ривилиса. Прикреплён внизу как DwgConvert.zip. Нужно распаковать архив и открыть файл readme.html.
UPD3. Перезалил оба архива. Внёс в шаблон некоторые правки, касающиеся визуального отображения, добавил в оглавление readme.html ещё один раздел, с помощью которого можно попадать в каталог нужной версии программы. Внёс изменения в chm-файл мануала.
UPD4. Перезалил оба архива. Внёс в шаблон некоторые правки, касающиеся визуального отображения, а так же расширил логику динамического формирования панели навигации readme.html - теперь в него можно добавлять произвольное количество групп с произвольным количеством позиций (помимо уже существующих). Частично изменил структуру и содержимое каталогов, например - в каталоге ./support находится только то, что не требует изменения (т.е. разработчику туда можно не заглядывать). Внёс соответствующие изменения в chm-файл мануала. Соответственно изменённому шаблону модифицировал пример приложения, построенного в соответствии с шаблоном.
UPD5. Перезалил оба архива. В шаблоне внёс изменение в файл appinfo.xslt, чтобы в таблицах имена команд, каталогов и файлов выделялись жирным шрифтом (так их легче читать), а так же исправил одну опечатку. Во второй архив добавил ещё два примера. Всё, более примеров выкладывать не буду - достаточно трёх.
UPD6. Перезалил оба архива. В шаблонах внёс некоторые изменения в файлы XSD, а так же в файл versions.xml, для возможности корректного описания LISP-программ. В архив samples, по просьбам телезрителей добавил пример упаковки LISP-сборника. В тот же архив упаковал и ещё одно приложение от Александра Ривилиса. В примере упаковки LISP-программ я, в качестве опять же примера, в таблицу загрузок добавил несколько записей, указав, что загружать следует все файлы с расширениями lsp, fas и vlx, хотя на самом деле в примере имеются только lsp-файлы.
__________________Надеюсь, ты не социальный овощ? Это определяется делами! :welcome: Как-то быстро тебя "улыбнуло", там в одной только документации 68 листов. __________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
Инженер-проектировщик, конструктор, руководитель группы.
не потому ли мегософтверные гиганты запихивают свои так называемые лицензионные соглашения в текстовый формат, чтоб их мог прочитать даже самый тупой юзерзачем юзеру версия модуля, которую он не сможет подгрузить?
может не прав, но каталог bin - пережиток прошлого, атавизм дос, а вот где папка Help не понятно
насчет "правильного" решения. программист на лисп просто зашьет текстовый файл в модуль vlx и будет читать оттуда
насчет настроек. тут дело вкуса, реестр, ini, xml у каждого свои плюсы и минусы
насчет автоматической правки справки, ну, да, большая лень - реактивный двигатель прогресса
имхо. как-то уж слишком много эксэмеля. __________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome: Спасибо, очень интересно. Буду изучать. Понравилась структура - все по полочкам. Хороший пример огранизации файлов приложения. Всю прелесть пока оценить не могу, ввиду скудных знаний XML и т.п.
hwd, ты все правильно сделал. Такая система, безусловно, нужна. Вот только кому?
Само собой, что в первую очередь себе. Ты её будешь придерживаться и будешь делать хорошие, унифицированные "плагины" (как ты их называешь).
А много ли таких "плагинов" вообще сделано? Хотя бы лично тобой? В России? В мире? Сколько именно, хотя бы примерно?
Можно примерный тематический список? А много ли таких плагинов сваливается на "адмнистраторов САПР" со стороны? Много ли таких "администраторов" вообще? 1? 10? 100000?
По сути же шаблона мне кажется, что здесь обязательно должен быть и "шаблон" сценария инсталлятора.
В конце концов даже полумифического Администратора САПР не должны интересовать внутренние потроха "плагина". Он (или доверенный пользователь) должен просто запустить инсталлятор, который сам разложит все компоненты "куда положено", запишет в настройки "что надо", вставит необходимое в меню AutoCAD.
Чтобы пользователю только оставалось нажимать кнопки и получать райское наслаждение.
Насчёт "кому это нужно" - это нужно и организации и пользователям, хотя они этого могут и не осознавать. Поясню. Если оформление приводится к единому знаменателю, то и пользователям будет проще работать с ними, т.к. они знают, что открыв readme.html они найдут всё, что им нужно. Более того - они уже знают, где именно в readme.html им следует искать интересующую их информацию. Такое оформление позволяет создавать приложения, которые управляли бы уже существующими плагинами и теми, которые появятся позднее. Например, можно написать приложение, которое отобразит пользователю полный перечень ключевых слов и словосочетаний, ассоциированных с командами, написанными во всех плагинах, построенных на основе шаблона. Юзер выбирает то, что ему нужно и автоматом будут открываться в браузере нужные страницы справок соответствующих плагинов с указанием команд, соответствующих его выбору. Т.о. пользователь может искать нужный ему функционал, не перелопачивая для этого кучу имеющихся приложений.
А много ли таких "плагинов" вообще сделано? Хотя бы лично тобой? В России? В мире? Сколько именно, хотя бы примерно? |
По сути же шаблона мне кажется, что здесь обязательно должен быть и "шаблон" сценария инсталлятора. |
Инсталлятор невозможен в принципе. Это ведь не приложение, а лишь обёртка. Каждый разработчик для своего приложения может создавать различного рода иерархию файлов и каталогов. Чтобы завернуть это в шаблон, нужно понимать, что делаешь. Если, к примеру, автор в текстовом файле всё в одном месте прописал: перечень команд, системные требования и т.п., то как инсталлятор узнает где какая информация и выдернет её, чтобы заполнить в шаблон? Сейчас ведь все пишут как им Бог на душу положит, а значит упаковку каждого приложения придётся делать вручную. Да, это придётся сделать один раз, но много времени это не займёт и оно того стоит (имхо). И ещё - упаковкой занимается не пользователь, а разработчик! Т.е. он сам своё творение упаковывает в шаблон. Пользователь юзает готовый результат. Если упаковывать нужно и чужой код, который уже имеется у юзеров, то этим может заняться администратор CAD или человек, выполняющий его обязанности.
И какого уровня эти "плагины", чтобы на них затрачивать такие усилия по унификации и документированию? |
это приложения, которые написаны в самой компании, либо притащенные юзерами из инета.
То, что я выложил в топике - это предложенный мною вариант оформления программ, написанных для AutoCAD. Если получаю плагин, оформленный в соответствии с данным шаблоном, то точно знаю, что скопировав его в нужный каталог мне более ничего делать не придётся, т.к. автозагрузчик далее сам разберётся каким пользователям, что и для какой версии автокада следует загружать для того, чтобы плагин заработал.
Я не утверждаю, что это панацея. Это всего лишь один из готовых, уже работающих вариантов. Я отдаю себе отчёт в том, что основная масса программистов не интересуется подобными темами (к сожалению), а из тех, кто интересуется - далеко не все правильно поймут то, что я предложил (скорее всего в виду сумбурности моего изложения). Но возможно, что найдутся и такие, кого обозначенная тема заинтересует и предоставленный мною материал будет полезен.
Чуть позднее я в этом топике выложу примеры приложений, упакованных в обозначенный шаблон. Если и это не поможет понять суть шаблона, значит не дано мне понятно излагать свои идеи.
Читайте также: