Procedura dettagliata: Usare un tasto di scelta rapida con un'estensione dell'editor

È possibile rispondere ai tasti di scelta rapida nell'estensione dell'editor. La procedura dettagliata seguente illustra come aggiungere una struttura di visualizzazione a una visualizzazione di testo usando un tasto di scelta rapida. Questa procedura dettagliata si basa sul modello dell'editor di oggetti decorativi del riquadro di visualizzazione e consente di aggiungere lo strumento decorativo usando il carattere + .

Creare un progetto MEF (Managed Extensibility Framework)

  1. Creare un progetto VSIX C#. (In Finestra di dialogo Nuovo progetto , selezionare Visual C# / Estendibilità e quindi progetto VSIX. Assegnare alla soluzione KeyBindingTestil nome .

  2. Aggiungere un modello di elemento Di struttura del testo dell'editor al progetto e denominarlo KeyBindingTest. Per altre informazioni, vedere Creare un'estensione con un modello di elemento dell'editor.

  3. Aggiungere i riferimenti seguenti e impostare CopyLocal su false:

    Microsoft.VisualStudio.Editor

    Microsoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell.14.0

    Microsoft.VisualStudio.TextManager.Interop

    Nel file di classe KeyBindingTest modificare il nome della classe in PurpleCornerBox. Usare la lampadina visualizzata nel margine sinistro per apportare le altre modifiche appropriate. All'interno del costruttore modificare il nome del livello decorativo da KeyBindingTest a PurpleCornerBox:

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

Nel file di classe KeyBindingTestTextViewCreationListener.cs modificare il nome di AdornmentLayer da KeyBindingTest a PurpleCornerBox:

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

Gestire il comando TYPECHAR

Prima di Visual Studio 2017 versione 15.6 l'unico modo per gestire i comandi in un'estensione dell'editor stava implementando un IOleCommandTarget filtro dei comandi basato. Visual Studio 2017 versione 15.6 ha introdotto un approccio semplificato moderno basato sui gestori dei comandi dell'editor. Le due sezioni successive illustrano come gestire un comando usando sia l'approccio legacy che quello moderno.

Definire il filtro dei comandi (prima di Visual Studio 2017 versione 15.6)

Il filtro dei comandi è un'implementazione di IOleCommandTarget, che gestisce il comando creando un'istanza dello strumento decorativo.

  1. Aggiungere un file di classe e assegnargli il nome KeyBindingCommandFilter.

  2. Aggiungere le direttive using seguenti.

    using System;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Text.Editor;
    
    
  3. La classe denominata KeyBindingCommandFilter deve ereditare da IOleCommandTarget.

    internal class KeyBindingCommandFilter : IOleCommandTarget
    
  4. Aggiungere campi privati per la visualizzazione testo, il comando successivo nella catena di comandi e un flag per indicare se il filtro dei comandi è già stato aggiunto.

    private IWpfTextView m_textView;
    internal IOleCommandTarget m_nextTarget;
    internal bool m_added;
    internal bool m_adorned;
    
  5. Aggiungere un costruttore che imposta la visualizzazione testo.

    public KeyBindingCommandFilter(IWpfTextView textView)
    {
        m_textView = textView;
        m_adorned = false;
    }
    
  6. Implementare il QueryStatus() metodo come indicato di seguito.

    int IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        return m_nextTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
    }
    
  7. Implementare il Exec() metodo in modo che aggiunga una casella viola alla visualizzazione se viene digitato un segno più (+).

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

Aggiungere il filtro dei comandi (prima di Visual Studio 2017 versione 15.6)

Il provider di strumenti decorativi deve aggiungere un filtro di comando alla visualizzazione testo. In questo esempio, il provider implementa IVsTextViewCreationListener per ascoltare gli eventi di creazione della visualizzazione testo. Questo provider di oggetti decorativi esporta anche il livello decorativo, che definisce l'ordine Z dell'oggetto decorativo.

  1. Nel file KeyBindingTestTextViewCreationListener aggiungere le direttive using seguenti:

    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. Per ottenere l'adattatore di visualizzazione testo, è necessario importare .IVsEditorAdaptersFactoryService

    [Import(typeof(IVsEditorAdaptersFactoryService))]
    internal IVsEditorAdaptersFactoryService editorFactory = null;
    
    
  3. Modificare il TextViewCreated metodo in modo che aggiunga .KeyBindingCommandFilter

    public void TextViewCreated(IWpfTextView textView)
    {
        AddCommandFilter(textView, new KeyBindingCommandFilter(textView));
    }
    
  4. Il AddCommandFilter gestore ottiene l'adattatore di visualizzazione testo e aggiunge il filtro dei comandi.

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

Implementare un gestore comandi (a partire da Visual Studio 2017 versione 15.6)

Prima di tutto, aggiornare i riferimenti NuGet del progetto per fare riferimento all'API dell'editor più recente:

  1. Fare clic con il pulsante destro del mouse sul progetto e scegliere Gestisci pacchetti NuGet.

  2. In NuGet Gestione pacchetti selezionare la scheda Aggiornamenti, selezionare la casella di controllo Seleziona tutti i pacchetti e quindi selezionare Aggiorna.

Il gestore dei comandi è un'implementazione di ICommandHandler<T>, che gestisce il comando creando un'istanza dello strumento decorativo.

  1. Aggiungere un file di classe e assegnargli il nome KeyBindingCommandHandler.

  2. Aggiungere le direttive using seguenti.

    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 classe denominata KeyBindingCommandHandler deve ereditare da ICommandHandler<TypeCharCommandArgs>ed esportarla come ICommandHandler:

    [Export(typeof(ICommandHandler))]
    [ContentType("text")]
    [Name("KeyBindingTest")]
    internal class KeyBindingCommandHandler : ICommandHandler<TypeCharCommandArgs>
    
  4. Aggiungere un nome visualizzato del gestore comandi:

    public string DisplayName => "KeyBindingTest";
    
  5. Implementare il GetCommandState() metodo come indicato di seguito. Poiché questo gestore comandi gestisce il comando TYPECHAR dell'editor principale, può delegare l'abilitazione del comando all'editor principale.

    public CommandState GetCommandState(TypeCharCommandArgs args)
    {
        return CommandState.Unspecified;
    }
    
  6. Implementare il ExecuteCommand() metodo in modo che aggiunga una casella viola alla visualizzazione se viene digitato un segno più (+).

    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. Copiare la definizione del livello decorativo dal file KeyBindingTestTextViewCreationListener.cs nel file KeyBindingCommandHandler.cs e quindi eliminare il file 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;
    

Fare in modo che la decorazione venga visualizzata su ogni riga

La decorazione originale è apparsa su ogni carattere 'a' in un file di testo. Ora che il codice è stato modificato per aggiungere la decorazione in risposta al + carattere, aggiunge la decorazione solo sulla riga in cui viene digitato il + carattere. È possibile modificare il codice di adornazione in modo che la decorazione venga visualizzata ancora una volta in ogni 'a'.

Nel file KeyBindingTest.cs modificare il CreateVisuals() metodo per scorrere tutte le righe nella visualizzazione per decorare il carattere '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);
                    }
                }
            }
        }
    }
}

Compilare e testare il codice

  1. Compilare la soluzione KeyBindingTest ed eseguirla nell'istanza sperimentale.

  2. Creare o aprire un file di testo. Digitare alcune parole contenenti il carattere 'a', quindi digitare + in qualsiasi punto della visualizzazione testo.

    Un quadrato viola dovrebbe essere visualizzato su ogni carattere "a" nel file.