Поделиться через


How VSPackages Add User Interface Elements to the IDE

A VSPackage can add user interface (UI) elements, for example, menus, toolbars, and tool windows, to the Visual Studio integrated development environment (IDE).

Architectural Principles

The set of rules and structures that enable a VSPackage to customize the UI is named the Command Table Architecture. The Command Table Architecture is based on the following design principles:

  • The UI should not be cluttered or confusing.

  • The UI should be dynamic, not static.

  • The UI should be customizable.

  • The UI should be helpful.

The UI Should Not Be Cluttered or Confusing

  • Several VSPackages may be installed in the Visual Studio session that hosts your VSPackage. When your VSPackage adds commands, it must not break previously installed VSPackages, but it should also make its features available to the other VSPackages and enable them to contribute features in return.

  • Every menu, whether it is accessed by using the main menu bar, a submenu, or a shortcut menu, can contain menu items that are contributed by other VSPackages. Therefore, be careful not to overcrowd the UI. If too many commands are displayed at the same time, the UI may confuse users.

The UI Should Be Dynamic, Not Static

  • Commands can be displayed or hidden at any time, depending on the state of the underlying data and the current user activity.

  • A VSPackage must be enabled to change the label of a UI item, and also the contents of its combo boxes or menus.

  • UI items may have to be added or removed when the VSPackage is used.

  • UI items may require additional calls to the VSPackage to populate their values or detect their current state. Examples of these items include lists of most-recently-used (MRU) files, combo boxes, and selectors for color or texture.

  • It may improve the user experience to add your command to menus in other VSPackages. For example, if the command that you provide resembles Copy, you can put your command in every VSPackage where Copy appears.

The UI Should Be Customizable

  • At any time, a user can customize the UI elements in your VSPackage, for example, by adding a button to a tool window or rearranging a menu. However, in some cases, you may want to disable customization.

  • Some commands are available only by using customization; that is, a command might not be available on a menu or toolbar until a user adds it by using the Customize dialog box.

  • At any time, a user can customize the keyboard shortcuts for your commands, together with the keyboard shortcuts of commands that come from Visual Studio and other VSPackages.

  • Your commands can be executed by using the Command window. Therefore, the IDE has to know which command corresponds to a particular command label. The IDE accomplishes this by using a process known as canonicalization, where spaces are removed to compress a command name into a single word. For example, the canonicalization of '&File Open' is 'FileOpen'.

The UI Should Be Helpful

  • Most UI items should have tooltips.

  • For better performance, your VSPackage should load only when one of its functions is invoked. This is known as "delayed loading."

  • Additions to the IDE requested by a VSPackage should be localizable.

  • You can use bitmaps that are included in Visual Studio or you can provide your own.

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

.Vsct files are formatted in XML. A .vsct file 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 Command Flag 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 Command Flag 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 Command Routing Algorithm.

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

See Also

Other Resources

Common Tasks with Commands, Menus, and Toolbars

Command Table Configuration (.ctc) Files

Command Table Format Reference

Command Routing in VSPackages

Implementing Menu Commands for Optimal Availability