Useful Code: Keyboard shortcuts
People often wonder about how we deal with Keyboard shortcuts in Visual Studio. There are a couple of things to know and I'll throw in a neat macro too.
Profiles
When you run Visual Studio for the first time, you will get a prompt asking which default settings you wish to use. We created these defaults to accommodate developers have become accustomed to a certain IDE layout and we don't want to impose a new one. Therefore we ship VS with 7 default profiles corresponding to types of development activities: J#, C#, VB, C++, Web, Team and General (kind of a default for defaults). These profiles encode things like the window layout, options, help filters, as well as keyboard shortcuts. If you are accustomed to VC6 shortcuts, you'll probably be most comfortable in the C++ profile. On the other hand, if you're coming from the C#/VB world, you might prefer to stick with their settings. Of course, the elite among you will care nothing for these imposed "defaults" and I'll be happy to show you how you can set up your own shortcuts.
Keyboard Options
There is a single location for all your shortcut management needs, the Keyboard options dialog. It is located within the IDE options dialog (Tools\Options...). You can find it under the top-level Environment node. I like to say that it's a highly functional dialog stuck in a poor UI. Here is a picture of it (the red boxes are my creative addition).
As you can see, it looks quite dense so I have highlighted what I consider the two features of this dialog everyone should know (I leave the rest up to the reader). The first box is a substring search filter to find any command which can be assigned a shortcut, which is great when you can't remember what the shortcut for a command is. The second box is somewhat the compliment of the first as it allows you to do a reverse lookup of a shortcut. In other words, given a shortcut, it will display what command(s) it is assigned to.
View all shortcuts
Over time, some of my colleagues decided it would be nice to query Visual Studio to return the list of all assigned shortcuts (in order to print it out or test it or something…). This seemed like an interesting opportunity to flex our extensibility model and write yet another macro. First, let's define a couple structures for this purpose.
Structure VSShortcut
Public Scope As String
Public KeyCombo As String
Sub New(ByVal fullshortcut As String)
Scope = fullshortcut.Split("::").GetValue(0)
KeyCombo = fullshortcut.Split("::").GetValue(2)
End Sub
End Structure
Structure VSCommand
Public Name As String
Public Category As String
Public Shortcuts As List(Of VSShortcut)
Sub New(ByVal fullname As String, ByVal keys As Array)
Name = fullname
Category = fullname.Split(".").GetValue(0)
Shortcuts = New List(Of VSShortcut)(5)
For Each key As String In keys
Shortcuts.Add(New VSShortcut(key))
Next
End Sub
End Structure
These two structures are pretty self-explanatory, they represent a shortcut key combination and a command respectively. We can now iterate through the list of all commands and generate a list of commands with assigned shortcuts.
Sub GetAssignedCommands(ByRef CommandList As List(Of VSCommand))
Dim keys As System.Array
' iterate through each possible command in VS
For Each item As EnvDTE.Command In DTE.Commands
If (item.Name <> Nothing) And (item.Name <> "") Then
' get the array of shortcuts for this command
keys = item.Bindings
' add command only if there is at least a shortcut assigned to it
If keys.Length > 0 Then
CommandList.Add(New VSCommand(item.Name, keys))
End If
End If
Next
End Sub
At this point, we simply need to print this out. It turns out there's a quick and dirty way of getting some output from a macro in VS. The Output window. Here is the relevant code to spit out some XML (HTML might be more appropriate for a print-out).
Sub WriteStringToOutput(ByRef s As String)
Dim pane As OutputWindowPane = GetOutputWindowPane("Commands")
pane.OutputString(s)
End Sub
Sub GenerateShortcutsInXML(ByRef CommandList As List(Of VSCommand), ByRef XMLDoc As XmlDocument)
Dim commandNode As XmlElement
Dim shortcutNode As XmlElement
Dim shortcutText As XmlText
Dim rootNode As XmlElement
' xml preamble
XMLDoc.CreateXmlDeclaration("1.0", "utf-8", Nothing)
XMLDoc.InsertBefore(XMLDoc.CreateXmlDeclaration("1.0", "utf-8", Nothing), XMLDoc.DocumentElement)
rootNode = xmldoc.CreateElement("commands")
XMLDoc.AppendChild(rootNode)
' iterate through commands
For Each command As VSCommand In CommandList
commandNode = XMLDoc.CreateElement("command")
commandNode.SetAttribute("name", command.Name)
For Each shortcut As VSShortcut In command.Shortcuts
shortcutNode = XMLDoc.CreateElement("shortcut")
shortcutNode.SetAttribute("scope", shortcut.Scope)
shortcutNode.AppendChild(XMLDoc.CreateTextNode(shortcut.KeyCombo))
commandNode.AppendChild(shortcutNode)
Next
rootNode.AppendChild(commandNode)
Next
End Sub
And finally, the glue that keeps it all together.
Sub OutputShortcutsAsXml()
Dim cmdList As List(Of VSCommand) = New List(Of VSCommand)
Dim xmlDoc As XmlDocument = New XmlDocument()
GetAssignedCommands(cmdList)
GenerateShortcutsInXML(cmdList, xmlDoc)
' generating the output
Dim sb As StringBuilder = New StringBuilder()
Dim writer As XmlTextWriter = New XmlTextWriter(New StringWriter(sb))
writer.Formatting = Formatting.Indented
writer.Indentation = 4
writer.IndentChar = " "
xmlDoc.WriteTo(writer)
writer.Flush()
writer.Close()
WriteStringToOutput(sb.ToString())
End Sub
Comments
- Anonymous
June 19, 2006
Cool macro! Thanks for sharing this...
John - Anonymous
November 02, 2006
The comment has been removed - Anonymous
December 01, 2007
The comment has been removed - Anonymous
April 02, 2008
i want a code for cucl2 i want taht little one - Anonymous
December 09, 2010
it's ok in one way but for me it's just not working so just don't try this