Udostępnij za pośrednictwem


Przewodnik: używanie klawisza skrótu z rozszerzeniem edytora

Możesz odpowiedzieć na klawisze skrótów w rozszerzeniu edytora. W poniższym przewodniku pokazano, jak dodać widok do widoku tekstowego przy użyciu klawisza skrótu. Ten przewodnik jest oparty na szablonie edytora ozdobiania widoku i umożliwia dodanie ozdoby przy użyciu znaku +.

Tworzenie projektu zarządzanej struktury rozszerzalności (MEF)

  1. Utwórz projekt VSIX w języku C#. (W Okno dialogowe Nowy projekt , wybierz pozycję Visual C# / Rozszerzalność, a następnie projekt VSIX. Nadaj rozwiązaniu KeyBindingTestnazwę .

  2. Dodaj szablon elementu ozdobnego tekstu edytora do projektu i nadaj mu KeyBindingTestnazwę . Aby uzyskać więcej informacji, zobacz Tworzenie rozszerzenia za pomocą szablonu elementu edytora.

  3. Dodaj następujące odwołania i ustaw wartość CopyLocal na false:

    Microsoft.VisualStudio.Editor

    Microsoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell.14.0

    Microsoft.VisualStudio.TextManager.Interop

    W pliku klasy KeyBindingTest zmień nazwę klasy na PurpleCornerBox. Użyj żarówki wyświetlanej na lewym marginesie, aby wprowadzić inne odpowiednie zmiany. Wewnątrz konstruktora zmień nazwę warstwy ozdobnej z KeyBindingTest na PurpleCornerBox:

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

W pliku klasy KeyBindingTestTextViewCreationListener.cs zmień nazwę elementu AdornmentLayer z KeyBindingTest na PurpleCornerBox:

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

Obsługa polecenia TYPECHAR

Przed programem Visual Studio 2017 w wersji 15.6 jedynym sposobem obsługi poleceń w rozszerzeniu edytora było zaimplementowanie opartego IOleCommandTarget filtru poleceń. Program Visual Studio 2017 w wersji 15.6 wprowadził nowoczesne uproszczone podejście oparte na programach obsługi poleceń edytora. W kolejnych dwóch sekcjach pokazano, jak obsłużyć polecenie przy użyciu zarówno starszego, jak i nowoczesnego podejścia.

Zdefiniuj filtr poleceń (przed programem Visual Studio 2017 w wersji 15.6)

Filtr poleceń jest implementacją IOleCommandTargetpolecenia , która obsługuje polecenie przez utworzenie wystąpienia elementu adornment.

  1. Dodaj plik klasy i nadaj mu KeyBindingCommandFilternazwę .

  2. Dodaj następujące dyrektywy using.

    using System;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Text.Editor;
    
    
  3. Klasa o nazwie KeyBindingCommandFilter powinna dziedziczyć z klasy IOleCommandTarget.

    internal class KeyBindingCommandFilter : IOleCommandTarget
    
  4. Dodaj pola prywatne dla widoku tekstowego, następne polecenie w łańcuchu poleceń i flagę reprezentującą, czy filtr poleceń został już dodany.

    private IWpfTextView m_textView;
    internal IOleCommandTarget m_nextTarget;
    internal bool m_added;
    internal bool m_adorned;
    
  5. Dodaj konstruktor, który ustawia widok tekstu.

    public KeyBindingCommandFilter(IWpfTextView textView)
    {
        m_textView = textView;
        m_adorned = false;
    }
    
  6. Zaimplementuj metodę QueryStatus() w następujący sposób.

    int IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        return m_nextTarget.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
    }
    
  7. Zaimplementuj metodę Exec() tak, aby dodaje fioletowe pole do widoku, jeśli znak plus (+) jest wpisany.

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

Dodaj filtr poleceń (przed programem Visual Studio 2017 w wersji 15.6)

