Walkthrough: Implementing a Shortcut Menu in a Tool Window
This walkthrough puts a shortcut menu in a tool window. A shortcut menu is a menu that appears when a user right-clicks a graphical user interface (GUI) element such as a button, text box, or window background. Commands on a shortcut menu behave the same as commands on other menus or toolbars. To support a shortcut menu, specify it in the XML Command Table (.vsct) file and display it in response to the right-click of the mouse.
A tool window consists of a Windows Presentation Foundation (WPF) user control in a custom tool window class that inherits from ToolWindowPane.
This walkthrough shows how to create a shortcut menu as a Visual Studio menu, by declaring menu items in the .vsct file, and then using the Managed Package Framework to implement them in the class that defines the tool window. This approach facilitates access to Visual Studio commands, UI elements, and the Automation object model.
Alternatively, if your shortcut menu will not access Visual Studio functionality, you can use the ContextMenu property of a XAML element in the user control. For more information, see ContextMenu.
Prerequisites
To complete this walkthrough, you must install the Visual Studio 2010 SDK.
Notes
For more information about the Visual Studio SDK, see Visual Studio Integration SDK. To find out how to download the Visual Studio SDK, see Visual Studio Extensibility Developer Center on the MSDN Web site.
Locations for the Visual Studio Package Project Template
The Visual Studio Package project template is available in three locations in the New Project dialog box:
Under Visual Basic Extensibility. The default language of the project is Visual Basic.
Under C# Extensibility. The default language of the project is C#.
Under Other Project Types Extensibility. The default language of the project is C++.
Creating the Tool Window Shortcut Menu Package
To create the MyTWGradientPackage VSPackage
Create a Visual Studio Package project named TWShortcutMenu.
In the package wizard, set the language to Visual Basic or C#.
Select the option to create a tool window.
Name the tool window Color Change Window, and set its command ID to cmdidColorChange.
Specifying the Shortcut Menu
A shortcut menu such as the one shown in this walkthrough lets the user select from a list of colors that are used to fill the background of the tool window.
To create the shortcut menu
Open MyTWGradientPackage.vsct.
In the Symbols element, in the GuidSymbol element named "guidTWShortcutMenuCmdSet", declare the shortcut menu, shortcut menu group, and menu options, as follows.
<IDSymbol name="ColorMenu" value="0x1000"/> <IDSymbol name="ColorGroup" value="0x1100"/> <IDSymbol name="cmdidRed" value="0x102"/> <IDSymbol name="cmdidYellow" value="0x103"/> <IDSymbol name="cmdidBlue" value="0x104"/>
Just before the Groups element, create a Menus element and then define the shortcut menu in it.
<Menus> <Menu guid="guidTWShortcutMenuCmdSet" id="ColorMenu" type="Context"> <Strings> <ButtonText>Color change</ButtonText> <CommandName>ColorChange</CommandName> </Strings> </Menu> </Menus>
A shortcut menu does not have a parent because it is not part of a menu or toolbar.
In the Groups element, define the Group element that contains the shortcut menu items, and associate the group with the shortcut menu.
<Group guid="guidTWShortcutMenuCmdSet" id="ColorGroup"> <Parent guid="guidTWShortcutMenuCmdSet" id="ColorMenu"/> </Group>
In the Buttons element, define the individual commands that will appear on the shortcut menu.
<Button guid="guidTWShortcutMenuCmdSet" id="cmdidRed" priority="1" type="Button"> <Parent guid="guidTWShortcutMenuCmdSet" id="ColorGroup" /> <Strings> <ButtonText>Red</ButtonText> </Strings> </Button> <Button guid="guidTWShortcutMenuCmdSet" id="cmdidYellow" priority="3" type="Button"> <Parent guid="guidTWShortcutMenuCmdSet" id="ColorGroup" /> <Strings> <ButtonText>Yellow</ButtonText> </Strings> </Button> <Button guid="guidTWShortcutMenuCmdSet" id="cmdidBlue" priority="5" type="Button"> <Parent guid="guidTWShortcutMenuCmdSet" id="ColorGroup" /> <Strings> <ButtonText>Blue</ButtonText> </Strings> </Button>
Open PkgCmdID.vb or PkgCmdID.cs.
Add the definitions for the shortcut menu and the menu items.
public const int ColorMenu = 0x1000; public const int cmdidRed = 0x102; public const int cmdidYellow = 0x103; public const int cmdidBlue = 0x104;
These are the same command IDs that are defined in the Symbols section of the TWShortcutMenu.vsct file. The context group is not included here because it is only required in the .vsct file.
Save the solution and build it.
Implementing the Shortcut Menu
This section implements the shortcut menu and its commands.
To implement the shortcut menu
Open MyToolWindow.vb or MyToolWindow.cs.
The MyToolWindow class has access to the menu command services, but the user control it hosts does not. The next three steps show how to make an instance of the menu command service available from the tool window to the user control.
Add the System.ComponentModel.Design namespace.
using System.ComponentModel.Design;
Add a variable to hold the instance of the menu command service.
internal OleMenuCommandService mcs;
At the end of the constructor, add a call to the menu command service and modify the call to base.Content, as follows.
mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService; base.Content = new MyControl(this);
Calling the menu command service in the constructor ensures that it is in memory whenever the tool window is open. Passing an instance of the tool window as a parameter to the control constructor enables the control to make calls to the members of the tool window class.
Open MyControl.xaml.
This file represents the user control that is displayed in the tool window.
Add a MouseRightButtonDown event to the top level UserControl element.
MouseRightButtonDown="MyToolWindow_MouseRightButtonDown"
Right-click the event declaration you just added and then click Navigate to Event Handler.
This opens MyControl.xaml.vb or MyControl.xaml.cs and creates a stub for the event handler.
At the top of MyControl, add the Microsoft.VisualStudio.Shell and System.ComponentModel.Design namespaces.
using Microsoft.VisualStudio.Shell; using System.ComponentModel.Design;
Add a field to hold a reference to the parent tool window, and modify the constructor as follows.
MyToolWindow _parent; public MyControl(MyToolWindow parent) { InitializeComponent(); _parent = parent; OleMenuCommandService mcs = this._parent.mcs; if (null != mcs) { // Create an alias for the command set guid. Guid g = GuidList.guidTWShortcutMenuCmdSet; // Create the command IDs. var red = new CommandID(g, PkgCmdIDList.cmdidRed); var yellow = new CommandID(g, PkgCmdIDList.cmdidYellow); var blue = new CommandID(g, PkgCmdIDList.cmdidBlue); // Add a command for each command ID. mcs.AddCommand(new MenuCommand(ChangeColor, red)); mcs.AddCommand(new MenuCommand(ChangeColor, yellow)); mcs.AddCommand(new MenuCommand(ChangeColor, blue)); } }
The constructor now takes the parent tool window instance as a parameter, and stores it in the _parent field. It then creates CommandID objects from the command set GUID and the PkgCmdList values that represent the menu commands that you defined in the .vsct file. Last, it adds the commands to the menu command service and assigns event handlers.
Implement the MyToolWindowMouseRightButtonDown event as follows.
private void MyToolWindow_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { OleMenuCommandService mcs = this._parent.mcs; if (null != mcs) { CommandID menuID = new CommandID( GuidList.guidTWShortcutMenuCmdSet, PkgCmdIDList.ColorMenu); Point p = this.PointToScreen(e.GetPosition(this)); mcs.ShowContextMenu(menuID, (int)p.X, (int)p.Y); } }
This creates a CommandID object for the shortcut menu, identifies the location of the mouse click, and opens the shortcut menu in that location by using the ShowContextMenu method.
Implement the event, which is defined in the constructor, for a user click on a menu item.
private void ChangeColor(object sender, EventArgs e ) { var mc = sender as MenuCommand; switch (mc.CommandID.ID) { case PkgCmdIDList.cmdidRed: MyToolWindow.Background = Brushes.Red; break; case PkgCmdIDList.cmdidYellow: MyToolWindow.Background = Brushes.Yellow; break; case PkgCmdIDList.cmdidBlue: MyToolWindow.Background = Brushes.Blue; break; } }
In this case, just one method handles events for all of the menu items by identifying the CommandID and setting the background color accordingly. If the menu items had contained unrelated commands, you would have created a separate event handler for each command.
Testing the Tool Window Features
This section shows how to demonstrate the features that have been added in this walkthrough.
To test the tool window features
Press F5 to open an experimental instance of Visual Studio.
In the experimental instance, on the View menu, click Other Windows and then click Color Change Window. Doing this should display your tool window.
Right-click the tool window background, away from the button. A shortcut menu that has a list of colors should be displayed.
Click a color on the shortcut menu. The shortcut menu should disappear, and the tool window background color should be changed to the selected color.
Next Steps
If you change the shortcut menu by modifying the .vsct file, you must rebuild the MyTWGradientPackageUI project. Doing this forces the .vsct file to be recompiled and the satellite DLL to be re-linked with the changes that you made to the .vsct file.