Официальный форум российского программного комплекса T-FLEX PLM


Поиск  Правила 
Закрыть
Логин:
Пароль:
Забыли свой пароль?
Регистрация
Войти
 
Страницы: 1 2 След.
Шаблон CAD плагина для VS2008
 
Здравствуйте!

А не найдётся ли у кого готового шаблона CAD плагина для VS2008? Тот, который лежит в : C:\Program Files\T-FLEX\T-FLEX CAD 10\API\Wizards VS 7.1 при конвертации до версии 2008 теряет свою работоспособность.

Спасибо.
 
Шаблон для создания плагина
Реализация классов PluginFactory и Plugin для регистрации и создания приложения:
Код
using TFlex;
using TFlex.Model;
using TFlex.Model.Model2D;
using TFlex.Command;

namespace test
{
    public class testFactory : PluginFactory
    {
        //Данный метод создаёт объекты приложения.
        //Их может быть один или более.
        public override Plugin CreateInstance()
        {
            return new testPlugin(this);
        }

        //Любое приложение должно иметь уникальный GUID, 
        //возвращаемый при помощи данного свойства.
        //Для данного приложения этот GUID сгенерирован автоматически
        //и изменять его не рекомендуется
        public override Guid ID
        {
            get
            {
                return new Guid("{60f4149b-5d3c-4f6f-982e-aadad499346b}");
            }
        }

        //Данное свойство является названием приложения.
        //Оно может быть отредактировано
        public override string Name
        {
            get
            {
                return "test";
            }
        }
    };

    //Перечислитель команд приложения.
    //Данные команды могут использоваться в главном меню системы и/или
    //в панелях инструментов.
    enum Commands
    {
        Command1 = 1,
        //Здесь можно добавить команды приложения

        Count
    };

    //Перечислитель команд объектов приложения.
    //Данные команды могут использоваться в контекстном меню
    //объектов модели или объектов приложения.
    enum ObjectCommands
    {
        Command1 = Commands.Count,
        //Здесь можно добавить команды объектов приложения

    };

    //Перечислитель иконок объектов модели, создаваемых приложением.
    enum ObjectTypeIcons
    {
        testObjectIcon
    };

    //Перечислитель команд автоменю
    enum AutomenuCommands
    {
        Number,
        Command9 = Number + 8,
    };

    //Класс приложения
    class testPlugin : Plugin
    {
        public testPlugin(testFactory factory)
            : base(factory)
        {

        }

        //Вспомогательный метод для загрузки изображения
        System.Drawing.Bitmap LoadBitmapResource(string name)
        {
            System.IO.Stream stream = GetType().Assembly.
            GetManifestResourceStream("test.Resource_Files." + name + ".bmp");
            return new System.Drawing.Bitmap(stream);
        }

        //Вспомогательный метод для загрузки иконки
        System.Drawing.Icon LoadIconResource(string name)
        {
            System.IO.Stream stream = GetType().Assembly.
            GetManifestResourceStream("test.Resource_Files." + name + ".ico");
            return new System.Drawing.Icon(stream);
        }

        //Метод, вызываемый системой при инициализации приложения.
        //Для правильной работы необходимо вызвать инициализацию базового класса.
        protected override void OnInitialize()
        {
            base.OnInitialize();

            int[] CmdIDs = new int[8];

            //Регистрируются иконки кнопок автоменю, если это необходимо
            for (int i = 0; i < 8; ++i)
            {
                String hint = String.Format(i < 2 ? "{0}" : "{0}", i + 3);
                CmdIDs[i] = (int)AutomenuCommands.Number + i;
                RegisterAutomenuCommand(CmdIDs[i], hint, LoadIconResource("AutoNum" + (i + 1)));
            }

            RegisterAutomenuCommand((int)AutomenuCommands.Command9, "Command 9", LoadIconResource("Automenu"));
        }

