How VSPackages add user interface elements

A VSPackage can add user interface (UI) elements, for example, menus, toolbars, and tool windows, to Visual Studio by means of the .vsct file.

You can find design guidelines for UI elements at Visual Studio user experience guidelines.

The Visual Studio command table architecture

As noted, the command table architecture supports the foregoing architectural principles. The tenets behind the abstractions, data structures, and tools of the command table architecture are as follows:

  • There are three basic kinds of items: menus, commands, and groups. Menus can be exposed in the UI as menus, submenus, toolbars, or tool windows. Commands are procedures that the user can execute in the IDE, and they can be exposed as menu items, buttons, list boxes, or other controls. Groups are containers for both menus and commands.

  • Each item is specified by a definition that describes the item, its priority relative to other items, and the flags that modify its behavior.

  • Each item has a placement that describes the parent of the item. An item can have multiple parents, so that it can appear in multiple locations in the UI.

Every command must have a group as its parent, even if it is the only child in that group. Every standard menu must also have a parent group. Toolbars and tool windows act as their own parents. A group can have as its parent the main Visual Studio menu bar, or any menu, toolbar, or tool window.

How items are defined

A .vsct file is formatted in XML. It defines the UI elements for a package and determines where those elements appear in the IDE. Every menu, group, or command in the package is first assigned a GUID and ID in the Symbols section. Throughout the rest of the .vsct file, each menu, command, and group is identified by its GUID and ID combination. The following example shows a typical Symbols section as generated by the Visual Studio package template when a Menu Command is selected in the template.

<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>

The top-level element of the Symbols section is the GuidSymbol element. GuidSymbol elements map names to GUIDs that are used by the IDE to identify packages and their component parts.

Note

GUIDs are generated automatically by the Visual Studio package template. You can also create a unique GUID by clicking Create GUID on the Tools menu.

The first GuidSymbol element, guid<PackageName>Pkg, is the GUID of the package itself. This is the GUID that is used by Visual Studio to load the package. Typically, it does not have child elements.

By convention, menus and commands are grouped under a second GuidSymbol element, guid<PackageName>CmdSet, and bitmaps are under a third GuidSymbol element, guidImages. You do not have to follow this convention, but each menu, group, command, and bitmap must be a child of a GuidSymbol element.

In the second GuidSymbol element, which represents the package command set, are several IDSymbol elements. Each IDSymbol element maps a name to a numeric value, and may represent a menu, group, or command that is part of the command set. The IDSymbol elements in the third GuidSymbol element represent bitmaps that may be used as icons for commands. Because GUID/ID pairs must be unique in an application, no two children of the same GuidSymbol element may have the same value.

When a menu, group, or command has a GUID and ID, it can be added to the IDE. Every UI element must have the following things:

  • A guid attribute that matches the name of the GuidSymbol element that the UI element is defined under.

  • An id attribute that matches the name of the associated IDSymbol element.

Together, the guid and id attributes compose the signature of the UI element.

  • A priority attribute that determines the placement of the UI element in its parent menu or group.

  • A Parent element that has guid and id attributes that specify the signature of the parent menu or group.

Each menu is defined as a Menu element in the Menus section. Menus must have guid, id, and priority attributes, and a Parent element, and also the following additional attributes and children:

  • A type attribute that specifies whether the menu should appear in the IDE as a kind of menu or as a toolbar.

  • A Strings element that contains a ButtonText element, which specifies the title of the menu in the IDE, and a CommandName element, which specifies the name that is used in the Command window to access the menu.

  • Optional flags. A CommandFlag element may appear in a menu definition to change its appearance or behavior in the IDE.

Every Menu element must have a group as its parent, unless it is a dockable element such as a toolbar. A dockable menu is its own parent. For more information about menus and values for the type attribute, see the Menu element documentation.

The following example shows a menu that appears on the Visual Studio menu bar, next to the Tools menu.

<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>

Groups

A group is an item that is defined in the Groups section of the .vsct file. Groups are just containers. They do not appear in the IDE except as a dividing line on a menu. Therefore, a Group element is defined only by its signature, priority, and parent.

A group can have a menu, another group, or itself as parent. However, the parent is typically a menu or toolbar. The menu in the earlier example is a child of the IDG_VS_MM_TOOLSADDINS group, and that group is a child of the Visual Studio menu bar. The group in the following example is a child of the menu in the earlier example.

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

Because it is part of a menu, this group would typically contain commands. However, it could also contain other menus. This is how submenus are defined, as shown in the following example.

<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>

Commands

A command that is provided to the IDE is defined as either a Button element or a Combo element. To appear on a menu or a toolbar, the command must have a group as its parent.

Buttons

Buttons are defined in the Buttons section. Any menu item, button, or other element that a user clicks to execute a single command is considered a button. Some button types can also include list functionality. Buttons have the same required and optional attributes that menus have, and can also have an Icon element that specifies the GUID and ID of the bitmap that represents the button in the IDE. For more information about buttons and their attributes, see the Buttons element documentation.

The button in the following example is a child of the group in the earlier example, and would appear in the IDE as a menu item on the parent menu of that group.

<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

Combos are defined in the Combos section. Each Combo element represents a drop-down list box in the IDE. The list box may or may not be writable by users, depending on the value of the type attribute of the combo. Combos have the same elements and behavior that buttons have, and can also have the following additional attributes:

  • A defaultWidth attribute that specifies pixel width.

  • An idCommandList attribute that specifies a list that contains the items that are displayed in the list box. The command list must be declared in the same GuidSymbol node that contains the combo.

The following example defines a combo element.

<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

Commands that will be displayed together with an icon must include an Icon element that refers to a bitmap by using its GUID and ID. Each bitmap is defined as a Bitmap element in the Bitmaps section. The only required attributes for a Bitmap definition are guid and href, which points to the source file. If the source file is a resource strip, a usedList attribute is also required, to list the available images in the strip. For more information, see the Bitmap element documentation.

