Partager via


Procédure pas à pas : utiliser une touche de raccourci avec une extension d’éditeur

Vous pouvez répondre aux touches de raccourci dans votre extension de l’éditeur. La procédure pas à pas suivante montre comment ajouter un ornement d’affichage à un affichage texte à l’aide d’une touche de raccourci. Cette procédure pas à pas est basée sur le modèle d’éditeur d’ornement de la fenêtre d’affichage et vous permet d’ajouter l’ornement à l’aide du caractère + .

Créer un projet MEF (Managed Extensibility Framework)

  1. Créez un projet VSIX C#. (Dans le Boîte de dialogue Nouveau projet , sélectionnez Visual C# / Extensibilité, puis VSIX Project.) Nommez la solution KeyBindingTest.

  2. Ajoutez un modèle d’élément d’ornement de texte de l’éditeur au projet et nommez-le KeyBindingTest. Pour plus d’informations, consultez Créer une extension avec un modèle d’élément d’éditeur.

  3. Ajoutez les références suivantes et définissez CopyLocal sur false:

    Microsoft.VisualStudio.Editor

    Microsoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell.14.0

    Microsoft.VisualStudio.TextManager.Interop

    Dans le fichier de classe KeyBindingTest, remplacez le nom de la classe par PurpleCornerBox. Utilisez l’ampoule qui apparaît dans la marge gauche pour apporter les autres modifications appropriées. À l’intérieur du constructeur, remplacez le nom de la couche d’ornement de KeyBindingTest par PurpleCornerBox :

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

Dans le fichier de classe KeyBindingTestTextViewCreationListener.cs, remplacez le nom de KeyBindingTest par PurpleCornerBox :

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

Gérer la commande TYPECHAR

Avant Visual Studio 2017 version 15.6, la seule façon de gérer les commandes dans une extension d’éditeur implémentait un IOleCommandTarget filtre de commandes basé. Visual Studio 2017 version 15.6 a introduit une approche simplifiée moderne basée sur les gestionnaires de commandes de l’éditeur. Les deux sections suivantes montrent comment gérer une commande à l’aide de l’approche héritée et moderne.

Définir le filtre de commandes (avant Visual Studio 2017 version 15.6)

Le filtre de commandes est une implémentation de IOleCommandTarget, qui gère la commande en instanciant l’ornement.

  1. Ajoutez un fichier de classe et nommez-le KeyBindingCommandFilter.

  2. Ajoutez les directives using suivantes.

    using System;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Text.Editor;
    
    
  3. La classe nommée KeyBindingCommandFilter doit hériter de IOleCommandTarget.

    internal class KeyBindingCommandFilter : IOleCommandTarget
    
  4. Ajoutez des champs privés pour l’affichage texte, la commande suivante dans la chaîne de commandes et un indicateur pour représenter si le filtre de commandes a déjà été ajouté.

    private IWpfTextView m_textView;
    internal IOleCommandTarget m_nextTarget;
    internal bool m_added;
    internal bool m_adorned;
    
  5. Ajoutez un constructeur qui définit l’affichage texte.

    public KeyBindingCommandFilter(IWpfTextView textView)
    {
        m_textView = textView;
        m_adorned = false;
    }
    
  6. Implémentez la QueryStatus() méthode comme suit.

    int IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        return m_nextTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
    }
    
  7. Implémentez la Exec() méthode afin qu’elle ajoute une zone violette à la vue si un caractère signe plus (+) est tapé.

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

Ajouter le filtre de commandes (avant Visual Studio 2017 version 15.6)

Le fournisseur d’ornements doit ajouter un filtre de commande à l’affichage texte. Dans cet exemple, le fournisseur implémente IVsTextViewCreationListener l’écoute des événements de création d’affichage de texte. Ce fournisseur d’ornements exporte également la couche d’ornements, qui définit l’ordre Z de l’ornement.

  1. Dans le fichier KeyBindingTestTextViewCreationListener, ajoutez les directives suivantes à l’aide :

    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. Pour obtenir l’adaptateur d’affichage de texte, vous devez importer le IVsEditorAdaptersFactoryService.

    [Import(typeof(IVsEditorAdaptersFactoryService))]
    internal IVsEditorAdaptersFactoryService editorFactory = null;
    
    
  3. Modifiez la TextViewCreated méthode afin qu’elle ajoute le KeyBindingCommandFilter.

    public void TextViewCreated(IWpfTextView textView)
    {
        AddCommandFilter(textView, new KeyBindingCommandFilter(textView));
    }
    
  4. Le AddCommandFilter gestionnaire obtient l’adaptateur de vue de texte et ajoute le filtre de commandes.

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

Implémenter un gestionnaire de commandes (à partir de Visual Studio 2017 version 15.6)

Tout d’abord, mettez à jour les références Nuget du projet pour référencer la dernière API de l’éditeur :

  1. Cliquez avec le bouton droit sur le projet et sélectionnez Gérer les packages Nuget.

  2. Dans Nuget Gestionnaire de package, sélectionnez l’onglet Mises à jour, sélectionnez la zone Sélectionner tous les packages case activée box, puis sélectionnez Mettre à jour.

Le gestionnaire de commandes est une implémentation de ICommandHandler<T>, qui gère la commande en instanciant l’ornement.

  1. Ajoutez un fichier de classe et nommez-le KeyBindingCommandHandler.

  2. Ajoutez les directives using suivantes.

    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 nommée KeyBindingCommandHandler doit hériter et ICommandHandler<TypeCharCommandArgs>l’exporter comme ICommandHandlersuit :

    [Export(typeof(ICommandHandler))]
    [ContentType("text")]
    [Name("KeyBindingTest")]
    internal class KeyBindingCommandHandler : ICommandHandler<TypeCharCommandArgs>
    
  4. Ajoutez un nom complet du gestionnaire de commandes :

    public string DisplayName => "KeyBindingTest";
    
  5. Implémentez la GetCommandState() méthode comme suit. Étant donné que ce gestionnaire de commandes gère la commande TYPECHAR de l’éditeur principal, il peut déléguer l’activation de la commande à l’éditeur principal.

    public CommandState GetCommandState(TypeCharCommandArgs args)
    {
        return CommandState.Unspecified;
    }
    
  6. Implémentez la ExecuteCommand() méthode afin qu’elle ajoute une zone violette à la vue si un caractère signe plus (+) est tapé.

    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. Copiez la définition de couche d’ornement à partir du fichier KeyBindingTestTextViewCreationListener.cs dans le fichier KeyBindingCommandHandler.cs, puis supprimez le fichier 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;
    

Faire apparaître l’ornement sur chaque ligne

L’ornement d’origine est apparu sur chaque caractère 'a' dans un fichier texte. Maintenant que nous avons modifié le code pour ajouter l’ornement en réponse au + caractère, il ajoute l’ornement uniquement sur la ligne où le + caractère est tapé. Nous pouvons modifier le code d’ornement afin que l’ornement s’affiche une fois de plus sur chaque 'a'.

Dans le fichier KeyBindingTest.cs , modifiez la CreateVisuals() méthode pour itérer toutes les lignes de la vue pour décorer le caractère « 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);
                    }
                }
            }
        }
    }
}

Générer et tester le code

  1. Générez la solution KeyBindingTest et exécutez-la dans l’instance expérimentale.

  2. Créez ou ouvrez un fichier texte. Tapez certains mots contenant le caractère « a », puis tapez + n’importe où dans l’affichage texte.

    Un carré violet doit apparaître sur chaque caractère « a » dans le fichier.