        //Метод, вызываемый системой при необходимости создания 
        //панелей инструментов и регистрации пунктов меню приложения.
        //Для правильной работы необходимо вызвать инициализацию базового класса.
        protected override void OnCreateTools()
        {
            base.OnCreateTools();

            RegisterCommand((int)Commands.Command1, "Первая команда", LoadIconResource("Command1Small"), LoadIconResource("Command1Large"));

            RegisterObjectCommand((int)ObjectCommands.Command1, "Первая команда объекта модели", LoadIconResource("ObjectCommand1Small"), LoadIconResource("ObjectCommand1Large"));

            //Здесь регистрируются иконки объектов модели, создаваемых приложением
            RegisterObjectTypeIcon((int)ObjectTypeIcons.testObjectIcon, LoadIconResource("testObjectIcon"));

            //Здесь приложение добавляет в главное меню системы свои команды.
            //Они появятся в подменю "Сервис"
            TFlex.Menu submenu = new TFlex.Menu();
            submenu.CreatePopup();

            submenu.Append((int)Commands.Command1, "&Первая команда", this);

            TFlex.Application.Window.InsertPluginSubMenu("testPlugin", submenu, TFlex.MainWindow.InsertMenuPosition.PluginSamples, this);

            //Здесь создаётся панель с командами приложения.
            int[] CmdIDs = new int[]
         {
            (int)Commands.Command1
         };

            CreateToolbar("testPlugin", CmdIDs);
        }

        //Данный метод производит обработку команд приложения
        protected override void OnCommand(Document document, int id)
        {
            switch ((Commands)id)
            {
                default:
                    //В случае получения неизвестной команды необходимо вызвать
                    //метод базового класса.
                    base.OnCommand(document, id);
                    break;

                case Commands.Command1:
                    //Запускаем команду приложения.
                    testCommand Command = new testCommand(this);
                    Command.Run(document.ActiveView);

                    break;
            }
        }

        //Данный метод позволяет блокировать команды приложения.
        protected override void OnUpdateCommand(CommandUI cmdUI)
        {
            if (cmdUI == null)
                return;

            if (cmdUI.Document == null)
            {
                cmdUI.Enable(false);
                return;
            }

            cmdUI.Enable();
        }

        //Данный метод должен создать объект модели указанного типа.
        protected override ProxyObject CreateObject(Document Document, IntPtr OwnerHandle, int TypeID)
        {
            switch (TypeID)
            {
                case 1:
                    return new testObject(OwnerHandle);
            }

            return null;
        }
    }
}


Реализация класса PluginCommand для создания команд автоменю и объектных команд приложения:
Код
//Данный файл обеспечивает реализацию команды приложения с диалогом на виде документа
using System;
using System.Runtime.InteropServices;
using TFlex;
using TFlex.Model;
using TFlex.Model.Model2D;
using TFlex.Drawing;
using TFlex.Command;

namespace test
{
    class testCommand : PluginCommand
    {
        testObject reptestObject;

        SelectEventHandler repSelectEventHandler;

        //В конструкторе команды необходимо зарегистрировать обработчики событий
        public testCommand(Plugin App)
            : base(App)
        {
            //Обработчик инициализации команды. Он будет вызываться один раз при каждом запуске данной команды
            this.Initialize += new InitializeEventHandler(testCommand_Initialize);

            //Обработчик выхода из команды. Он будет вызываться один раз при каждом выходе из данной команды
            this.Exit += new ExitEventHandler(testCommand_Exit);

            //Обработчик нажатия клавиши на клавиатуре или кнопки автоменю
            this.KeyPressed += new KeyEventHandler(testCommand_KeyPressed);

            //Обработчик события вызываемого при необходимости нарисовать курсор на экране
            this.ShowCursor += new MouseEventHandler(testCommand_ShowHideCursor);

            //Обработчик события вызываемого при необходимости стереть курсор с экрана.
            //Может использоваться тот же метод, который обрабатывает событие ShowCursor
            this.HideCursor += new MouseEventHandler(testCommand_ShowHideCursor);

            //Обработчик события необходимости подсветки элемента модели
            repSelectEventHandler = new SelectEventHandler(testCommand_Select);
        }

