Como os VSPackages adicionam elementos da interface do usuário

Um VSPackage pode adicionar elementos de interface do usuário (UI), por exemplo, menus, barras de ferramentas e janelas de ferramentas, ao Visual Studio por meio do arquivo .vsct .

Você pode encontrar diretrizes de design para elementos da interface do usuário em Diretrizes de experiência do usuário do Visual Studio.

A arquitetura da tabela de comandos do Visual Studio

Como observado, a arquitetura da tabela de comandos oferece suporte aos princípios de arquitetura anteriores. Os princípios por trás das abstrações, estruturas de dados e ferramentas da arquitetura da tabela de comandos são os seguintes:

  • Há três tipos básicos de itens: menus, comandos e grupos. Os menus podem ser expostos na interface do usuário como menus, submenus, barras de ferramentas ou janelas de ferramentas. Comandos são procedimentos que o usuário pode executar no IDE e podem ser expostos como itens de menu, botões, caixas de listagem ou outros controles. Grupos são contêineres para menus e comandos.

  • Cada item é especificado por uma definição que descreve o item, sua prioridade em relação a outros itens e os sinalizadores que modificam seu comportamento.

  • Cada item tem um posicionamento que descreve o pai do item. Um item pode ter vários pais, para que possa aparecer em vários locais na interface do usuário.

Todo comando deve ter um grupo como pai, mesmo que seja o único filho desse grupo. Cada menu padrão também deve ter um grupo pai. Barras de ferramentas e janelas de ferramentas agem como seus próprios pais. Um grupo pode ter como pai a barra de menus principal do Visual Studio ou qualquer menu, barra de ferramentas ou janela de ferramenta.

Como os itens são definidos

Um arquivo .vsct é formatado em XML. Ele define os elementos da interface do usuário para um pacote e determina onde esses elementos aparecem no IDE. A cada menu, grupo ou comando no pacote é atribuído primeiro um GUID e ID na Symbols seção. No restante do arquivo .vsct, cada menu, comando e grupo é identificado por sua combinação de GUID e ID. O exemplo a seguir mostra uma seção típica Symbols como gerada pelo modelo de pacote do Visual Studio quando um comando de menu é selecionado no modelo.

<Symbols>
  <!-- This is the package guid. -->
  <GuidSymbol name="guidMenuTextPkg" value="{b1253bc6-d266-402b-89e7-5e3d3b22c746}" />

  <!-- This is the guid used to group the menu commands together -->
  <GuidSymbol name="guidMenuTextCmdSet" value="{a633d4e4-6c65-4436-a138-1abeba7c9a69}">
    <IDSymbol name="MyMenuGroup" value="0x1020" />
    <IDSymbol name="cmdidMyCommand" value="0x0100" />
  </GuidSymbol>

  <GuidSymbol name="guidImages" value="{53323d9a-972d-4671-bb5b-9e418480922f}">
    <IDSymbol name="bmpPic1" value="1" />
    <IDSymbol name="bmpPic2" value="2" />
    <IDSymbol name="bmpPicSearch" value="3" />
    <IDSymbol name="bmpPicX" value="4" />
    <IDSymbol name="bmpPicArrows" value="5" />
  </GuidSymbol>
</Symbols>

O elemento de nível superior da Symbols seção é o elemento GuidSymbol. GuidSymbol elementos mapeiam nomes para GUIDs que são usados pelo IDE para identificar pacotes e suas partes componentes.

Observação

GUIDs são gerados automaticamente pelo modelo de pacote do Visual Studio. Você também pode criar um GUID exclusivo clicando em Criar GUID no menu Ferramentas .

O primeiro GuidSymbol elemento, , guid<PackageName>Pkgé o GUID do próprio pacote. Este é o GUID que é usado pelo Visual Studio para carregar o pacote. Normalmente, ele não tem elementos filho.

Por convenção, menus e comandos são agrupados em um segundo GuidSymbol elemento, e bitmaps estão sob um terceiro GuidSymbol elemento, guid<PackageName>CmdSetguidImages. Você não precisa seguir essa convenção, mas cada menu, grupo, comando e bitmap deve ser filho de um GuidSymbol elemento.

No segundo GuidSymbol elemento, que representa o conjunto de comandos do pacote, estão vários IDSymbol elementos. Cada elemento IDSymbol mapeia um nome para um valor numérico e pode representar um menu, grupo ou comando que faz parte do conjunto de comandos. Os IDSymbol elementos no terceiro GuidSymbol elemento representam bitmaps que podem ser usados como ícones para comandos. Como os pares GUID/ID devem ser exclusivos em um aplicativo, nenhum filho do mesmo elemento pode ter o mesmo GuidSymbol valor.

