Como: adicionar um comando ao menu de atalhoHow to: Add a command to the shortcut menu

É possível adicionar comandos de menu à linguagem específica do domínio (DSL) para que seus usuários possam executar tarefas que são específicas de sua DSL.You can add menu commands to your domain-specific language (DSL) so that your users can perform tasks that are specific to your DSL. Os comandos aparecem no menu de contexto (atalho) quando os usuários clicam com o botão direito do mouse no diagrama.The commands appear on the context (shortcut) menu when users right-click on the diagram. Você pode definir um comando para aparecer no menu apenas em circunstâncias específicas.You can define a command so that it only appears in the menu in specific circumstances. Por exemplo, você pode tornar o comando visível apenas quando o usuário clicar em tipos específicos de elementos ou em elementos em estados específicos.For example, you can make the command visible only when the user clicks specific types of element, or elements in specific states.

Em resumo, as etapas são executadas no projeto DslPackage da seguinte maneira:In summary, the steps are performed in the DslPackage project as follows:

  1. Declare o comando em Commands. vsctDeclare the command in Commands.vsct

  2. Atualize o número de versão do pacote em Package.tt.Update the package version number in Package.tt. Você precisará fazer isso sempre que alterar o Commands.vsctYou have to do this whenever you change Commands.vsct

  3. Escreva métodos na classe commandSet para tornar o comando visível e definir o que você deseja que o comando faça.Write methods in the CommandSet class to make the command visible and to define what you want the command to do.

Observação

Também é possível modificar o comportamento de alguns comandos existentes, tais como Recortar, Colar, Selecionar Tudo e Imprimir substituindo métodos em CommandSet.cs.You can also modify the behavior of some existing commands such as Cut, Paste, Select All, and Print by overriding methods in CommandSet.cs. Para obter mais informações, consulte como modificar um comando de menu padrão.For more information, see How to: Modify a Standard Menu Command.

Definir um comando usando o MEFDefine a Command using MEF

O Managed Extensibility Framework (MEF) fornece um método alternativo de definição de comandos de menu no menu do diagrama.Managed Extension Framework (MEF) provides an alternative method of defining menu commands on the diagram menu. Sua finalidade principal é permitir que uma DSL seja estendida por você ou por outras partes.Its primary purpose is to enable a DSL to be extended by you or by other parties. Os usuários podem optar por instalar apenas a DSL ou podem instalar a DSL e as extensões.Users can choose to install just the DSL, or can install both the DSL and extensions. No entanto, o MEF também reduz o trabalho na definição de comandos de menu de atalho, após o trabalho inicial de permitir o MEF na DSL.However, MEF also reduces the work of defining shortcut menu commands, after the initial work to enable MEF on the DSL.

Use o método neste tópico se:Use the method in this topic if:

  1. Desejar definir comandos de menu nos menus que não sejam os de atalho com clique direito do mouse.You want to define menu commands on menus other than the right-click shortcut menu.

  2. Desejar definir agrupamentos específicos de comandos no menu.You want to define specific groupings of commands in the menu.

  3. Não desejar permitir que outros estendam a DSL com comandos próprios.You do not want to enable others to extend the DSL with their own commands.

  4. Desejar definir apenas um comando.You only want to define one command.

    Caso contrário, considere o uso do método MEF para definir os comandos.Otherwise, consider using the MEF method to define commands. Para obter mais informações, consulte estender sua DSL usando o MEF.For more information, see Extend your DSL by using MEF.

Declare o comando em Commands. vsctDeclare the Command in Commands.Vsct

Os comandos de menu são declarados em DslPackage\Commands.vsct.Menu commands are declared in DslPackage\Commands.vsct. Essas definições especificam os rótulos dos itens de menu e onde eles aparecem nos menus.These definitions specify the labels of the menu items and where they appear on the menus.

O arquivo que você edita, Commands. vsct, importa definições de vários arquivos. h, que estão localizados no diretório caminho de instalação do SDK do Visual Studio\VisualStudioIntegration\Common\Inc. Ele também inclui GeneratedVsct. vsct, que é gerado a partir de sua definição de DSL.The file that you edit, Commands.vsct, imports definitions from several .h files, which are located in the directory Visual Studio SDK install path\VisualStudioIntegration\Common\Inc. It also includes GeneratedVsct.vsct, which is generated from your DSL definition.