        //Данное свойство должно возвращать ID, по которой вызывается данная команда
        public override int ID { get { return (int)Commands.Command1; } }

        //Данный метод инициализирует автоменю команды
        void UpdateAutomenu()
        {
            System.Collections.ArrayList list1 = new System.Collections.ArrayList();
            System.Collections.ArrayList list2 = new System.Collections.ArrayList();

            for (int i = 0; i < 8; ++i)
            {
                list2.Add(new SingleButton((int)AutomenuCommands.Number + i,
                    i != 7 ? KeyCode.key3 + i : KeyCode.key0,
                    Button.Style.Default));
            }

            list1.Add(new DefaultButton(DefaultButton.Kind.Parameters));
            list1.Add(new GroupButton("Number",
                list2.ToArray(typeof(Button)) as Button[], 2));
            list1.Add(new SingleButton((int)AutomenuCommands.Command9, KeyCode.keyF,
                Button.Style.Checked));
            list1.Add(new SeparatorButton());
            list1.Add(new DefaultButton(DefaultButton.Kind.Exit));

            Automenu = new Automenu(list1.ToArray(typeof(Button)) as Button[]);
        }

        //Инициализация команды
        private void testCommand_Initialize(object sender, InitializeEventArgs e)
        {
            reptestObject = new testObject();

            this.Select += this.repSelectEventHandler;

            UpdateAutomenu();
        }

        //Выход из команды
        private void testCommand_Exit(object sender, ExitEventArgs e)
        {

        }

        //Обработка нажатии клавиши на клавиатуре или кнопки автоменю
        private void testCommand_KeyPressed(object sender, KeyEventArgs e)
        {
            switch (e.Code)
            {
                //Enter или левая кнопка мыши
                case KeyCode.keyENTER:
                case KeyCode.LMB:
                    {
                        UpdateAutomenu();

                        break;
                    }

                //Escape или правая кнопка мыши
                case KeyCode.keyESCAPE:
                case KeyCode.RMB:
                    //Завершаем работу команды
                    Terminate();
                    UpdateAutomenu();

                    break;

                //Клавиша End
                case KeyCode.keyEND:
                    Terminate();
                    break;

                //Клавиша <P>
                case KeyCode.keyP:
                    {
                        //Обычно здесь происходит задание параметров

                        UpdateAutomenu();
                        break;
                    }
            }
        }

        //Метод, вызываемый для прорисовки или стирания курсора
        private void testCommand_ShowHideCursor(object sender, MouseEventArgs e)
        {
            //Для прорисовки необходимо пользоваться объектом класса Graphics
            Graphics graphics = e.Graphics;

            //Обязательно начать с BeginDraw, а закончить EndDraw
            graphics.BeginDraw();

            //Корсор необходимо выводить при помощи режима XOR (исключающее "или")
            RasterOperation rop = graphics.SetRop(RasterOperation.XOR);
            int color = graphics.SetColor(Graphics.MarkColor);

            //Рисуем создаваемый объект или другой курсор
            reptestObject.DrawCursor(graphics);

            //Возвращаем обратно изменённые режимы
            graphics.Rop = rop;
            graphics.Color = color;

            graphics.EndDraw();
        }

        //Выбираем объект в зависимости от его типа
        private void testCommand_Select(object sender, SelectEventArgs e)
        {
            switch (e.GroupType)
            {
                case ObjectType.Undefined:
                    e.Result = false;
                    break;
                case ObjectType.Node:
                    e.Result = true;
                    break;
            }
        }

    }
}



Реализация класса ProxyObject2D для создания прокси объекта:
Код
//Данный файл обеспечивает реализацию класса объекта модели, создаваемого приложением
using System;
using System.IO;
using System.Runtime.InteropServices;
using TFlex;
using TFlex.Model;
using TFlex.Model.Model2D;
using TFlex.Drawing;