Quando um menu, grupo ou comando tem um GUID e ID, ele pode ser adicionado ao IDE. Cada elemento da interface do usuário deve ter as seguintes coisas:

  • Um guid atributo que corresponde ao GuidSymbol nome do elemento no qual o elemento da interface do usuário é definido.

  • Um id atributo que corresponde ao nome do elemento associado IDSymbol .

Juntos, os guid atributos e id compõem a assinatura do elemento da interface do usuário.

  • Um priority atributo que determina o posicionamento do elemento da interface do usuário em seu menu ou grupo pai.

  • Um elemento Parent que tem guid atributos e id que especificam a assinatura do menu ou grupo pai.

Cada menu é definido como um elemento Menu na Menus seção. Os menus devem ter guid, e atributos, ide um Parent elemento e também os seguintes atributos adicionais e priority filhos:

Cada Menu elemento deve ter um grupo como pai, a menos que seja um elemento encaixável, como uma barra de ferramentas. Um menu encaixável é seu próprio pai. Para obter mais informações sobre menus e valores para o type atributo, consulte a documentação do elemento Menu.

O exemplo a seguir mostra um menu que aparece na barra de menus do Visual Studio, ao lado do menu Ferramentas .

<Menu guid="guidTopLevelMenuCmdSet" id="TopLevelMenu" priority="0x700" type="Menu">
  <Parent guid="guidSHLMainMenu" id="IDG_VS_MM_TOOLSADDINS" />
  <Strings>
    <ButtonText>TestMenu</ButtonText>
    <CommandName>TestMenu</CommandName>
  </Strings>
</Menu>

Grupos

Um grupo é um item definido na Groups seção do arquivo .vsct . Os grupos são apenas contêineres. Eles não aparecem no IDE, exceto como uma linha divisória em um menu. Portanto, um elemento Group é definido apenas por sua assinatura, prioridade e pai.

Um grupo pode ter um menu, outro grupo ou ele mesmo como pai. No entanto, o pai é normalmente um menu ou barra de ferramentas. O menu no exemplo anterior é um filho do IDG_VS_MM_TOOLSADDINS grupo, e esse grupo é um filho da barra de menus do Visual Studio. O grupo no exemplo a seguir é um filho do menu no exemplo anterior.

<Group guid="guidTopLevelMenuCmdSet" id="MyMenuGroup" priority="0x0600">
  <Parent guid="guidTopLevelMenuCmdSet" id="TopLevelMenu"/>
</Group>

Como faz parte de um menu, esse grupo normalmente conteria comandos. No entanto, ele também pode conter outros menus. É assim que os submenus são definidos, conforme mostrado no exemplo a seguir.

<Menu guid="guidTopLevelMenuCmdSet" id="SubMenu" priority="0x0100" type="Menu">
  <Parent guid="guidTopLevelMenuCmdSet" id="MyMenuGroup"/>
  <Strings>
    <ButtonText>Sub Menu</ButtonText>
    <CommandName>Sub Menu</CommandName>
  </Strings>
</Menu>

Comandos

Um comando fornecido ao IDE é definido como um elemento Button ou um elemento Combo. Para aparecer em um menu ou barra de ferramentas, o comando deve ter um grupo como pai.

Botões

Os botões são definidos na Buttons seção . Qualquer item de menu, botão ou outro elemento que um usuário clica para executar um único comando é considerado um botão. Alguns tipos de botão também podem incluir a funcionalidade de lista. Os botões têm os mesmos atributos obrigatórios e opcionais que os menus e também podem ter um elemento Icon que especifica o GUID e a ID do bitmap que representa o botão no IDE. Para obter mais informações sobre botões e seus atributos, consulte a documentação do elemento Buttons.

O botão no exemplo a seguir é um filho do grupo no exemplo anterior e apareceria no IDE como um item de menu no menu pai desse grupo.

<Button guid="guidTopLevelMenuCmdSet" id="cmdidTestCommand" priority="0x0100" type="Button">
  <Parent guid="guidTopLevelMenuCmdSet" id="MyMenuGroup" />
  <Icon guid="guidImages" id="bmpPic1" />
  <Strings>
    <CommandName>cmdidTestCommand</CommandName>
    <ButtonText>Test Command</ButtonText>
  </Strings>
</Button>
Combos

Os combos são definidos na Combos seção. Cada Combo elemento representa uma caixa de listagem suspensa no IDE. A caixa de listagem pode ou não ser gravável pelos usuários, dependendo do valor do type atributo da combinação. As combinações têm os mesmos elementos e comportamento que os botões e também podem ter os seguintes atributos adicionais:

  • Um defaultWidth atributo que especifica a largura do pixel.

  • Um idCommandList atributo que especifica uma lista que contém os itens que são exibidos na caixa de listagem. A lista de comandos deve ser declarada no mesmo GuidSymbol nó que contém a combinação.

