Compartir a través de


Tutorial: Uso de una tecla de método abreviado con una extensión del editor

Puede responder a las teclas de método abreviado en la extensión del editor. En el siguiente tutorial se muestra cómo agregar un adorno de vista a una vista de texto mediante una tecla de método abreviado. Este tutorial se basa en la plantilla del editor de adornos de ventanilla y permite agregar el adorno mediante el carácter + .

Creación de un proyecto de Marco de extensibilidad administrada (MEF)

  1. Cree un proyecto VSIX de C#. (En Cuadro de diálogo Nuevo proyecto , seleccione Visual C# / Extensibilidad y, después , Proyecto VSIX). Asigne un nombre a la solución KeyBindingTest.

  2. Agregue una plantilla de elemento De adorno de texto del editor al proyecto y asígnele KeyBindingTestel nombre . Para obtener más información, vea Crear una extensión con una plantilla de elemento de editor.

  3. Agregue las siguientes referencias y establezca CopyLocal en false:

    Microsoft.VisualStudio.Editor

    Microsoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell.14.0

    Microsoft.VisualStudio.TextManager.Interop

    En el archivo de clase KeyBindingTest, cambie el nombre de clase a PurpleCornerBox. Use la bombilla que aparece en el margen izquierdo para realizar los demás cambios adecuados. Dentro del constructor, cambie el nombre de la capa de adorno de KeyBindingTest a PurpleCornerBox:

this.layer = view.GetAdornmentLayer("PurpleCornerBox");

En el archivo de clase KeyBindingTestTextViewCreationListener.cs, cambie el nombre de AdornmentLayer de KeyBindingTest a PurpleCornerBox:

[Export(typeof(AdornmentLayerDefinition))]
[Name("PurpleCornerBox")]
[Order(After = PredefinedAdornmentLayers.Selection, Before = PredefinedAdornmentLayers.Text)]
public AdornmentLayerDefinition editorAdornmentLayer;

Control del comando TYPECHAR

Antes de la versión 15.6 de Visual Studio 2017, la única manera de controlar comandos en una extensión del editor implementaba un IOleCommandTarget filtro de comandos basado. La versión 15.6 de Visual Studio 2017 introdujo un enfoque simplificado moderno basado en controladores de comandos del editor. En las dos secciones siguientes se muestra cómo controlar un comando mediante el enfoque heredado y moderno.

Definir el filtro de comandos (antes de Visual Studio 2017, versión 15.6)

El filtro de comandos es una implementación de IOleCommandTarget, que controla el comando mediante la creación de instancias del adorno.

  1. Agregue un archivo de clase y asígnele el nombre KeyBindingCommandFilter.

  2. Agregue las siguientes directivas using.

    using System;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Text.Editor;
    
    
  3. La clase denominada KeyBindingCommandFilter debe heredar de IOleCommandTarget.

    internal class KeyBindingCommandFilter : IOleCommandTarget
    
  4. Agregue campos privados para la vista de texto, el siguiente comando de la cadena de comandos y una marca para representar si el filtro de comandos ya se ha agregado.

    private IWpfTextView m_textView;
    internal IOleCommandTarget m_nextTarget;
    internal bool m_added;
    internal bool m_adorned;
    
  5. Agregue un constructor que establezca la vista de texto.

    public KeyBindingCommandFilter(IWpfTextView textView)
    {
        m_textView = textView;
        m_adorned = false;
    }
    
  6. Implemente el QueryStatus() método como se indica a continuación.

    int IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        return m_nextTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
    }
    
  7. Implemente el Exec() método para que agregue un cuadro púrpura a la vista si se escribe un carácter de signo más (+).

    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);
    }
    
    

Agregar el filtro de comandos (antes de Visual Studio 2017, versión 15.6)

El proveedor de adornos debe agregar un filtro de comandos a la vista de texto. En este ejemplo, el proveedor implementa IVsTextViewCreationListener para escuchar eventos de creación de vistas de texto. Este proveedor de adornos también exporta la capa de adorno, que define el orden Z del adorno.

  1. En el archivo KeyBindingTestTextViewCreationListener, agregue las siguientes directivas using:

    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;
    
    
  2. Para obtener el adaptador de vista de texto, debe importar .IVsEditorAdaptersFactoryService

    [Import(typeof(IVsEditorAdaptersFactoryService))]
    internal IVsEditorAdaptersFactoryService editorFactory = null;
    
    
  3. Cambie el TextViewCreated método para que agregue .KeyBindingCommandFilter

    public void TextViewCreated(IWpfTextView textView)
    {
        AddCommandFilter(textView, new KeyBindingCommandFilter(textView));
    }
    
  4. El AddCommandFilter controlador obtiene el adaptador de vista de texto y agrega el filtro de comandos.

    void AddCommandFilter(IWpfTextView textView, KeyBindingCommandFilter commandFilter)
    {
        if (commandFilter.m_added == false)
        {
            //get the view adapter from the editor factory
            IOleCommandTarget next;
            IVsTextView view = editorFactory.GetViewAdapter(textView);
    
            int hr = view.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;
            }
        }
    }
    

Implementar un controlador de comandos (a partir de Visual Studio 2017, versión 15.6)