namespace test
{
    //Он должен быть порождён от соответствующего базового класса
    class testObject : ProxyObject2D
    {
        //Конструктор
        public testObject()
        {
        }

        //Конструктор, принимающий родительский объект
        public testObject(IntPtr OwnerHandle)
            : base(OwnerHandle)
        {
        }

        //Метод, сравнивающий данный объект с другим объектом
        protected override bool Equals(ProxyObject obj)
        {
            testObject Other = obj as testObject;

            if (Other == null)
                return false;

            return true;
        }

        //Данный метод возвращает идентификатор типа 
        //Тип объекта является уникальным в пределах приложения и не должен меняться.
        //В соответствии с типом, система вызывает метод CreateObject для создания 
        //объекта приложения при чтении файла, выполнении отмены действий и т.д.
        protected override int TypeID { get { return 1; } }

        //Данный метод возвращает имя типа объекта 
        protected override string TypeName { get { return "test Object"; } }

        //Данный метод возвращает ID иконки объекта
        protected override int IconID { get { return (int)ObjectTypeIcons.testObjectIcon; } }

        //Данное свойство возвращает версию объекта для сохранения её в файл
        protected override int Version { get { return 0; } }

        //Данный метод вызывается при необходимости считывания данных объекта из файла.
        //Параметр Version имеет значение, которое имело свойство Version
        //на момент записи в файл.
        protected override void Read(Stream stream, int Version)
        {
            BinaryReader reader = new BinaryReader(stream);
            //Здесь необходимо реализовать чтение данных объекта

        }

        //Данный метод вызывается при необходимости записи данных объекта в файл.
        protected override void Write(Stream stream)
        {
            BinaryWriter writer = new BinaryWriter(stream);
            //Здесь необходимо реализовать запись данных объекта

        }

        //Данный метод используется в комманде для прорисовки курсора
        public void DrawCursor(Graphics graphics)
        {
            Draw(graphics);
        }

        //Данный метод вызывается при необходимости прорисовки объекта
        protected override void Draw(Graphics graphics)
        {
            //Для прорисовки необходимо пользоваться исключительно методами
            //класса Graphics так как прорисовки ведётся не на экран, а в метафайл
            graphics.BeginDraw();
            //Здесь необходимо реализовать прорисовку объекта

            graphics.EndDraw();
        }


        //Реакция на попытку перетаскивания объекта по экрану
        protected override void CanTransform(TransformContext Context)
        {
            Context.ReturnIgnore();
        }

        //Реакция на перетаскивание объекта по экрану
        protected override bool Transform(TransformContext Context)
        {
            //В случае положительного результата необходимо вернуть true

            return false;
        }

        //Данный метод вызывается при вызове контекстного меню объекта.
        //Здесь можно добавить или удалить команды.
        protected override bool GetContextMenu(Menu Menu)
        {
            Menu.Append((int)ObjectCommands.Command1, "&Первая команда", true, false, OwnerApp);

            return true;
        }

        //Обработка команд объекта
        protected override bool OnCommand(int CommandID, View View)
        {
            switch ((ObjectCommands)CommandID)
            {
                case ObjectCommands.Command1:

                    //Получение документа объекта
                    Document Doc = Owner2D.Document;

                    //Начало изменения объекта
                    Doc.BeginChanges("Изменение объекта test");

                    //Получение копии объекта
                    testObject NewObject = Owner2D.VolatileObject as testObject;

                    //Здесь можно изменить копию объекта (NewObject)

                    //По завершении необходимо вызвать EndChanges или CancelChanges
                    Doc.EndChanges();

                    return true;
            }

            return false;
        }

        //Данный метод вызывается при необходимости редактирования свойств объекта
        protected override PropertyChange EditProperties()
        {
            Document Doc = Owner2D.Document;

            Doc.BeginChanges("Изменение объекта test");

            testObject NewObject = Owner2D.VolatileObject as testObject;

            //Здесь можно вызвать диалог свойств объекта (NewObject)

            Doc.EndChanges();

            return PropertyChange.Regenerate;
        }
    }
}
 
