Pular para o conteúdo principal

Criando um palette dinâmico no AutoCAD para comandos e métodos usando o .NET

Eu queria criar um palette para colocar uma família de funções para alguns amigos meus que não usam .NET. Na verdade eu sempre faço alguns pequenos comandos e funções no trabalho para auxiliar as pessoas a realizarem o trabalho mais rapidamente. Todos esses comandos eu somei em uma única DLL.

O fato é que depois que eu o faço simplesmente esqueço que já fiz então tenho que buscar o comando no programa ou como, já aconteceu, fazer novamente a mesma coisa...

Resolvi então fazer um palette onde coloco dinamicamente os comandos como botões.

O palette em si é um objeto do Windows.Forms então basicamente o que queremos é fazer um código para criar dinamicamente um formulário do Windows.

O primeiro passo foi descobrir como chamar os comandos de maneira sistemática a partir dos botões. Para isso existe os tipos personalizados de do atributo CommandMethod (). Criei um comando - denominado MeusComandos, para MyCmdListPalette - que usa expressão do módulo principal do assembly em execução para extrair os vários comandos e métodos de interesse, isso é interessante.
Os comandos são chamados usando DocumentCollection.ExecuteInCommandContextAsync() que se trata de uma maneira de chamar um comando do contexto da sessão. Listado os botões com os nomes das funções pode se utilizar método MethodInfo.Invoke () para chamar a execução dos comandos.

Código em C#:

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Windows;
using WinForms = System.Windows.Forms;


namespace MeusComandos

{
    // The basic attribute we'll use to tag the methods/commands to place
    // on the palette

    [AttributeUsage(AttributeTargets.Method)]
    public class PaletteMethod : Attribute { }

    public class Commandos
    {
        private static PaletteSet _ps = null;


        // Comando principal para incluri a palette na tela
        [PaletteMethod]
        [CommandMethod("MeusComandos")]
        public void MyCmdListPalette()
        {
            if (_ps == null)
            {
                var doc = Application.DocumentManager.MdiActiveDocument;
                if (doc == null) return;
                var ed = doc.Editor;

                // Invocação da classe para saber todas as suas entidades.
                var asm = Assembly.GetExecutingAssembly();
                var type = asm.GetType("MeusComandos.Commandos");
                if (type == null)
                {
                    ed.WriteMessage("\nClasse não encontrada.");
                    return;
                }

                //Criando um botão para cada chamada dessa classe..
                var bs = new List<WinForms.Button>();
                var i = 1;

                //loop de criação dos botões
                foreach (var m in type.GetMethods())
                {
                    var cmdName = "";
                    var palette = false;

                    //Verifica poelos atributos se deve ser uma função que vai ter 
                    //botão ou não pelo metodo "PaletteMethod".
                    foreach (var a in m.CustomAttributes)
                    {
                        if (a.AttributeType.Name == "CommandMethodAttribute")
                        {
                            cmdName = (string)a.ConstructorArguments[0].Value;
                        }
                        else if (a.AttributeType.Name == "PaletteMethod")
                        {
                            palette = true;
                        }
                    }

                    // Criação do bão propriamente dita
                    if (palette)
                    {
                        //Cria o objeto botão Windows.Forms e depois 
                        // lhe dá uma posição.
                        var b = new WinForms.Button();
                        b.SetBounds(50, 40 * i, 100, 30);

                        // trata o nome do botão.
                        if (String.IsNullOrEmpty(cmdName))
                        {
                            b.Text = m.Name;
                            b.Click +=
                              (s, e) =>
                              {
                                  var b2 = (WinForms.Button)s;
                                  var mi = type.GetMethod(b2.Text);
                                  if (mi != null)
                                  {
                                      //usara o Invoke para chamar os comandos com os argumentos
                                      //Cria um "trigger" de ativação do comando com o botão
                                      mi.Invoke(this, null);
                                  }
                              };
                        }
                        else
                        {
                            // OU executando o comando de maneira assrincona, 
                            //bom para comandos que chamam outros desenhos ou ainda
                            //que demoram para ser executados.

                            b.Text = cmdName;
                            b.Click +=
                              async (s, e) =>
                              {
                                  var dm = Application.DocumentManager;
                                  var doc2 = dm.MdiActiveDocument;
                                  if (doc2 == null) return;

                                  var ed2 = doc2.Editor;

                                  await dm.ExecuteInCommandContextAsync(
                      async (obj) =>
                                  {
                                      await ed2.CommandAsync("_." + cmdName);
                                  },
                      null
                    );
                              };
                        }
                        bs.Add(b);
                        i++;
                    }
                }

                //Cria o palette, ou o UserControl como é chamando no Windows.Forms
                var uc = new WinForms.UserControl();
                uc.Controls.AddRange(bs.ToArray());

                //cria o palette
                _ps = new PaletteSet("PC", new Guid("00112233-4455-6677-8899-aabbccddeeff"));
                _ps.Add("AUTOCADNETBLOGCMDPALETTE", uc);
                _ps.DockEnabled = (DockSides)(DockSides.Left | DockSides.Right);
            }

            _ps.Visible = true;
        }