O exemplo a seguir define um elemento de combinação.

<Combos>
  <Combo guid="guidFirstToolWinCmdSet"
         id="cmdidWindowsMediaFilename"
         priority="0x0100" type="DynamicCombo"
         idCommandList="cmdidWindowsMediaFilenameGetList"
         defaultWidth="130">
    <Parent guid="guidFirstToolWinCmdSet"
            id="ToolbarGroupID" />
    <CommandFlag>IconAndText</CommandFlag>
    <CommandFlag>CommandWellOnly</CommandFlag>
    <CommandFlag>StretchHorizontally</CommandFlag>
    <Strings>
      <CommandName>Filename</CommandName>
      <ButtonText>Enter a Filename</ButtonText>
    </Strings>
  </Combo>
</Combos>
Bitmaps

Os comandos que serão exibidos junto com um ícone devem incluir um elemento que se refira a um Icon bitmap usando seu GUID e ID. Cada bitmap é definido como um elemento Bitmap na Bitmaps seção. Os únicos atributos necessários para uma Bitmap definição são guid e href, que aponta para o arquivo de origem. Se o arquivo de origem for uma faixa de recursos, um atributo usedList também será necessário para listar as imagens disponíveis na faixa. Para obter mais informações, consulte a documentação do elemento Bitmap.

Gerenciamento do domínio pai

As regras a seguir regem como um item pode chamar outro item como seu pai.

Element Definido nesta seção da Tabela de Comandos Pode estar contido (como pai, ou por colocação na CommandPlacements seção, ou ambos) Pode conter (referido como um pai)
Grupo Elemento Groups, o IDE, outros VSPackages Um menu, um grupo, o próprio item Menus, grupos e comandos
Menu Elemento Menus, o IDE, outros VSPackages 1 a n grupos 0 a n grupos
Barra de ferramentas Elemento Menus, o IDE, outros VSPackages O item em si 0 a n grupos
Item de menu Elemento Buttons, o IDE, outros VSPackages 1 a n grupos, o item em si -0 a n grupos
Botão Elemento Buttons, o IDE, outros VSPackages 1 a n grupos, o item em si
Combinação Combos elemento, o IDE, outros VSPackages 1 a n grupos, o item em si

Um menu, grupo ou comando pode aparecer em mais de um local no IDE. Para que um item apareça em vários locais, ele deve ser adicionado à CommandPlacements seção como um elemento CommandPlacement. Qualquer menu, grupo ou comando pode ser adicionado como um posicionamento de comando. No entanto, as barras de ferramentas não podem ser posicionadas dessa maneira porque não podem aparecer em vários locais sensíveis ao contexto.

Os posicionamentos de comando têm guidatributos , ide priority . O GUID e a ID devem corresponder aos do item posicionado. O priority atributo rege o posicionamento do item em relação a outros itens. Quando o IDE mescla dois ou mais itens que têm a mesma prioridade, seus posicionamentos são indefinidos porque o IDE não garante que os recursos do pacote sejam lidos na mesma ordem toda vez que o pacote é criado.

Se um menu ou grupo aparecer em vários locais, todos os filhos desse menu ou grupo aparecerão em cada instância.

Visibilidade e contexto do comando

Quando vários VSPackages são instalados, uma profusão de menus, itens de menu e barras de ferramentas pode bagunçar o IDE. Para evitar esse problema, você pode controlar a visibilidade de elementos individuais da interface do usuário usando restrições de visibilidade e sinalizadores de comando.

Restrições de visibilidade

Uma restrição de visibilidade é definida como um elemento VisibilityItem na VisibilityConstraints seção. Uma restrição de visibilidade define contextos de interface do usuário específicos nos quais o item de destino é visível. Um menu ou comando incluído nesta seção fica visível somente quando um dos contextos definidos está ativo. Se um menu ou comando não for referenciado nesta seção, ele estará sempre visível por padrão. Esta seção não se aplica a grupos.

VisibilityItem os elementos devem ter três atributos, da seguinte maneira: o guid e do elemento da interface do usuário de destino e id context. O context atributo especifica quando o item de destino ficará visível e usa qualquer contexto de interface do usuário válido como seu valor. As constantes de contexto da interface do usuário para Visual Studio são membros da VSConstants classe. Cada VisibilityItem elemento pode ter apenas um valor de contexto. Para aplicar um segundo contexto, crie um segundo VisibilityItem elemento que aponte para o mesmo item, conforme mostrado no exemplo a seguir.

<VisibilityConstraints>
  <VisibilityItem guid="guidSolutionToolbarCmdSet"
        id="cmdidTestCmd"
        context="UICONTEXT_SolutionHasSingleProject" />
  <VisibilityItem guid="guidSolutionToolbarCmdSet"
        id="cmdidTestCmd"
        context="UICONTEXT_SolutionHasMultipleProjects" />