Большое Вам спасибо!
Это, как я понял, для CAD версии не ниже 11 (отсутствуют некоторые конструкторы и ещё пара моментов при компиляции с CAD 10).
 
Да, шаблон для версии 11
 
А что за testObject ?? у меня сишарп на него ругается
 
TestObject - это класс прокси объекта приложения. Какое конкретно сообщение выдает компилятор?
 
Так же для функционирования данного приложения необходимо добавить графические ресурсы (иконки) для команд приложения и автоменю, объектных команд и иконку для объекта. При вставке ссылок в References проекта необходимо в свойствах TFlexAPI.dll (и TFlexAPI3D.dll если используется) выставить свойство CopyLocal в False.

Для того чтобы подключить приложение в TFlex CAD необходимо:
1) создать текстовый файл в папке с собранной бибилотекой проекта (Bin/Debug или Bin/Release);
2) в текстовом файле прописать следующее
Код
[60f4149b-5d3c-4f6f-982e-aadad499346b]
dll=testPlugin.dll
name=Шаблон приложения TFlex CAD
autostart=1
managed=1

где первая строчка - GUID приложения (возвращается свойством ID класса testFactory), вторая - название библиотеки, третья - название приложения, которое будет отображаться в списке активных приложений TFlex'а, четвертая - будет ли приложение запускаться при запуске TFlex CAD, пятая - является ли приложение управляемым (.NET приложением)
3) изменить расширение файла с *.txt на *.tfa

Подключить приложение можно в разделе меню Настройка -> Приложения.
В появившемся окне выбрать вкладку "Приложения .NET", нажать кнопку "Добавить" и в дереве указать путь к папке с *.tfa файлом
 
Скомпилировал пример. Подключил и запустил приложение. Закрыл / открыл T-Flex. При запуске T-Flex трижды появляется сообщение об ошибке (см. рис.). В меню "Сервис" команда не появилась.
Цитата
//Здесь приложение добавляет в главное меню системы свои команды.
//Они появятся в подменю "Сервис"
TFlex.Menu submenu = new TFlex.Menu();
submenu.CreatePopup();

submenu.Append((int)Commands.Command1, "&Первая команда", this);
Пока не понимаю как подключить команду, например, "построить свободный узел".
err.JPG (9.08 КБ)
Изменено: Сергей Максимов - 01.05.2009 20:55:54
 
Судя по тому, что речь идёт о stream, падение происходит при загрузке ресурсов (картинок) из файла. Ведь про них Александр ничего не написал.

Для Вашего случая я бы рекомендовал код упростить. Не нужны Вам ни ресурсы, ни прокси-объекты. Вам нужна только команда, обрабатывающая щелчки в экран и создающая узлы. Кода будет раза в 3 меньше.
 
Закоментировал код, загружающий иконки, но в меню "Сервис" ни одна команда так и не появилась. Не могу пока понять с чего здесь начинать, вроде код хорошо документирован. Нужен пример, уж больно хочеться разобраться - тема интересная. Но видимо сказывается недостаток знаний.
 
Вот упрощённый проект.
Делал на C# Express для учебной версии
 
Возможно, после запуска DLL стоит выполнить "Восстановить начальные установки". Иногда это помогает.
 
Спасибо - хоть увидел как работает в T-Flex. С выбором команд разобрался тоже.
Изменено: Сергей Максимов - 02.05.2009 16:51:43
 
Такой вопрос. Как при работе с плагинами сделать выбор конкретного элемента, получить его имя?
Код
private void selectObj(object sender, SelectEventArgs e)
        {
            SelectionFilter filter = new SelectionFilter();//Фильтр селектора
            filter.DisableAllTypes();
            filter.Enable(ObjectType.Node);//Фильтр по узлам

            Document doc = e.Document;

            //Здесь неверно
            Object2D obj = doc.Selection.Select(filter) as Object2D;

            foreach (Node nodes in doc.Nodes)
            {
                if (nodes.DisplayName == obj.DisplayName)
                {
                    e.Document.BeginChanges("Какие-то действия с узлом");
                    //Какие-то действия с узлом
                    e.Document.EndChanges();
                }
            }
        }