        // AS FUNÇÕES QUE SERÃO MOSYTRADAS NO POALLET

        // Uma função qualquer que não serã mostrada incluicad como botão
        private static void funcaoqq(string str, bool postPrompt = true)
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            doc.Editor.WriteMessage("\n {0}\n", str);            
        }

 
        [PaletteMethod]
        public void MeuNome()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            doc.Editor.WriteMessage("\n Seu nome é {0}\n", doc.Name );
            
        }

        [PaletteMethod]
        public void OlaMundo()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            string str1 = "Olá Mundo";
            doc.Editor.WriteMessage("\n {0}\n", str1);
        }

        [PaletteMethod]
        public void Method3()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            doc.Editor.WriteMessage("\n Método do Palet 3 \n");

        }
                

        [PaletteMethod]
        [CommandMethod("CMD_TESTE")]
        public static void CommandTest()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            doc.Editor.WriteMessage("Este é um comando TESTE e também é um botão!", false);
        }
    }
}

Realmente esse é um recurso bem útil para qualquer pessoa que esteja interessada em ter um guia com seus comandos.

Vídeo Exemplo de Utilização:



Código em Visual Studio 2019: Download.

Comentários

Postagens mais visitadas deste blog

Numeração Automática no AutoCAD

Sem dúvida esse é uma ferramenta única que fazia falta a tempos e foi introduzida recentemente no AutoCAD, na última década… Em 2013 tinha feito um programa para criar uma bolinhas de numeração automática usando o conceito de Leader eu fazia um controle dos números dos itens na mão mesmo, depois de um tempo resolvi fazer um menuzinho para controlar o conteúdo do número dos bullets, hoje isso não é mais necessário, existe um comando no próprio AutoCAD para isso e faz parte das Ferramentas Expressas do AutoCAD. Gosto de compartilhar ferramentas e dicas que tendem a ser menos conhecidas ou subutilizadas, mas ainda podem fornecer um impulso para sua produtividade e fluxo de trabalho e que eu mesmo me surpreendi quando as encontrei Hoje, quero apresentar outra ferramenta, a numeração automática. Como o nome indica, o comando Numeração automática permite que você adicione automaticamente um número às etiquetas ou texto em um desenho. Vou mostrar como a numeração automática pode ser usada par...

Alterar a cor de fundo do AutoCAD

Eu sou um adepto do fundo preto, tudo que eu posso mudo a cor do fundo para preto. Nas ultimas versões do AutoCAD tenho notado que não é mais o padrão o fundo preto absoluto, é um cinza escuro. As vezes gosto também de mudar a cor do Layout de branco para preto afinal de contas quando trabalhamos com penas e contraste no model space preto, ver um desenho no layout é impossível.  Você pode mudar sua cor de fundo do AutoCAD para a cor que quiser. Definindo cores personalizadas Primeiro, vá para o menu Opções (botão Aplicativo> Opções), selecione a guia Exibição e clique no botão Cores. Agora você deve ver a caixa de diálogo Cores da janela de desenho: Agora você pode atualizar as cores de qualquer elemento da interface. Isso incluí o plano de fundo em qualquer contexto (selecione Model e Layout). Você pode escolher qualquer uma das predefinições, ou você pode escolher a partir de todo o espectro (basta escolher a opção Selecionar Cor ...). Se você não gost...

Unindo blocos em AutoCAD utilizando .NET

Hoje me deparai com uma necessidade de unir blocos com propriedades então resolvi fazer um comando para realizar esses procedimento. A principio esse procedimento não é tão complexo de ser executado individualmente mas por outro lado gostaria também de analisar um pouco melhor as possibilidades de se manipular blocos utilizando o AutoCAD. Abaixo o código que utilizei: using Autodesk.AutoCAD.ApplicationServices ; using Autodesk.AutoCAD.DatabaseServices ; using Autodesk.AutoCAD.EditorInput ; using Autodesk.AutoCAD.Runtime ; using System.Linq ; // This line is not mandatory, but improves loading performances [assembly: CommandClass(typeof(Merging_AutoCAD_blocks.Comandos))] namespace Merging_AutoCAD_blocks { public class Comandos { /// <summary> /// Uni dois ou mais blocos em um unico bloco. /// </summary> [CommandMethod("MERGBLKS")] public static void UnindoBlocos () {...