Walkthrough: Using a Shortcut Key with an Editor Extension

You can respond to shortcut keys in your editor extension. The following walkthrough shows how to add a view adornment to a text view by using a shortcut key. This walkthrough is based on the viewport adornment editor template, and it allows you to add the adornment by using the + character.

To complete this walkthrough, you must install the Visual Studio 2010 SDK.

NoteNote

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.

To create a MEF project

  1. Create an Editor Viewport Adornment project. Name the solution KeyBindingTest.

  2. Open the source.extension.vsixmanifest file in the VSIX Manifest Editor.

  3. Make sure that the Content heading contains a MEF Component content type and that the Path is set to KeyBindingTest.dll.

  4. Save and close Source.extension.vsixmanifest.

  5. Add the following references and set CopyLocal to false:

    Microsoft.VisualStudio.Editor

    Microsoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell

    Microsoft.VisualStudio.TextManager.Interop

  6. Delete the KeyBindingTestFactory class file.

In the KeyBindingTest class file, change the class name to PurpleCornerBox. Change the constructor as well. Inside the constructor, change the line:


_adornmentLayer = view.GetAdornmentLayer("KeyBindingTest");


to


_adornmentLayer = view.GetAdornmentLayer("PurpleCornerBox");


The command filter is an implementation of IOleCommandTarget, which handles the command by instantiating the adornment.

To define the command filter

  1. Add a class file and name it KeyBindingCommandFilter.

  2. Add the following using statements.

    
    using System;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Text.Editor;
    
    
    
  3. The class named KeyBindingCommandFilter should inherit from IOleCommandTarget.

    
    internal class KeyBindingCommandFilter : IOleCommandTarget
    
    
    
  4. Add private fields for the text view, the next command in the command chain, and a flag to represent whether the command filter has already been added.

    
    private IWpfTextView m_textView;
    internal IOleCommandTarget m_nextTarget;
    internal bool m_added;
    internal bool m_adorned;
    
    
    
  5. Add a constructor that sets the text view.

    
    public KeyBindingCommandFilter(IWpfTextView textView)
    {
        m_textView = textView;
        m_adorned = false;
    }
    
    
    
  6. Implement the QueryStatus() method as follows.

    
    int IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        return m_nextTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
    }
    
    
    
  7. Implement the Exec() method so that it adds a purple box to the view if a + character is typed.

    
    int IOleCommandTarget.Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
    {
        if (m_adorned == false)
        {
            char typedChar = char.MinValue;
    
            if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
            {
                typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
                if (typedChar.Equals('+'))
                {
                    new PurpleCornerBox(m_textView);
                    m_adorned = true;
                }
            }
        }
        return m_nextTarget.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
    }
    
    
    

The adornment provider must add a command filter to the text view. In this example, the provider implements IVsTextViewCreationListener to listen to text view creation events. This adornment provider also exports the adornment layer, which defines the Z-order of the adornment.

To add the command filter provider

  1. Add a class file and name it KeyBindingFilterProvider.

  2. Add the following using statements.

    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio.Utilities;
    using Microsoft.VisualStudio.Editor;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.TextManager.Interop;
    
    
    
  3. Add a class named KeyBindingFilterProvider that inherits from IVsTextViewCreationListener, and export it with a content type of "text" and a TextViewRoleAttribute of Editable.

    
    [Export(typeof(IVsTextViewCreationListener))]
    [ContentType("text")]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    internal class KeyBindingCommandFilterProvider : IVsTextViewCreationListener
    
    
    
  4. Add the adornment layer definition.

    
    [Export(typeof(AdornmentLayerDefinition))]
    [Name("PurpleCornerBox")]
    [Order()]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    internal AdornmentLayerDefinition keybindingAdornmentLayer;
    
    
    
  5. To get the text view adapter, you must import the IVsEditorAdaptersFactoryService.

    
    [Import(typeof(IVsEditorAdaptersFactoryService))]
    internal IVsEditorAdaptersFactoryService editorFactory = null;
    
    
    
  6. Implement the VsTextViewCreated method so that it adds the KeyBindingCommandFilter.

    
    public void VsTextViewCreated(IVsTextView textViewAdapter)
    {
        IWpfTextView textView = editorFactory.GetWpfTextView(textViewAdapter);
        if (textView == null)
            return;
    
        AddCommandFilter(textViewAdapter, new KeyBindingCommandFilter(textView));
    }
    
    
    
  7. The AddCommandFilter handler gets the text view adapter and adds the command filter.

    
    void AddCommandFilter(IVsTextView viewAdapter, KeyBindingCommandFilter commandFilter)
    {
        if (commandFilter.m_added == false)
        {
            //get the view adapter from the editor factory
            IOleCommandTarget next;
            int hr = viewAdapter.AddCommandFilter(commandFilter, out next);
    
            if (hr == VSConstants.S_OK)
            {
                commandFilter.m_added = true;
                //you'll need the next target for Exec and QueryStatus
                if (next != null)
                    commandFilter.m_nextTarget = next;
            }
        }
    }
    
    
    

To test this code, build the KeyBindingTest solution and run it in the experimental instance.

To build and test the KeyBindingTest solution

  1. Build the solution.

  2. When you run this project in the debugger, a second instance of Visual Studio is instantiated.

  3. Create or open a text file, and then click anywhere in the text view.

  4. Type +.

    Resize the text view.

    A purple square should appear in the upper right corner of the text view.

Was this page helpful?
(1500 characters remaining)
Thank you for your feedback

Community Additions

ADD
Show:
© 2014 Microsoft