En primer lugar, actualice las referencias de Nuget del proyecto para hacer referencia a la API del editor más reciente:

  1. Haga clic con el botón derecho en el proyecto y seleccione Administrar paquetes Nuget.

  2. En Nuget Administrador de paquetes, active la pestaña Novedades, active la casilla Seleccionar todos los paquetes y, a continuación, seleccione Actualizar.

El controlador de comandos es una implementación de ICommandHandler<T>, que controla el comando mediante la creación de instancias del adorno.

  1. Agregue un archivo de clase y asígnele el nombre KeyBindingCommandHandler.

  2. Agregue las siguientes directivas using.

    using Microsoft.VisualStudio.Commanding;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Text.Editor.Commanding.Commands;
    using Microsoft.VisualStudio.Utilities;
    using System.ComponentModel.Composition;
    
  3. La clase denominada KeyBindingCommandHandler debe heredar de ICommandHandler<TypeCharCommandArgs>y exportarla como ICommandHandler:

    [Export(typeof(ICommandHandler))]
    [ContentType("text")]
    [Name("KeyBindingTest")]
    internal class KeyBindingCommandHandler : ICommandHandler<TypeCharCommandArgs>
    
  4. Agregue un nombre para mostrar del controlador de comandos:

    public string DisplayName => "KeyBindingTest";
    
  5. Implemente el GetCommandState() método como se indica a continuación. Dado que este controlador de comandos controla el comando TYPECHAR del editor principal, puede delegar la habilitación del comando en el editor principal.

    public CommandState GetCommandState(TypeCharCommandArgs args)
    {
        return CommandState.Unspecified;
    }
    
  6. Implemente el ExecuteCommand() método para que agregue un cuadro púrpura a la vista si se escribe un carácter de signo más (+).

    public bool ExecuteCommand(TypeCharCommandArgs args, CommandExecutionContext executionContext)
    {
        if (args.TypedChar == '+')
        {
            bool alreadyAdorned = args.TextView.Properties.TryGetProperty(
                "KeyBindingTextAdorned", out bool adorned) && adorned;
            if (!alreadyAdorned)
            {
                new PurpleCornerBox((IWpfTextView)args.TextView);
                args.TextView.Properties.AddProperty("KeyBindingTextAdorned", true);
            }
        }
    
        return false;
    }
    
    1. Copie la definición de capa de adorno del archivo KeyBindingTestTextViewCreationListener.cs en el archivo KeyBindingCommandHandler.cs y elimine el archivo KeyBindingTestTextViewCreationListener.cs:
    /// <summary>
    /// Defines the adornment layer for the adornment. This layer is ordered
    /// after the selection layer in the Z-order.
    /// </summary>
    [Export(typeof(AdornmentLayerDefinition))]
    [Name("PurpleCornerBox")]
    [Order(After = PredefinedAdornmentLayers.Selection, Before = PredefinedAdornmentLayers.Text)]
    private AdornmentLayerDefinition editorAdornmentLayer;
    

Hacer que el adorno aparezca en cada línea

El adorno original apareció en cada carácter 'a' en un archivo de texto. Ahora que hemos cambiado el código para agregar el adorno en respuesta al + carácter, agrega el adorno solo en la línea donde se escribe el + carácter. Podemos cambiar el código de adorno para que el adorno aparezca una vez más en cada "a".

En el archivo KeyBindingTest.cs , cambie el CreateVisuals() método para recorrer en iteración todas las líneas de la vista para decorar el carácter "a".

private void CreateVisuals(ITextViewLine line)
{
    IWpfTextViewLineCollection textViewLines = this.view.TextViewLines;

    foreach (ITextViewLine textViewLine in textViewLines)
    {
        if (textViewLine.ToString().Contains("a"))
        {
            // Loop through each character, and place a box around any 'a'
            for (int charIndex = textViewLine.Start; charIndex < textViewLine.End; charIndex++)
            {
                if (this.view.TextSnapshot[charIndex] == 'a')
                {
                    SnapshotSpan span = new SnapshotSpan(this.view.TextSnapshot, Span.FromBounds(charIndex, charIndex + 1));
                    Geometry geometry = textViewLines.GetMarkerGeometry(span);
                    if (geometry != null)
                    {
                        var drawing = new GeometryDrawing(this.brush, this.pen, geometry);
                        drawing.Freeze();

                        var drawingImage = new DrawingImage(drawing);
                        drawingImage.Freeze();

                        var image = new Image
                        {
                            Source = drawingImage,
                        };

                        // Align the image with the top of the bounds of the text geometry
                        Canvas.SetLeft(image, geometry.Bounds.Left);
                        Canvas.SetTop(image, geometry.Bounds.Top);

                        this.layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, span, null, image, null);
                    }
                }
            }
        }
    }
}

Compilación y prueba del código

  1. Compile la solución KeyBindingTest y ejecútela en la instancia experimental.

  2. Cree o abra un archivo de texto. Escriba algunas palabras que contengan el carácter "a" y, a continuación, escriba + en cualquier lugar de la vista de texto.

    Un cuadrado púrpura debe aparecer en cada carácter "a" del archivo.