Walkthrough: Adding a Menu Controller to a Toolbar
注意
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.
This walkthrough builds on the Walkthrough: Adding a Toolbar to a Tool Window walkthrough and guides you through the steps of adding a menu controller to the tool window's toolbar. The steps shown here also can be applied to the toolbar created in the Walkthrough: Adding a Toolbar to the IDE, if desired.
A menu controller is a split control. The left side of the menu controller shows the last-used command, and it can be run by clicking it. The right side of the menu controller is a drop-down arrow that, when clicked, opens a drop-down list of additional commands. When you click a command on the list, the command runs, and it replaces the command on the left side of the menu controller. In this way, the menu controller operates like a command button that always shows the last-used command from a list.
Menu controllers can appear on menus but they are most often used on toolbars. Menu controllers can display the icon of the last-used command, the text of the last-used command, or both.
This walkthrough demonstrates a menu controller that offers three selectable options which are added by using .ctc files. For more information on menus and.ctc files, see Menus and Toolbars.
Prerequisites
This walkthrough requires the Visual Studio Industry Partner (VSIP) SDK to be installed.
Creating a VSPackage
To create the MyTWToolbarPackage VSPackage
Follow the procedures described in Walkthrough: Adding a Toolbar to a Tool Window to create a tool window VSPackage with a toolbar.
注意
In this walkthrough for adding a menu controller, the process of adding the menu controller to a Visual C++ VSPackage is different than that of adding a menu controller to a Visual C# VSPackage. Therefore, two procedures are provided: one for Visual C# and the other for Visual C++. However, the process of creating the menu controller in the .ctc file is the same for both programming languages.
The rest of the procedures in this walkthrough use the VSPackage name MyTWToolbarPackage, which is the name used in the Walkthrough: Adding a Toolbar to a Tool Window walkthrough.
Creating a Menu Controller
To create a menu controller
In Solution Explorer, expand the CtcComponents folder in the MyTWToolPackage project, right-click CommandIds.h, and then click Open to open it in a text editor.
In the Menu IDs section, after the existing menu ID, add a definition for MyMenuController:
#define MyMenuController 0x1300
In the Menu Group IDs section, after the existing group IDs, add a definition for MyMenuControllerGroup:
#define MyMenuControllerGroup 0x1060
In the Command IDs section, after the existing command IDs, add the following command IDs:
#define cmdidMCItem1 0x130 #define cmdidMCItem2 0x131 #define cmdidMCItem3 0x132
Again, in the CtcComponents folder, right-click MyTWToolbarPackage.ctc, and then click Open to open it in a text editor.
In the MENUS_BEGIN section, after the last menu entry, add the following lines:
guidMyTWToolbarPackageCmdSet:MyMenuController, // Menu ID guidMyTWToolbarPackageCmdSet:MyToolbarGroup, // Parent Group 0x0100, // Priority MENUCONTROLLER | ICONANDTEXT | TEXTCHANGES | TEXTISANCHORCOMMAND, // Type and Flags "My Menu Controller"; // Menu Name
注意
The TEXTCHANGES flag must be included with the TEXTISANCHORCOMMAND flag. Otherwise, the menu controller will not change to reflect the last selected command.
In the NEWGROUPS_BEGIN section, after the last group entry, add the following lines:
// Any command added to this group appears in the menu controller. guidMyTWToolbarPackageCmdSet:MyMenuControllerGroup, // Group ID guidMyTWToolbarPackageCmdSet:MyMenuController, // Menu ID 0x0000; // Priority
In the BUTTONS_BEGIN section, after the last button entry, add the following lines:
guidMyTWToolbarPackageCmdSet:cmdidMCItem1, // Command ID guidMyTWToolbarPackageCmdSet:MyMenuControllerGroup, // Parent Group, 0x0000, // Priority guidMyTWToolbarPackageCmdSet:bmpPic1, // Icon ID BUTTON, // Type ICONANDTEXT, // Flags "MC Item 1"; // Button name guidMyTWToolbarPackageCmdSet:cmdidMCItem2, // Command ID guidMyTWToolbarPackageCmdSet:MyMenuControllerGroup, // Parent Group, 0x0100, // Priority guidMyTWToolbarPackageCmdSet:bmpPic2, // Icon ID BUTTON, // Type ICONANDTEXT, // Flags "MC Item 2"; // Button name guidMyTWToolbarPackageCmdSet:cmdidMCItem3, // Command ID guidMyTWToolbarPackageCmdSet:MyMenuControllerGroup, // Parent Group, 0x0200, // Priority guidMyTWToolbarPackageCmdSet:bmpPicSmile, // Icon ID BUTTON, // Type ICONANDTEXT, // Flags "MC Item 3"; // Button name
In Solution Explorer, right-click the MyTWToolbarPackage project, and then click Rebuild.
This rebuilds the .ctc file with the changes. Correct any errors that occur during building. (Wrong case for a GUID label or a command ID is the most common error. GUID labels and command IDs always are case-sensitive.)
At this point, you can look at the menu controller. Open an instance of the experimental Visual Studio using any one of the following methods:
At the Visual Studio command prompt, type devenv /rootsuffix exp.
On the Start Menu, select the experimental Visual Studio shortcut, Visual Studio 2008 Experimental. This shortcut is added when the VSIP SDK is installed.
Press F5 or select Start on the Debug menu (this runs the experimental Visual Studio under the debugger and allows debugging of your VSPackage).
On the View menu, point to Other Windows, and then click MyToolWindow.
The menu controller appears in the toolbar in the tool window.
Click the down arrow on the right-hand side of the menu controller to see the three possible commands.
Notice that when you click a command, the left-hand side of the menu controller changes to display that command. Normally, the command is also run when clicked, but for now, nothing happens.
Close the experimental Visual Studio.
Implementing the Menu Controller Commands
The following procedure assumes that you created the VSPackage in Visual C#. For a VSPackage created in Visual C++, see the next procedure, To implement menu controller commands in unmanaged code.
To implement the menu controller commands in managed code
In Solution Explorer, right-click PkgCmdID.cs, and then click Open to open it in a text editor.
After the existing command IDs in the PkgCmdID.cs file, add the following command IDs:
public const int cmdidMCItem1 = 0x130; public const int cmdidMCItem2 = 0x131; public const int cmdidMCItem3 = 0x132;
In Solution Explorer, right-click VsPkg.cs, and then click Open to open it in a text editor.
At the top of the MyTWToolbarPackage class, just after the declaration for const int bitmapResourceID = 300;, add the following:
private int currentMCCommand; // The currently selected menu controller command
Locate the hidden region labeled "Package Members" and expand it by clicking the plus sign in the left margin.
In the Initialize method, immediately after the call to the AddCommand method, add the following lines. This code routes the events for each command through the same handlers.
for (int i = PkgCmdIDList.cmdidMCItem1; i <= PkgCmdIDList.cmdidMCItem3; i++) { CommandID cmdID = new CommandID(GuidList.guidMyTWToolbarPackageCmdSet, i); OleMenuCommand mc = new OleMenuCommand(new EventHandler(OnMCItemClicked), cmdID); mc.BeforeQueryStatus += new EventHandler(OnMCItemQueryStatus); mcs.AddCommand(mc); // The first item is, by default, checked. if (PkgCmdIDList.cmdidMCItem1 == i) { mc.Checked = true; this.currentMCCommand = i; } }
At the end of the MyTWToolbarPackage class, right after MenuItemCallback method, add the following method, which marks the selected command as checked:
private void OnMCItemQueryStatus(object sender, EventArgs e) { OleMenuCommand mc = sender as OleMenuCommand; if (null != mc) { mc.Checked = (mc.CommandID.ID == this.currentMCCommand); } }
After the OnMCItemQueryStatus method, add the following method, which is called when the user selects a command on the menu controller:
private void OnMCItemClicked(object sender, EventArgs e) { OleMenuCommand mc = sender as OleMenuCommand; if (null != mc) { string selection; switch (mc.CommandID.ID) { case PkgCmdIDList.cmdidMCItem1: selection = "Menu controller Item 1"; break; case PkgCmdIDList.cmdidMCItem2: selection = "Menu controller Item 2"; break; case PkgCmdIDList.cmdidMCItem3: selection = "Menu controller Item 3"; break; default: selection = "Unknown command"; break; } this.currentMCCommand = mc.CommandID.ID; IVsUIShell uiShell = (IVsUIShell)GetService(typeof(SVsUIShell)); Guid clsid = Guid.Empty; int result; uiShell.ShowMessageBox( 0, ref clsid, "My Tool Window Toolbar Package", string.Format(CultureInfo.CurrentCulture, "You selected {0}", selection), string.Empty, 0, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST, OLEMSGICON.OLEMSGICON_INFO, 0, out result); } }
On the Build menu, click Build Solution to build the solution. Correct any errors that occur.
To test the menu controller, refer to the section, Testing the Menu Controller.
To implement the menu controller commands in unmanaged code
In Solution Explorer, right-click VsPkg.h, and then click Open to open it in a text editor.
At the end of the CMyTWToolbarPackagePackage class, after the last variable in the private section, add the following:
// Menu controller stuff. int m_currentMCCommand; void OnMCItemClicked(int cmdID); int OnMCItemQueryStatus(int cmdID, int cmdFlags);
In Solution Explorer, right-click VSPkg.cpp, and then click Open to open it in a text editor.
In the CMyTWToolbarPackagePackage::CMyTWToolbarPackagePackage constructor, add the following to the end of the constructor:
m_currentMCCommand = cmdidMCItem1;
Find the CMyTWToolbarPackagePackage::QueryStatus method and add the following to the switch statement just before the default statement:
case cmdidMCItem1: case cmdidMCItem2: case cmdidMCItem3: cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED; cmdf = OnMCItemQueryStatus(prgCmds[0].cmdID, cmdf); break;
Find the CMyTWToolbarPackagePackage::Exec method and add the following to the switch statement just before the default statement.
case cmdidMCItem1: case cmdidMCItem2: case cmdidMCItem3: OnMCItemClicked(nCmdID); break;
At the end of the VsPkg.cpp file, add the following OnMCItemQueryStatus method. This method handles updating the status of the three menu controller commands:
int CMyTWToolbarPackagePackage::OnMCItemQueryStatus(int cmdID, int cmdFlags) { if (cmdID == m_currentMCCommand) { cmdFlags |= OLECMDF_LATCHED; } return(cmdFlags); }
After the OnMCItemQueryStatus method, add the following OnMCItemClicked method. This method is called when the user clicks a command on the menu controller.
void CMyTWToolbarPackagePackage::OnMCItemClicked(int cmdID) { LPCWSTR selection = L""; switch(cmdID) { case cmdidMCItem1: selection = L"Menu controller Item 1"; break; case cmdidMCItem2: selection = L"Menu controller Item 2"; break; case cmdidMCItem3: selection = L"Menu controller Item 3"; break; default: selection = L"Unknown command"; break; } m_currentMCCommand = cmdID; CComBSTR prompt(L"You selected "); prompt += selection; CComPtr<IVsUIShell> srpUiShell; HRESULT hr = _AtlModule.QueryService(SID_SVsUIShell, IID_IVsUIShell, (void **)&srpUiShell); if (SUCCEEDED(hr)) { // Show Message Box to prove we were here. LONG lResult; hr = srpUiShell->ShowMessageBox( 0, CLSID_NULL, L"CMyTWToolbarPackage", (LPOLESTR)prompt, NULL, 0, OLEMSGBUTTON_OK, OLEMSGDEFBUTTON_FIRST, OLEMSGICON_INFO, 0, &lResult); } }
On the Build menu, click Build Solution to build the solution. Correct any errors that occur.
To test the menu controller, refer to the section, Testing the Menu Controller.
Testing the Menu Controller
To test the menu controller
Open an instance of the experimental Visual Studio using one of the following methods:
At the Visual Studio command prompt, type devenv /rootsuffix exp.
On the Start Menu, click the experimental Visual Studio shortcut, Visual Studio 2008 Experimental. This shortcut is added when the VSIP SDK is installed.
Press F5 or select Start on the Debug menu (this runs the experimental Visual Studio under the debugger and allows debugging of your VSPackage).
On the View menu, point to Other Windows, and then click MyToolWindow.
The menu controller appears in the toolbar in the tool window and displays "MC Item 1".
Click the menu controller button to the left of the little down arrow.
A dialog box appears and displays the message "Selected Menu controller Item 1". Note that the message corresponds to the text on the menu controller button.
Click the drop-down arrow on the menu controller to display three items, the first of which is selected with a highlight box around its icon. Click MC Item 3.
A dialog box appears and displays the message "Selected Menu controller Item 3". Note that the menu controller button now displays "MC Item 3".
On the menu controller, click the MC Item 3 button.
A dialog box appears and displays the message "Selecting Menu controller Item 3". This demonstrates that the menu controller has been modified to show the last-used command as the default.
Click the drop-down arrow on the menu controller to display the options. Notice that the new default, MC Item 3, now is selected.
See Also
Concepts
Menu and Toolbar Command Walkthroughs
Walkthrough: Adding a Toolbar to a Tool Window