다음을 통해 공유


Best Practices for Implementing Menu and Toolbar Commands

참고

Beginning with Visual Studio 2008 SDK, use XML Command Table (.vsct) files instead of command table configuration (.ctc) files to define how menus and commands appear in your VSPackages. For more information, see XML-Based Command Table Configuration (.vsct) Files.

Adding multiple VSPackages with their corresponding commands to Visual Studio can quickly lead to an overcrowded UI. There are two ways you can help reduce the clutter: by avoiding or delaying VSPackage loading, and by designing the package so that it displays only the most necessary commands. The guidelines below discuss how to do this.

Avoiding VSPackage Loading

Loading a VSPackage into Visual Studio takes time and resources, so from a performance standpoint, it makes sense to delay loading it until it is needed by the user. One way to do this is to design the VSPackage to display its commands in the UI, but not load the VSPackage itself until a user selects one its commands. The easiest way for a VSPackage to add a command to Visual Studio is to define the command in its Command Table Configuration (.Ctc) Files.

The following .ctc file example shows a Hello World Tool command (guidToolWnCmdSet:icmdHelloWorld) that is always available on the View menu (guidSHLMainMenu:IDG_VS_VIEW_BROWSER) that is owned by a VSPackage (guidToolWnPkg).

CMDS_SECTION guidToolWnPkg
    BUTTONS_BEGIN
        guidToolWnCmdSet:icmdHelloWorld,          // Command.
            guidSHLMainMenu:IDG_VS_VIEW_BROWSER,  // Parent group.
            0x0100,                               // Priority.
            guidOfficeIcon:msotcidNoIcon,         // Icon (in this 
                                                  // case, no icon).
            BUTTON,                               // Type.
            ,                                     // Flags (in this 
                                                  // case, use default      
                                                  // flags).
            "&Hello World Tool";                  // Menu text.

This icmdHelloWorld command is not defined as shared, so it uses a custom guidToolWnCmdSet as its command set GUID. Also, by specifying blank for the flags, this command is enabled and displays by default.

Some other common flag values are:

  • DefaultDisabled — Theitem is initially disabled.

  • DefaultInvisible — The item is initially invisible.

  • DynamicInvisibility — The item can be hidden or displayed (as opposed to disabled or enabled).

  • TextChanges— The item's text can change at runtime.

  • IconAndText — The item displays both text and an icon (a valid icon must be specified).

You can us the | operator (that is, logical OR) to combine these flags. For example: DefaultInvisible | DynamicVisibility.

Contexts and Visibility of Menu Items

Sometimes VSPackage commands should be visible or hidden, enabled or disabled either to indicate the state of the VSPackage data or to inform the user about the most relevant and appropriate actions. The easiest way is to allow the VSPackage to set the state of its menu commands, typically through an implementation of the QueryStatus(String, vsCommandStatusTextWanted, vsCommandStatus%, Object%) method from the IOleCommandTarget interface. However, this requires the VSPackage to be loaded before executing any code. The preferred strategy is to allow the integrated development environment (IDE) to manage the visibility of the VSPackage commands without loading the VSPackage. This is accomplished in the Command Table Configuration (.Ctc) Files by associating the command with one or more special UI contexts. These UI contexts are identified by a GUID called a "command context GUID."

Visual Studio monitors major changes in the user's actions, such as the loading of a project, or going from editing code to building the project. This monitoring results in automatic modification of the appearance of the IDE at each context change. The following table shows four of the five major areas of context that Visual Studio monitors.

Type of Context

Description

Active Project Type

For most project types this GUID value is the same as that of the VSPackage implementing the project. Visual C++ projects, however, 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. In some cases, though, it could be a tool window that has a key binding table like the internal web browser. For multi-tabbed document windows like the HTML editor there is a different command context GUID for each tab.

Active Language Service

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

Active Tool Window

A tool window is open and has focus.

The fifth major area of context that Visual Studio monitors, is changes to the internal state of the IDE. These states, called UI contexts, are identified by active command context GUIDs:

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 VSPackage's commands in the IDE without having to load the package itself. You do this by defining the VSPackage's command in its Command Table Configuration (.Ctc) Files with the DefaultDisabled | DefaultInvisible | DynamicVisibility flags and by adding one or more entries to the VISIBILITY_SECTION – VISIBILITY_END section. (For details, see the example .ctc file later in this topic). When one of the specified command context GUIDs becomes active, the command displays and is enabled automatically without actually loading the VSPackage.

Although automatic visibility management on a command-by-command basis is a powerful feature, it is not always possible to get ideal visibility or enabling of a command. In such cases, a reasonable tradeoff is to define the command to be visible and enabled even if it should not be. The user may get an error message saying that the command really did not apply, but from then on, the command is disabled as expected because the VSPackage has been loaded. The performance increase gained by loading a VSPackage only when needed usuall offsets the fact that a command displays when it does not apply.

Custom Context GUIDs

If an appropriate command context GUID is not already defined, your VSPackage can define a custom context GUID and then make that GUID active or inactive as necessary. In this way, you can control the commands you defined to display or hide based on the state of that custom context GUID. The SVsShellMonitorSelection service can be used 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).

    경고

    It is strongly advised that your VSPackage does not affect the state of any existing context GUID since other VSPackages depend on those contexts for proper functioning.

Example

The following is an example of a VSPackage command taken from the Solution Extender sample. It demonstrates dynamic visibility of a command managed by command contexts without loading the VSPackage. In this case, the command is the Project.AddNewSolutionNote command that is set to be enabled and display whenever a solution exists. (That is, whenever one of the following command context GUIDs is active:

CMDS_SECTION guidSlnExtPkg
    BUTTONS_BEGIN
    guidSlnExtCmdSet:icmdAddNote,       // Command.
        guidSlnExtMenuGrp:IDG_SLNNOTES, // Parent group.
        0x0100,                         // Priority.
        guidOfficeIcon:msotcidNoIcon,   // Icon (in this case, none).
        BUTTON,                         // Type.
        DEFAULTDISABLED | DEFAULTINVISIBLE | DYNAMICVISIBILITY, 
                                        // Flags.
        "Add New &Solution Note";       // Menu text.
    BUTTONS_END
CMDS_END

VISIBILITY_SECTION
    // Command GUID when visible.
    guidSlnExtCmdSet:icmdAddNote,  UICONTEXT_EmptySolution;
    guidSlnExtCmdSet:icmdAddNote,  
      UICONTEXT_SolutionHasMultipleProjects;
    guidSlnExtCmdSet:icmdAddNote,  UICONTEXT_SolutionHasSingleProject;
VISIBILITY_END

See Also

Concepts

VISIBILITY_SECTION – VISIBILITY_END

How VSPackages Add User Interface Elements

Command Routing in VSPackages

Solution Extender