Implementing Menu Commands for Optimal Availability

When multiple VSPackages are added to Visual Studio, the user interface (UI) may become overcrowded with commands. You can program your package to help reduce this problem, as follows:

  • Program the package so that it is loaded only when a user requires it.

  • Program the package so that its commands are displayed only when they may be required in the context of the current state of the integrated development environment (IDE).

Delayed Loading

The typical way to enable delayed loading is to design the VSPackage so that its commands are displayed in the UI, but the package itself is not loaded until a user clicks one of the commands. To accomplish this, in the .vsct file, create commands that have no command flags.

The following example shows the definition of a menu command from a .vsct file. This is the command that is generated by the Visual Studio Integration Package Wizard when the Menu Command option in the wizard is selected.

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

In the example, if the parent group, MyMenuGroup, is a child of a top-level menu such as the Tools menu, the command will be visible on that menu, but the package that executes the command will not be loaded until the command is clicked by a user. However, by programming the command to implement the IOleCommandTarget interface, you can enable the package to be loaded when the menu that contains the command is first expanded.

Notice that delayed loading may also improve start-up performance.

Current Context and the Visibility of Commands

You can program VSPackage commands to be visible or hidden, depending on the current state of the VSPackage data or the actions that are currently relevant. You can enable the VSPackage to set the state of its commands, typically by using an implementation of the QueryStatus method from the IOleCommandTarget interface, but this requires the VSPackage to be loaded before it can execute the code. Instead, we recommend that you enable the IDE to manage the visibility of the commands without loading the package. To do this, in the .vsct file, associate commands with one or more special UI contexts. These UI contexts are identified by a GUID known as a command context GUID.

Visual Studio monitors changes that result from user actions such as loading a project or going from editing to building. As changes occur, the appearance of the IDE is automatically modified. The following table shows four major contexts of IDE change that Visual Studio monitors.

Type of Context

Description

Active Project Type

For most project types, this GUID value is the same as the GUID of the VSPackage that implements the project. However, Visual C++ projects use the Project Type GUID as the value.

Active Window

Typically, this is the last active document window that establishes the current UI context for key bindings. However, it could also be a tool window that has a key binding table that resembles the internal Web browser. For multi-tabbed document windows such as the HTML editor, every tab has a different command context GUID.

Active Language Service

The language service that is associated with the file that is currently displayed in a text editor.

Active Tool Window

A tool window that is open and has focus.

A fifth major context area is the UI state of the IDE. UI contexts are identified by active command context GUIDs, as follows:

These GUIDs are marked as active or inactive, depending on the current state of the IDE. Multiple UI contexts can be active at the same time.

Hiding and Displaying Commands Based on Context

You can display or hide a package command in the IDE without loading the package itself. To do this, define the command in the .vsct file of the package by using the DefaultDisabled, DefaultInvisible, and DynamicVisibility command flags and adding one or more VisibilityItem Element entries to the VisibilityConstraints Element section. When a specified command context GUID becomes active, the command is displayed without loading the package.

Custom Context GUIDs

If an appropriate command context GUID is not already defined, you can define one in your VSPackage and then program it to be active or inactive as required to control the visibility of your commands. Use the SVsShellMonitorSelection service to:

  • Register context GUIDs (by calling the GetCmdUIContextCookie method).

  • Get the state of a context GUID (by calling the IsCmdUIContextActive method).

  • Turn context GUIDs on and off (by calling the SetCmdUIContext method).

    Warning

    Make sure that your VSPackage does not affect the state of any existing context GUID because other VSPackages may depend on them.

Example

The following example of a VSPackage command demonstrates the dynamic visibility of a command that is managed by command contexts without loading the VSPackage.

The command is set to be enabled and displayed whenever a solution exists; that is, whenever one of the following command context GUIDs is active:

In the example, notice that every command flag is a separate Command Flag Element.

<Button guid="guidDynamicVisibilityCmdSet" id="cmdidMyCommand" 
        priority="0x0100" type="Button">
  <Parent guid="guidDynamicVisibilityCmdSet" id="MyMenuGroup" />
  <Icon guid="guidImages" id="bmpPic1" />
  <CommandFlag>DefaultDisabled</CommandFlag>
  <CommandFlag>DefaultInvisible</CommandFlag>
  <CommandFlag>DynamicVisibility</CommandFlag>
  <Strings>
    <CommandName>cmdidMyCommand</CommandName>
    <ButtonText>My Command name</ButtonText>
  </Strings>
</Button>

Also notice that every UI context must be given in a separate VisibilityItem element, as follows.

<VisibilityConstraints>
  <VisibilityItem guid="guidDynamicVisibilityCmdSet"
                  id="cmdidMyCommand" context="UICONTEXT_EmptySolution" />
  <VisibilityItem guid="guidDynamicVisibilityCmdSet"
                      id="cmdidMyCommand" context="UICONTEXT_SolutionHasSingleProject" />
  <VisibilityItem guid="guidDynamicVisibilityCmdSet"
                  id="cmdidMyCommand" context="UICONTEXT_SolutionHasMultipleProjects" />
</VisibilityConstraints>

See Also

Tasks

How to: Create and Handle Commands in VSPackages (C#)

How to: Dynamically Add Menu Items

Concepts

How VSPackages Add User Interface Elements to the IDE

Other Resources

Command Routing in VSPackages