Dostawca dodatków musi dodać filtr poleceń do widoku tekstowego. W tym przykładzie dostawca implementuje IVsTextViewCreationListener nasłuchiwanie zdarzeń tworzenia widoku tekstu. Ten dostawca dodatków eksportuje również warstwę ozdobną, która definiuje kolejność Z elementu ozdobnego.

  1. W pliku KeyBindingTestTextViewCreationListener dodaj następujące dyrektywy 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. Aby uzyskać kartę widoku tekstu, należy zaimportować element IVsEditorAdaptersFactoryService.

    [Import(typeof(IVsEditorAdaptersFactoryService))]
    internal IVsEditorAdaptersFactoryService editorFactory = null;
    
    
  3. Zmień metodę tak TextViewCreated , aby dodaje element KeyBindingCommandFilter.

    public void TextViewCreated(IWpfTextView textView)
    {
        AddCommandFilter(textView, new KeyBindingCommandFilter(textView));
    }
    
  4. Procedura AddCommandFilter obsługi pobiera adapter widoku tekstu i dodaje filtr polecenia.

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

Implementowanie programu obsługi poleceń (począwszy od programu Visual Studio 2017 w wersji 15.6)

Najpierw zaktualizuj odwołania Nuget projektu, aby odwoływać się do najnowszego interfejsu API edytora:

  1. Kliknij prawym przyciskiem myszy projekt i wybierz polecenie Zarządzaj pakietami Nuget.

  2. W Menedżer pakietów Nuget wybierz kartę Aktualizacje, zaznacz pole wyboru Zaznacz wszystkie pakiety, a następnie wybierz pozycję Aktualizuj.

Procedura obsługi poleceń jest implementacją ICommandHandler<T>klasy , która obsługuje polecenie przez utworzenie wystąpienia elementu adornment.

  1. Dodaj plik klasy i nadaj mu KeyBindingCommandHandlernazwę .

  2. Dodaj następujące dyrektywy 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. Klasa o nazwie KeyBindingCommandHandler powinna dziedziczyć z ICommandHandler<TypeCharCommandArgs>klasy i eksportować ją jako ICommandHandler:

    [Export(typeof(ICommandHandler))]
    [ContentType("text")]
    [Name("KeyBindingTest")]
    internal class KeyBindingCommandHandler : ICommandHandler<TypeCharCommandArgs>
    
  4. Dodaj nazwę wyświetlaną programu obsługi poleceń:

    public string DisplayName => "KeyBindingTest";
    
  5. Zaimplementuj metodę GetCommandState() w następujący sposób. Ponieważ ta procedura obsługi poleceń obsługuje podstawowe polecenie TYPECHAR edytora, może delegować włączenie polecenia do edytora podstawowego.

    public CommandState GetCommandState(TypeCharCommandArgs args)
    {
        return CommandState.Unspecified;
    }
    
  6. Zaimplementuj metodę ExecuteCommand() tak, aby dodaje fioletowe pole do widoku, jeśli znak plus (+) jest wpisany.

    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. Skopiuj definicję warstwy adornment z pliku KeyBindingTestTextViewCreationListener.cs do pliku KeyBindingCommandHandler.cs, a następnie usuń plik 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;
    

Ustaw, że ozdoba jest wyświetlana w każdym wierszu

Oryginalna ozdoba pojawiła się na każdym znaku "a" w pliku tekstowym. Teraz, gdy zmieniliśmy kod, aby dodać ozdobę w odpowiedzi na + znak, dodaje ozdobę tylko w wierszu, w którym + jest wpisany znak. Możemy zmienić kod ozdoby, tak aby ozdoba pojawiała się po raz kolejny na każdym "a".

W pliku KeyBindingTest.cs zmień metodęCreateVisuals(), aby iterować wszystkie wiersze w widoku, aby ozdobić znak "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);
                    }
                }
            }
        }
    }
}

Kompilowanie i testowanie kodu

  1. Skompiluj rozwiązanie KeyBindingTest i uruchom je w wystąpieniu eksperymentalnym.

  2. Utwórz lub otwórz plik tekstowy. Wpisz kilka wyrazów zawierających znak "a", a następnie wpisz + dowolne miejsce w widoku tekstowym.

    Fioletowy kwadrat powinien być wyświetlany na każdym znaku "a" w pliku.