Para obter mais informações sobre arquivos. vsct, consulte a tabela de comandos do Visual Studio (. Vsct) arquivos.For more information about .vsct files, see Visual Studio Command Table (.Vsct) Files.

Para adicionar o comandoTo add the command

  1. No Gerenciador de soluções, no projeto DslPackage , abra Commands. vsct.In Solution Explorer, under the DslPackage project, open Commands.vsct.

  2. No elemento Commands, defina um ou mais botões e um grupo.In the Commands element, define one or more buttons and a group. Um botão é um item no menu.A button is an item on the menu. Um grupo é uma seção no menu.A group is a section in the menu. Para definir esses itens, adicione os seguintes elementos:To define these items, add the following elements:

    <!-- Define a group - a section in the menu -->
    <Groups>
      <Group guid="guidCustomMenuCmdSet" id="grpidMyMenuGroup" priority="0x0100">
        <!-- These symbols are defined in GeneratedVSCT.vsct -->
        <Parent guid="guidCmdSet" id="menuidContext" />
      </Group>
    </Groups>
    <!-- Define a button - a menu item - inside the Group -->
    <Buttons>
      <Button guid="guidCustomMenuCmdSet" id="cmdidMyContextMenuCommand"
        priority="0x0100" type="Button">
        <Parent guid="guidCustomMenuCmdSet" id="grpidMyMenuGroup"/>
        <!-- If you do not want to place the command in your own Group,
             use Parent guid="guidCmdSet" id="grpidContextMain".
             These symbols are defined in GeneratedVSCT.vsct -->
        <CommandFlag>DynamicVisibility</CommandFlag>
        <Strings>
          <ButtonText>My Context Menu Command</ButtonText>
        </Strings>
      </Button>
    </Buttons>
    

    Observação

    Cada botão ou grupo é identificado por um GUID e um ID do número inteiro.Each button or group is identified by a GUID and an integer ID. Você pode criar vários grupos e botões com o mesmo GUID.You can create several groups and buttons with the same GUID. No entanto, eles devem ter IDs diferentes.However, they must have different IDs. Os nomes de GUID e nomes de ID são convertidos em GUIDs reais e em IDs numéricas no <Symbols> nó.The GUID names and ID names are translated to actual GUIDs and numeric IDs in the <Symbols> node.

  3. Adicione uma restrição de visibilidade ao comando para que ele seja carregado apenas no contexto de sua linguagem específica do domínio.Add a visibility constraint for the command so that it is loaded only in the context of your domain-specific language. Para obter mais informações, consulte elemento VisibilityConstraints.For more information, see VisibilityConstraints Element.

    Para fazer isso, adicione os seguintes elementos no elemento CommandTable após o elemento Commands.To do this, add the following elements in the CommandTable element after the Commands element.

    <VisibilityConstraints>
      <!-- Ensures the command is only loaded for this DSL -->
      <VisibilityItem guid="guidCustomMenuCmdSet" id="cmdidMyContextMenuCommand"
        context="guidEditor"/>
    </VisibilityConstraints>
    
  4. Defina os nomes que você usou para os GUIDs e IDs.Define the names that you used for the GUIDs and IDs. Para fazer isso, adicione um elemento Symbols no elemento CommandTable após o elemento Commands.To do this, add a Symbols element in the CommandTable element after the Commands element.

    <Symbols>
      <!-- Substitute a unique GUID for the placeholder: -->
      <GuidSymbol name="guidCustomMenuCmdSet"
        value="{00000000-0000-0000-0000-000000000000}" >
        <IDSymbol name="grpidMyMenuGroup" value="0x01001"/>
        <IDSymbol name="cmdidMyContextMenuCommand" value="0x00001"/>
      </GuidSymbol>
    </Symbols>
    
  5. Substitua {000...000} por um GUID que identifica seus grupos e itens de menu.Replace {000...000} with a GUID that identifies your groups and menu items. Para obter um novo GUID, use a ferramenta Criar GUID no menu ferramentas .To obtain a new GUID, use the Create GUID tool on the Tools menu.

    Observação

    Se você adicionar mais grupos ou itens de menu, poderá usar o mesmo GUID.If you add more groups or menu items, you can use the same GUID. No entanto, você deve usar novos valores para o IDSymbols.However, you must use new values for the IDSymbols.

  6. No código copiado deste procedimento, substitua toda ocorrência das seguintes cadeias de caracteres por suas próprias cadeias de caracteres:In the code you have copied from this procedure, replace each occurrence of the following strings with your own strings:

    • grpidMyMenuGroup

    • cmdidMyContextMenuCommand

    • guidCustomMenuCmdSet

    • My Context Menu Command