</VisibilityConstraints>

Sinalizadores de comando

Os sinalizadores de comando a seguir podem afetar a visibilidade dos menus e comandos aos quais se aplicam.

AlwaysCreate O menu é criado mesmo que não tenha grupos ou botões.

Válido para: Menu

CommandWellOnly Aplique esse sinalizador se o comando não aparecer no menu de nível superior e você quiser disponibilizá-lo para personalização adicional do shell, por exemplo, vinculando-o a uma chave. Depois que o VSPackage é instalado, um usuário pode personalizar esses comandos abrindo a caixa de diálogo Opções e, em seguida, editando o posicionamento do comando na categoria Ambiente do teclado . Não afeta o posicionamento em menus de atalho, barras de ferramentas, controladores de menu ou submenus.

Válido para: Button, Combo

DefaultDisabled Por padrão, o comando será desabilitado se o VSPackage que implementa o comando não for carregado ou o método QueryStatus não tiver sido chamado.

Válido para: Button, Combo

DefaultInvisible Por padrão, o comando será invisível se o VSPackage que implementa o comando não for carregado ou o método QueryStatus não tiver sido chamado.

Deve ser combinado com a DynamicVisibility bandeira.

Válido para: Button, , Combo, Menu

DynamicVisibility A visibilidade do comando pode ser alterada usando o QueryStatus método ou um GUID de contexto incluído na VisibilityConstraints seção .

Aplica-se a comandos que aparecem em menus, não em barras de ferramentas. Os itens da barra de ferramentas de nível superior podem ser desabilitados, mas não ocultos, quando o OLECMDF_INVISIBLE sinalizador é retornado do QueryStatus método.

Em um menu, esse sinalizador também indica que ele deve ser automaticamente oculto quando seus membros estão ocultos. Esse sinalizador normalmente é atribuído a submenus porque os menus de nível superior já têm esse comportamento.

Deve ser combinado com a DefaultInvisible bandeira.

Válido para: Button, , Combo, Menu

NoShowOnMenuController Se um comando que tem esse sinalizador estiver posicionado em um controlador de menu, o comando não aparecerá na lista suspensa.

Válido para: Button

Para obter mais informações sobre sinalizadores de comando, consulte a documentação do elemento CommandFlag.

Requisitos gerais

Seu comando deve passar na seguinte série de testes antes de poder ser exibido e habilitado:

  • O comando está posicionado corretamente.

  • A DefaultInvisible bandeira não está definida.

  • O menu pai ou a barra de ferramentas está visível.

  • O comando não é invisível devido a uma entrada de contexto na seção do elemento VisibilityConstraints.

  • O código VSPackage que implementa a IOleCommandTarget interface exibe e habilita o comando. Nenhum código de interface o interceptou e agiu sobre ele.

  • Quando um usuário clica no comando, ele fica sujeito ao procedimento descrito no algoritmo de roteamento.

Chamar comandos predefinidos

O elemento UsedCommands permite que VSPackages acessem comandos fornecidos por outros VSPackages ou pelo IDE. Para fazer isso, crie um elemento UsedCommand que tenha o GUID e a ID do comando a ser usado. Isso garante que o comando será carregado pelo Visual Studio, mesmo se ele não faz parte da configuração atual do Visual Studio. Para obter mais informações, consulte UsedCommand element.

Aparência do elemento de interface

As considerações para selecionar e posicionar elementos de comando são as seguintes:

  • O Visual Studio oferece muitos elementos de interface do usuário que aparecem de forma diferente dependendo do posicionamento.

  • Um elemento de interface do usuário definido usando o DefaultInvisible sinalizador não será exibido no IDE, a menos que seja exibido por sua implementação VSPackage do método ou associado a um contexto de interface do QueryStatus usuário específico na VisibilityConstraints seção .

  • Mesmo um comando posicionado com êxito pode não ser exibido. Isso ocorre porque o IDE oculta ou exibe automaticamente alguns comandos, dependendo das interfaces que o VSPackage implementou (ou não). Por exemplo, a implementação de um VSPackage de algumas interfaces de compilação faz com que os itens de menu relacionados à compilação sejam mostrados automaticamente.

  • Aplicar o sinalizador na definição do elemento UI significa que o CommandWellOnly comando pode ser adicionado somente pela personalização.

  • Os comandos podem estar disponíveis somente em determinados contextos de interface do usuário, por exemplo, somente quando uma caixa de diálogo é exibida quando o IDE está no modo de design.

  • Para fazer com que determinados elementos da interface do usuário sejam exibidos no IDE, você deve implementar uma ou mais interfaces ou escrever algum código.