Parenting

The following rules govern how an item can call another item as its parent.

Element Defined in this section of the Command Table May be contained (as a parent, or by placement in the CommandPlacements section, or both) May contain (referred to as a parent)
Group Groups element, the IDE, other VSPackages A menu, a group, the item itself Menus, groups, and commands
Menu Menus element, the IDE, other VSPackages 1 to n groups 0 to n groups
Toolbar Menus element, the IDE, other VSPackages The item itself 0 to n groups
Menu Item Buttons element, the IDE, other VSPackages 1 to n groups, the item itself -0 to n groups
Button Buttons element, the IDE, other VSPackages 1 to n groups, the item itself
Combo Combos element, the IDE, other VSPackages 1 to n groups, the item itself

A menu, group, or command can appear in more than one location in the IDE. For an item to appear in multiple locations, it must be added to the CommandPlacements section as a CommandPlacement element. Any menu, group, or command can be added as a command placement. However, toolbars cannot be positioned in this manner because they cannot appear in multiple context-sensitive locations.

Command placements have guid, id, and priority attributes. The GUID and ID must match those of the item that is positioned. The priority attribute governs the placement of the item with regard to other items. When the IDE merges two or more items that have the same priority, their placements are undefined because the IDE does not guarantee that package resources are read in the same order every time that the package is built.

If a menu or group appears in multiple locations, all children of that menu or group will appear in each instance.

Command visibility and context

When multiple VSPackages are installed, a profusion of menus, menu items, and toolbars may clutter the IDE. To avoid this problem, you can control the visibility of individual UI elements by using visibility constraints and command flags.

Visibility constraints

A visibility constraint is set as a VisibilityItem element in the VisibilityConstraints section. A visibility constraint defines specific UI contexts in which the target item is visible. A menu or command that is included in this section is visible only when one of the defined contexts is active. If a menu or command is not referenced in this section, it is always visible by default. This section does not apply to groups.

VisibilityItem elements must have three attributes, as follows: the guid and id of the target UI element, and context. The context attribute specifies when the target item will be visible, and takes any valid UI context as its value. The UI context constants for Visual Studio are members of the VSConstants class. Every VisibilityItem element can take only one context value. To apply a second context, create a second VisibilityItem element that points to the same item, as shown in the following example.

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

Command flags

The following command flags can affect the visibility of the menus and commands they apply to.

AlwaysCreate Menu is created even if it has no groups or buttons.

Valid for: Menu

CommandWellOnly Apply this flag if the command does not appear on the top-level menu and you want to make it available for additional shell customization, for example, binding it to a key. After the VSPackage is installed, a user can customize these commands by opening the Options dialog box and then editing the command placement under the Keyboard Environment category. Does not affect placement on shortcut menus, toolbars, menu controllers, or submenus.

Valid for: Button, Combo

DefaultDisabled By default, the command is disabled if the VSPackage that implements the command is not loaded or the QueryStatus method has not been called.

Valid for: Button, Combo

DefaultInvisible By default, the command is invisible if the VSPackage that implements the command is not loaded or the QueryStatus method has not been called.

Should be combined with the DynamicVisibility flag.

Valid for: Button, Combo, Menu

DynamicVisibility The visibility of the command can be changed by using the QueryStatus method or a context GUID that is included in the VisibilityConstraints section.

Applies to commands that appear on menus, not on toolbars. Top-level toolbar items can be disabled, but not hidden, when the OLECMDF_INVISIBLE flag is returned from the QueryStatus method.

On a menu, this flag also indicates that it should be automatically hidden when its members are hidden. This flag is typically assigned to submenus because top-level menus already have this behavior.

Should be combined with the DefaultInvisible flag.

Valid for: Button, Combo, Menu

NoShowOnMenuController If a command that has this flag is positioned on a menu controller, the command does not appear in the drop-down list.

Valid for: Button

For more information about command flags, see the CommandFlag element documentation.

General requirements

Your command must pass the following series of tests before it can be displayed and enabled:

  • The command is positioned correctly.

  • The DefaultInvisible flag is not set.

  • The parent menu or toolbar is visible.

  • The command is not invisible because of a context entry in the VisibilityConstraints element section.

  • VSPackage code that implements the IOleCommandTarget interface displays and enables your command. No interface code intercepted it and acted on it.

  • When a user clicks your command, it becomes subject to the procedure that is outlined in Routing algorithm.

Call pre-defined commands

The UsedCommands element enables VSPackages to access commands that are provided by other VSPackages or by the IDE. To do this, create a UsedCommand element that has the GUID and ID of the command to use. This ensures that the command will be loaded by Visual Studio, even if it is not part of the current Visual Studio configuration. For more information, see UsedCommand element.

Interface element appearance

Considerations for selecting and positioning command elements are as follows:

  • Visual Studio offers many UI elements that appear differently depending on placement.

  • A UI element that is defined by using the DefaultInvisible flag will not be displayed in the IDE unless it is either displayed by its VSPackage implementation of the QueryStatus method, or associated with a particular UI context in the VisibilityConstraints section.

  • Even a successfully positioned command may not be displayed. This is because the IDE automatically hides or displays some commands, depending on interfaces that the VSPackage has (or has not) implemented. For example, a VSPackage's implementation of some build interfaces causes build-related menu items to be automatically shown.

  • Applying the CommandWellOnly flag in the definition of UI element means that the command can be added only by customization.

  • Commands may be available only in certain UI contexts, for example, only when a dialog box is displayed when the IDE is in design view.

  • To cause certain UI elements to be displayed in the IDE, you must implement one or more interfaces or write some code.