Atualize a versão do pacote no Package.ttUpdate the Package Version in Package.tt

Sempre que você adicionar ou alterar um comando, atualize o parâmetro version de ProvideMenuResourceAttribute que é aplicado à classe de pacotes antes de liberar a nova versão de sua linguagem específica do domínio.Whenever you add or change a command, update the version parameter of the ProvideMenuResourceAttribute that is applied to the package class before you release the new version of your domain-specific language.

Como a classe de pacotes é definida em um arquivo gerado, atualize o atributo no arquivo de modelo de texto que gera o arquivo Package.cs.Because the package class is defined in a generated file, update the attribute in the text template file that generates the Package.cs file.

Para atualizar o arquivo Package.ttTo update the Package.tt file

  1. No Gerenciador de soluções, no projeto DslPackage , na pasta GeneratedCode , abra o arquivo Package.tt.In Solution Explorer, in the DslPackage project, in the GeneratedCode folder, open the Package.tt file.

  2. Localize o atributo ProvideMenuResource.Locate the ProvideMenuResource attribute.

  3. Incremente o parâmetro version do atributo, que é o segundo parâmetro.Increment the version parameter of the attribute, which is the second parameter. Se desejar, você pode escrever o nome do parâmetro explicitamente para lembrá-lo de sua finalidade.If you want, you can write the parameter name explicitly to remind you of its purpose. Por exemplo:For example:

    [VSShell::ProvideMenuResource("1000.ctmenu", version: 2 )]

Definir o comportamento do comandoDefine the Behavior of the Command

Sua DSL já possui alguns comandos que são implantados em uma classe parcial que é declarada em DslPackage\GeneratedCode\CommandSet.cs.Your DSL already has some commands that are implemented in a partial class that is declared in DslPackage\GeneratedCode\CommandSet.cs. Para adicionar novos comandos, você deve estender essa classe criando um novo arquivo que contém uma declaração parcial da mesma classe.To add new commands, you must extend this class by creating a new file that contains a partial declaration of the same class. O nome da classe geralmente é <YourDslName> CommandSet .The name of the class is usually <YourDslName>CommandSet. É útil começar verificando o nome da classe e inspecionando seu conteúdo.It's useful to begin by verifying the name of the class and inspecting its contents.

A classe do conjunto de comandos é derivada de CommandSet.The command set class is derived from CommandSet.

