Key Bindings
You've seen the many ways that commands can be invoked, but each way requires either moving your hand from the keyboard to the mouse or typing a long string of commands. To aid in accessibility or just to make invoking these commands easier, many commands are assigned a shortcut keystroke, or key binding. For example, rather than picking up the mouse, opening the File menu, choosing the Open submenu, and then clicking File to open a file, you can use the keystroke Ctrl+O to quickly access the Open File dialog box.Each command can have one or more key bindings assigned to it. The Command.Bindings property allows you to read or set the bindings assigned to that command. When you call this property to retrieve the set of bindings, an array of objects containing strings describing each binding is returned, which can be enumerated to find each binding. You can set bindings by using this property, and they can accept either a singular string to set a single keystroke or an array of strings to assign multiple bindings at once. You can see how these key bindings are retrieved in this macro:
Sub GetFileOpenBindings()
Dim bindings As Object()
Dim binding As Object
bindings = DTE.Commands.Item("File.OpenFile").Bindings
For Each binding In bindings
MsgBox(CStr(binding))
Next
End Sub
Each binding that is set has a specific format, and you must follow this format closely to avoid generating an error. Here's the format:
Scope::ModifierKeys+Key,ModifierKeys2+Key2
And here's a description of each piece of the binding: Scope is the context in which the key binding can be applied. For example, pressing the Ctrl+B key binding makes the selected text bold when you're using the HTML editor; if the image editor is active (a bitmap is loaded and is the active window), the brush tool is selected. If neither the HTML editor nor the image editor is active, pressing Ctrl+B displays the debugger breakpoints dialog box. A number of scopes are available, but the most common is the Global scope. In this scope, the command is available everywhere except when a more specific scope is active. The Ctrl+B keystroke for displaying debugger breakpoints is in the Global scope, while Ctrl+B for bolding text is in the HTML Editor Design View scope and takes precedence over the breakpoints dialog box if an HTML designer window is active.Modifier keys are system keys that are pressed while you're pressing another key. These modifiers include the Alt, Shift, and Ctrl keys. One or more modifier keys can be specified; they can appear in any order but must be separated by the + character.A key is any key on a standard 102-key keyboard (which excludes keys on newer Windows keyboards, such as the Windows key, multimedia keys, and the Fn key on some notebook keyboards). If a key is a system key, such as F1, F2, and so forth or the Esc key, a Modifier key isn't required. If the key is an alphanumeric key, a Modifier must be specified. It can't be Shift alone but must include either Alt or Ctrl or both because some keystrokes are reserved and can't be overridden. (For example, A and Shift+A are reserved by the text editor.) The keys available for use are the alphanumeric keys, the unshifted characters (such as the comma and period), and the values Bkspce, Del, Ins, Space, F1 to F24, Enter, Break, Up Arrow, Down Arrow, Left Arrow, Right Arrow, Tab, Home, End, PgUp, PgDn, Esc, NUM *, NUM -, NUM +, and NUM /. The Caps Lock, Print Screen, Num Lock, and Pause keys are reserved by the operating system, so you can't use them.ModifierKeys2 and Key2 make up another set of keystrokes. These are optional and can be used to refine command groups. For example, you can have your add-in use the key binding Ctrl+Shift+D, O to open a file into a tool window, while Ctrl+Shift+D, S can save that file. Key2 isn't restricted to being grouped with a modifier key, which means that ModifierKeys2 is optional.
Using this format, we can assign the keystroke Ctrl+Shift+D,O within the Global scope by using code like this:
Sub SetKeyBinding()
Dim command As Command
command = DTE.Commands.Item("File.OpenFile")
command.Bindings = "Global::Ctrl+Shift+D,O"
End Sub
This call to the Bindings property sets one key binding, but you can also assign more than one key binding at a time by passing an array of System.Object, each set to a System.String:
Sub SetKeyBindings()
Dim command As Command
Dim bindings(1) As Object
bindings(0) = "Global::Ctrl+Shift+D,O"
bindings(1) = "Global::Ctrl+Shift+D,F"
command = DTE.Commands.Item("File.OpenFile")
command.Bindings = bindings
End Sub
When any changes are made to the key bindings for a command, all the bindings for that command are removed, and if the binding is in use with another command, that binding is also removed. After running a macro such as this, users who are accustomed to using Ctrl+O to open a file might become confused about why their familiar binding has been lost, but this setting can be preserved through code:
Sub SetKeyBindingsPreserve()
Dim command As Command
Dim bindings() As Object
Dim preserveLength As Integer
command = DTE.Commands.Item("File.OpenFile")
'Retrieve the current bindings for the command
bindings = command.Bindings
'Find the number of current bindings
preserveLength = bindings.Length
'Add 2 elements to the array (remember, preserveLength
' will be 1 more than the number of elements, and this
' extra value with 1 added to it becomes 2 elements
ReDim Preserve bindings(preserveLength + 1)
'Assign our new bindings
bindings(preserveLength) = "Global::Ctrl+Shift+D,O"
bindings(preserveLength + 1) = "Global::Ctrl+Shift+D,F"
command.Bindings = bindings
End Sub
When you attempt to modify the set of key bindings for a command, you might get an exception with the message "Setting key bindings valid only when using a non-built-in key binding scheme." This exception occurs because the key binding schemes that ship with Visual Studio .NET are read-only; to modify the keyboard scheme, you or your user must first switch to a user-defined key scheme. You can do this through the user interface in the Options dialog box on the Environment | Keyboard tab by clicking the Save As button or by assigning a path to the Environment | Keyboard property collection's Scheme property. If, when you're setting this value, the .vsk file (keyboard schemes are saved into a file with the extension .vsk) doesn't exist, a file is created for you.The following macro creates a keyboard scheme file in the user's application data folder for Visual Studio .NET:
Sub ChangeKeyboardScheme()
Dim props As EnvDTE.Properties
Dim prop As EnvDTE.Property
Dim path As String
Dim folder As System.Environment.SpecialFolder
'Find the Environment, Keyboard, scheme property
props = DTE.Properties("Environment", "Keyboard")
prop = props.Item("Scheme")
'Set the path we wish to save information to
folder = System.Environment.SpecialFolder.ApplicationData
path = System.Environment.GetFolderPath(folder)
path = path + "\Microsoft\VisualStudio\7.1\scheme.vsk"
'Set the path
prop.Value = path
End Sub
Lab: Creating a Command and Key Binding Cheat SheetI like to keep handy a printout of all commands and the bindings of those commands that Visual Studio .NET offers. When I find that I'm running a certain command repeatedly, I look up that command on my printout and then try to remember the keystroke shortcut for that command. Finding the command that I want to run might take a while because there are so many commands, but over time this approach has increased my productivity because I no longer need to hunt for a command on the menusI can just press a keystroke. Here's the macro I used to create my command cheat sheet: [View full width]Sub GenerateCommandCheatSheet() |