Изменено: Сергей Максимов - 02.05.2009 19:53:37
 
Для получения имени есть свойство Name.
Для добавления элемента в селектор (пометки на экране) можно вызвать что-то типа: document.Selection.Add(obj);

Это если я правильно понял вопрос
Изменено: TFUser - 02.05.2009 23:49:53
 
Например, одна команда создает свободные узлы (или др. построения), другая команда, например, команда создания по узлам линии изображения (текста и т.д.) должна отловить "DisplayName" или "ID" элемента, по которому произведен щелчок мышью (т.е. выбранный элемент). Подозреваю, что это необходимо выполнить в методе "testCommand_Select(object sender, SelectEventArgs e)". Думаю, что этод метод должен в постоянном режиме отслеживать, что именно попадает под курсор, выделять элемент и выдавать подсказку либо с его "DisplayName", либо "ID". Иначе как сказать команде к какому элементу необходимо, например, привязать линию?
Изменено: Сергей Максимов - 03.05.2009 09:50:11
 
Вообще было бы неплохо, если бы в "Руководстве по API" продублировали пример из справки по макросам (построить линию изображения по двум узлам, но разбили бы на две команды, для лучшего понимания). Причем пример нужен как для Control, так и для Plugin под VS2008Exspress.

P.S. в папке API, где установлен T-Flex есть пример звездочки и работает! Буду разбираться.
Изменено: Сергей Максимов - 03.05.2009 10:36:36
 
Цитата
Сергей Максимов пишет:

команда создания по узлам линии изображения (текста и т.д.) должна отловить "DisplayName" или "ID" элемента, по которому произведен щелчок мышью (т.е. выбранный элемент)

Ловить "DisplayName" или "ID" элемента не надо, так как в селектор добавляется именно объект типа ModelObject, а не его идентификатор или другое свойство объекта. Другими словами, если на экране выделены два узла, то в селекторе находятся два объекта типа ModelObject, они же одновременно являются и объектами типа Node.
Изменено: Brom25 - 03.05.2009 13:06:10
Кто ищет - тот всегда найдет!
 
Цитата
Александр Сысоев пишет:
Код
//Данный метод производит обработку команд приложения
protected override void OnCommand(Document document, int id)
{
switch ((Commands)id)
{
    default:
    //В случае получения неизвестной команды необходимо вызвать
    //метод базового класса.
    base.OnCommand(document, id);
    break; 

    case Commands.Command1:
    //Запускаем команду приложения.
    testCommand Command = new testCommand(this);
    Command.Run(document.ActiveView);
    break;
}
}

Когда я увидел этот код, мне стало интересно, можно ли каким-либо образом "поймать" идентификатор одной из стандартных команд? Конкретно, меня интересует команда Сервис>Спецификация>Обновить все.

P.S. Если по хорошему, то мне нужен обработчик события для этой команды, но такового я не нашел. Но можно было бы сделать гибрид из обработчика "регенерация", запускающего мой метод после поимки соответствующего идентификатора вышеуказанной команды...
Изменено: Brom25 - 23.09.2009 21:54:50
Кто ищет - тот всегда найдет!
 
В представленном примере есть строчки

Код
//Здесь приложение добавляет в главное меню системы свои команды. 
//Они появятся в подменю "Сервис" 
TFlex.Menu submenu = new TFlex.Menu(); 
submenu.CreatePopup(); 

submenu.Append((int)Commands.Command1, "&Первая команда", this);  
TFlex.Application.Window .InsertPluginSubMenu("testPlugin", submenu, TFlex.MainWindow .InsertMenuPosition.PluginSamples, this);
Видимо я совсем туплю, но как свою кнопку в меню сделать, а не добавлять команду в уже существующее?
Изменено: Batarejka - 31.10.2012 19:11:37
Страницы: 1 2 След.