Estender a classe commandSetExtend the CommandSet class

  1. No Gerenciador de Soluções, no projeto DslPackage, abra a pasta GeneratedCode e procure sob CommandSet.tt e abra o arquivo gerado CommandSet.cs.In Solution Explorer, in the DslPackage project, open the GeneratedCode folder and then look under CommandSet.tt and open its generated file CommandSet.cs. Observe o namespace e o nome da primeira classe que está definida lá.Note the namespace and the name of the first class that is defined there. Por exemplo, é possível ver:For example, you might see:

    namespace Company.Language1

    { ... internal partial class Language1CommandSet : ...

  2. No DslPackage, crie uma pasta chamada código personalizado.In DslPackage, create a folder that is named Custom Code. Nessa pasta, crie um novo arquivo de classe chamado CommandSet.cs .In this folder, create a new class file that is named CommandSet.cs.

  3. No novo arquivo, grave uma declaração parcial que contenha o mesmo namespace e o nome que a classe parcial gerada.In the new file, write a partial declaration that has the same namespace and name as the generated partial class. Por exemplo:For example:

    namespace Company.Language1 /* Make sure this is correct */

    { internal partial class Language1CommandSet { ...

    Observação

    Se você usou o modelo de classe para criar o novo arquivo, deverá corrigir o namespace e o nome da classe.If you used the class template to create the new file, you must correct both the namespace and the class name.

Seu código do conjunto de comandos geralmente precisará importar os seguintes namespaces:Your command set code will typically need to import the following namespaces:

using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Shell;

Ajuste o namespace e o nome da classe para corresponder aos encontrados no CommandSet.cs gerado:Adjust the namespace and the class name to match those in the generated CommandSet.cs:

namespace Company.Language1 /* Make sure this is correct */
{
  // Same class as the generated class.
  internal partial class Language1CommandSet
  {

Você deve definir dois métodos, um para determinar quando o comando ficará visível no menu do botão direito do mouse (contexto) e o outro para executar o comando.You must define two methods, one to determine when the command will be visible on the right-click (context) menu, and the other to perform the command. Esses métodos não são substituições, uma vez que você os registra em uma lista de comandos.These methods are not overrides; instead, you register them in a list of commands.

Defina quando o comando estará visívelDefine when the command will be visible

Para cada comando, defina um OnStatus... método que determina se o comando será exibido no menu e se ele será habilitado ou esmaecido. Defina as Visible Enabled Propriedades e do MenuCommand , conforme mostrado no exemplo a seguir.For each command, define an OnStatus... method that determines whether the command will appear on the menu, and whether it will be enabled or greyed out. Set the Visible and Enabled properties of the MenuCommand, as shown in the following example. Este método é chamado para construir o menu de atalho sempre que o usuário clicar com o botão direito do mouse no diagrama, portanto, é preciso que ele funcione com rapidez.This method is called in order to construct the shortcut menu every time that the user right-clicks the diagram, so it must work quickly.

Neste exemplo, o comando estará visível apenas quando o usuário tiver selecionado um tipo específico de formato e estará habilitado apenas quando pelo menos um dos elementos selecionados estiver em um estado específico.In this example, the command is visible only when the user has selected a particular type of shape, and is enabled only when at least one of the selected elements is in a particular state. O exemplo se baseia no modelo DSL do Diagrama de Classe, e ClassShape e ModelClass são tipos que são definidos na DSL:The example is based on the Class Diagram DSL template, and ClassShape and ModelClass are types that are defined in the DSL:

private void OnStatusMyContextMenuCommand(object sender, EventArgs e)
{
  MenuCommand command = sender as MenuCommand;
  command.Visible = command.Enabled = false;
  foreach (object selectedObject in this.CurrentSelection)
  {
    ClassShape shape = selectedObject as ClassShape;
    if (shape != null)
    {
      // Visibility depends on what is selected.
      command.Visible = true;
      ModelClass element = shape.ModelElement as ModelClass;
      // Enabled depends on state of selection.
      if (element != null && element.Comments.Count == 0)
      {
        command.Enabled = true;
        return; // seen enough
} } } }

Os seguintes fragmentos são geralmente úteis nos métodos OnStatus:The following fragments are frequently useful in OnStatus methods:

  • this.CurrentSelection.this.CurrentSelection. O formato que o usuário clicou com o botão direito do mouse estará sempre incluído nesta lista.The shape that the user right-clicked is always included in this list. Se o usuário clicar em uma parte em branco do diagrama, o Diagrama será o único membro da lista.If the user clicks on a blank part of the diagram, the Diagram is the only member of the list.

  • this.IsDiagramSelected() - true Se o usuário clicou em uma parte em branco do diagrama.this.IsDiagramSelected() - true if the user clicked a blank part of the diagram.

  • this.IsCurrentDiagramEmpty()

  • this.IsSingleSelection() -o usuário não selecionou vários objetosthis.IsSingleSelection() - the user did not select multiple objects

  • this.SingleSelection -a forma ou o diagrama em que o usuário clicou com o botão direitothis.SingleSelection - the shape or diagram that the user right-clicked

  • shape.ModelElement as MyLanguageElement -o elemento de modelo representado por uma forma.shape.ModelElement as MyLanguageElement - the model element represented by a shape.

Como diretriz geral, faça com que a propriedade Visible dependa do que foi selecionado e faça com que a propriedade Enabled dependa do estado dos elementos selecionados.As a general guideline, make the Visible property depend on what is selected, and make the Enabled property depend on the state of the selected elements.

Um método OnStatus não deve alterar o estado do Armazenamento.An OnStatus method should not change the state of the Store.

Defina o que o comando fazDefine what the command does

Para cada comando, defina um método OnMenu... que execute a ação necessária quando o usuário clica no comando de menu.For each command, define an OnMenu... method that performs the required action when the user clicks the menu command.

Se você fizer alterações nos elementos do modelo, deverá fazer isso dentro de uma transação.If you make changes to model elements, you must do so inside a transaction. Para obter mais informações, consulte como modificar um comando de menu padrão.For more information, see How to: Modify a Standard Menu Command.

Neste exemplo, ClassShape, ModelClass e Comment são tipos definidos na DSL, que é derivada do modelo de DSL do Diagrama de Classe.In this example, ClassShape, ModelClass, and Comment are types that are defined in the DSL, which is derived from the Class Diagram DSL template.

private void OnMenuMyContextMenuCommand(object sender, EventArgs e)
{
  MenuCommand command = sender as MenuCommand;
  Store store = this.CurrentDocData.Store;
  // Changes to elements and shapes must be performed in a Transaction.
  using (Transaction transaction =
       store.TransactionManager.BeginTransaction("My command"))
  {
    foreach (object selectedObject in this.CurrentSelection)
    {
      // ClassShape is defined in my DSL.
      ClassShape shape = selectedObject as ClassShape;
      if (shape != null)
      {
        // ModelClass is defined in my DSL.
        ModelClass element = shape.ModelElement as ModelClass;
        if (element != null)
        {
          // Do required action here - for example:

          // Create a new element. Comment is defined in my DSL.
          Comment newComment = new Comment(element.Partition);
          // Every element must be the target of an embedding link.
          element.ModelRoot.Comments.Add(newComment);
          // Set properties of new element.
          newComment.Text = "This is a comment";
          // Create a reference link to existing object.
          element.Comments.Add(newComment);
        }
      }
    }
    transaction.Commit(); // Don't forget this!
  }
}

Para obter mais informações sobre como navegar de objeto para objeto no modelo e sobre como criar objetos e links, consulte como modificar um comando de menu padrão.For more information about how to navigate from object to object in the model, and about how to create objects and links, see How to: Modify a Standard Menu Command.

Registre o comandoRegister the command

Repita em C# as declarações dos valores de GUID e de ID criados na seção Símbolos de CommandSet.vsct:Repeat in C# the declarations of the GUID and ID values that you made in the Symbols section of CommandSet.vsct:

private Guid guidCustomMenuCmdSet =
    new Guid("00000000-0000-0000-0000-000000000000");
private const int grpidMyMenuGroup = 0x01001;
private const int cmdidMyContextMenuCommand = 1;

Use o mesmo valor de GUID que você inseriu em Commands. vsct.Use the same GUID value as you inserted in Commands.vsct.

Observação

Se você alterar a seção Símbolos do arquivo VSCT, deverá também alterar essas declarações para que correspondam.If you change the Symbols section of the VSCT file, you must also change these declarations to match. Você deve também incrementar o número de versão em Package.ttYou should also increment the version number in Package.tt

Registre os comandos de menu como parte deste conjunto de comandos.Register your menu commands as part of this command set. GetMenuCommands() é chamado uma vez quando o diagrama é inicializado:GetMenuCommands() is called once when the diagram is initialized:

protected override IList<MenuCommand> GetMenuCommands()
{
  // Get the list of generated commands.
  IList<MenuCommand> commands = base.GetMenuCommands();
  // Add a custom command:
  DynamicStatusMenuCommand myContextMenuCommand =
    new DynamicStatusMenuCommand(
      new EventHandler(OnStatusMyContextMenuCommand),
      new EventHandler(OnMenuMyContextMenuCommand),
      new CommandID(guidCustomMenuCmdSet, cmdidMyContextMenuCommand));
  commands.Add(myContextMenuCommand);
  // Add more commands here.
  return commands;
}

Testar o comandoTest the Command

Compile e execute a DSL em uma instância experimental do Visual Studio.Build and run the DSL in an experimental instance of Visual Studio. O comando deve aparecer no menu de atalho nas situações especificadas.The command should appear in the shortcut menu in the situations you have specified.

Para exercitar o comandoTo exercise the command

  1. Na barra de ferramentas Gerenciador de soluções , clique em transformar todos os modelos.On the Solution Explorer toolbar, click Transform All Templates.

  2. Pressione F5 para recompilar a solução e iniciar a depuração da linguagem específica do domínio na compilação experimental.Press F5 to rebuild the solution, and start debugging the domain-specific language in the experimental build.

  3. Na compilação experimental, abra o diagrama de amostra.In the experimental build, open a sample diagram.

  4. Clique com o botão direito do mouse em vários itens do diagrama para verificar se o comando está habilitado ou desabilitado corretamente e exibido ou oculto de maneira apropriada, dependendo do item escolhido.Right-click various items in the diagram to verify that the command is correctly enabled or disabled, and appropriately shown or hidden, depending on the selected item.

Solucionar problemasTroubleshoot

O comando não aparece no menu:Command does not appear in menu:

  • O comando aparecerá apenas nas instâncias de depuração do Visual Studio até você instalar o pacote DSL.The command will appear only in debugging instances of Visual Studio, until you install the DSL package. Para obter mais informações, confira Implantando soluções de linguagem específica de domínio.For more information, see Deploying Domain-Specific Language Solutions.

  • Verifique se a sua amostra experimental tem a extensão de nome de arquivo correta para esta DSL.Make sure that your experimental sample has the correct file name extension for this DSL. Para verificar a extensão do nome do arquivo, abra DslDefinition.dsl na instância principal do Visual Studio.To check the file name extension, open DslDefinition.dsl in the main instance of Visual Studio. Em seguida, no Gerenciador de DSL, clique com o botão direito do mouse no nó Editor e clique em Propriedades.Then in DSL Explorer, right-click the Editor node, and then click Properties. Na janela Propriedades, examine a propriedade FileExtension.In the Properties window, examine the FileExtension property.

  • Você incrementa o número de versão do pacote?Did you increment the package version number?

  • Defina um ponto de interrupção no início do método OnStatus.Set a breakpoint at the beginning of your OnStatus method. Ele deve ser interrompido quando você clicar com o botão direito do mouse em qualquer parte do diagrama.It should break when you right-click over any part of the diagram.

O método OnStatus não é chamado:OnStatus method is not called:

  • Verifique se os GUIDs e IDs em seu código CommandSet correspondem aos presentes na seção Símbolos de Commands.vsct.Make sure that the GUIDs and IDs in your CommandSet code match those in the Symbols section of Commands.vsct.

  • Em Commands.vsct, verifique se o GUID e o ID em cada nó pai identificam o grupo pai correto.In Commands.vsct, make sure that the GUID and ID in every Parent node identify the correct parent Group.

  • Em um prompt de comando do Visual Studio, digite devenv /rootsuffix exp /setup.In a Visual Studio command prompt, type devenv /rootsuffix exp /setup. Em seguida, reinicie a instância de depuração do Visual Studio.Then restart the debugging instance of Visual Studio.

  • Repasse o método OnStatus para verificar se command.Visible e command.Enabled estão definidos como true.Step through the OnStatus method to verify that command.Visible and command.Enabled are set to true.

O texto de menu errado aparece, ou o comando aparece no local errado:Wrong menu text appears, or command appears in the wrong place:

  • Certifique-se de que a combinação de GUID e ID seja exclusiva para este comando.Make sure that the combination of GUID and ID is unique to this command.

  • Certifique-se de que você tenha desinstalado as versões anteriores do pacote.Make sure that you have uninstalled earlier versions of the package.

Confira tambémSee also

Observação

O componente de transformação de modelo de texto é instalado automaticamente como parte da carga de trabalho de desenvolvimento de extensão do Visual Studio .The Text Template Transformation component is automatically installed as part of the Visual Studio extension development workload. Você também pode instalá-lo na guia componentes individuais do instalador do Visual Studio, na categoria SDKs, bibliotecas e estruturas .You can also install it from the Individual components tab of Visual Studio Installer, under the SDKs, libraries, and frameworks category. Instale o componente SDK de modelagem da guia componentes individuais .Install the Modeling SDK component from the Individual components tab.