Bagikan melalui


Panduan: Menggunakan perintah shell dengan ekstensi editor

Dari VSPackage, Anda dapat menambahkan fitur seperti perintah menu ke editor. Panduan ini menunjukkan cara menambahkan hiasan ke tampilan teks di editor dengan memanggil perintah menu.

Panduan ini menunjukkan penggunaan VSPackage bersama dengan bagian komponen Managed Extensibility Framework (MEF). Anda harus menggunakan VSPackage untuk mendaftarkan perintah menu dengan shell Visual Studio. Dan, Anda dapat menggunakan perintah untuk mengakses bagian komponen MEF.

Membuat ekstensi dengan perintah menu

Buat VSPackage yang menempatkan perintah menu bernama Tambahkan Hiasan pada menu Alat .

  1. Buat proyek C# VSIX bernama MenuCommandTest, dan tambahkan nama templat item Perintah Kustom AddAdornment. Untuk informasi selengkapnya, lihat Membuat ekstensi dengan perintah menu.

  2. Solusi bernama MenuCommandTest terbuka. File MenuCommandTestPackage memiliki kode yang membuat perintah menu dan meletakkannya di menu Alat . Pada titik ini, perintah hanya menyebabkan kotak pesan muncul. Langkah-langkah selanjutnya akan menunjukkan cara mengubah ini untuk menampilkan hiasan komentar.

  3. Buka file source.extension.vsixmanifest di Editor Manifes VSIX. Tab Assets harus memiliki baris untuk Microsoft.VisualStudio.VsPackage bernama MenuCommandTest.

  4. Simpan dan tutup file source.extension.vsixmanifest .

Menambahkan ekstensi MEF ke ekstensi perintah

  1. Di Penjelajah Solusi, klik kanan simpul solusi, klik Tambahkan, lalu klik Proyek Baru. Dalam kotak dialog Tambahkan Proyek Baru, klik Ekstensibilitas di bawah Visual C#, lalu Proyek VSIX. Beri nama proyek CommentAdornmentTest.

  2. Karena proyek ini akan berinteraksi dengan rakitan VSPackage bernama kuat, Anda harus menandatangani rakitan. Anda dapat menggunakan kembali file kunci yang sudah dibuat untuk rakitan VSPackage.

    1. Buka properti proyek dan pilih tab Penandatanganan .

    2. Pilih Tanda tangani rakitan.

    3. Di bawah Pilih file kunci nama yang kuat, pilih file Key.snk yang dihasilkan untuk rakitan MenuCommandTest.

Lihat ekstensi MEF dalam proyek VSPackage

Karena Anda menambahkan komponen MEF ke VSPackage, Anda harus menentukan kedua jenis aset dalam manifes.

Catatan

Untuk mendapatkan informasi selengkapnya tentang MEF, lihat Managed Extensibility Framework (MEF).

Untuk merujuk ke komponen MEF dalam proyek VSPackage

  1. Dalam proyek MenuCommandTest, buka file source.extension.vsixmanifest di Editor Manifes VSIX.

  2. Pada tab Aset , klik Baru.

  3. Di daftar Jenis, pilih Microsoft.VisualStudio.MefComponent.

  4. Di daftar Sumber, pilih Proyek dalam solusi saat ini.

  5. Di daftar Proyek, pilih KomentarAdornmentTest.

  6. Simpan dan tutup file source.extension.vsixmanifest .

  7. Pastikan bahwa proyek MenuCommandTest memiliki referensi ke proyek CommentAdornmentTest.

  8. Dalam proyek CommentAdornmentTest, atur proyek untuk menghasilkan assembly. Di Penjelajah Solusi, pilih proyek dan lihat di jendela Properti untuk properti Salin Output Build ke OutputDirectory, dan atur ke true.

Menentukan hiasan komentar

Hiasan komentar itu sendiri terdiri dari ITrackingSpan yang melacak teks yang dipilih, dan beberapa string yang mewakili penulis dan deskripsi teks.

Untuk menentukan hiasan komentar

  1. Dalam proyek CommentAdornmentTest, tambahkan file kelas baru dan beri nama CommentAdornment.

  2. Tambahkan referensi berikut:

    1. Microsoft.VisualStudio.CoreUtility

    2. Microsoft.VisualStudio.Text.Data

    3. Microsoft.VisualStudio.Text.Logic

    4. Microsoft.VisualStudio.Text.UI

    5. Microsoft.VisualStudio.Text.UI.Wpf

    6. System.ComponentModel.Composition

    7. PresentationCore

    8. PresentationFramework

    9. WindowsBase

  3. Tambahkan direktif berikut using .

    using Microsoft.VisualStudio.Text;
    
  4. File harus berisi kelas bernama CommentAdornment.

    internal class CommentAdornment
    
  5. Tambahkan tiga bidang ke CommentAdornment kelas untuk ITrackingSpan, penulis, dan deskripsi.

    public readonly ITrackingSpan Span;
    public readonly string Author;
    public readonly string Text;
    
  6. Tambahkan konstruktor yang menginisialisasi bidang.

    public CommentAdornment(SnapshotSpan span, string author, string text)
    {
        this.Span = span.Snapshot.CreateTrackingSpan(span, SpanTrackingMode.EdgeExclusive);
        this.Author = author;
        this.Text = text;
    }
    

Membuat elemen visual untuk hiasan

Tentukan elemen visual untuk hiasan Anda. Untuk panduan ini, tentukan kontrol yang mewarisi dari kelas CanvasWindows Presentation Foundation (WPF).

  1. Buat kelas di proyek CommentAdornmentTest, dan beri nama CommentBlock.

  2. Tambahkan direktif berikut using .

    using Microsoft.VisualStudio.Text;
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Shapes;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Utilities;
    
  3. Buat kelas mewarisi CommentBlock dari Canvas.

    internal class CommentBlock : Canvas
    { }
    
  4. Tambahkan beberapa bidang privat untuk menentukan aspek visual hiasan.

    private Geometry textGeometry;
    private Grid commentGrid;
    private static Brush brush;
    private static Pen solidPen;
    private static Pen dashPen;
    
  5. Tambahkan konstruktor yang menentukan hiasan komentar dan menambahkan teks yang relevan.

    public CommentBlock(double textRightEdge, double viewRightEdge,
            Geometry newTextGeometry, string author, string body)
    {
        if (brush == null)
        {
            brush = new SolidColorBrush(Color.FromArgb(0x20, 0x00, 0xff, 0x00));
            brush.Freeze();
            Brush penBrush = new SolidColorBrush(Colors.Green);
            penBrush.Freeze();
            solidPen = new Pen(penBrush, 0.5);
            solidPen.Freeze();
            dashPen = new Pen(penBrush, 0.5);
            dashPen.DashStyle = DashStyles.Dash;
            dashPen.Freeze();
        }
    
        this.textGeometry = newTextGeometry;
    
        TextBlock tb1 = new TextBlock();
        tb1.Text = author;
        TextBlock tb2 = new TextBlock();
        tb2.Text = body;
    
        const int MarginWidth = 8;
        this.commentGrid = new Grid();
        this.commentGrid.RowDefinitions.Add(new RowDefinition());
        this.commentGrid.RowDefinitions.Add(new RowDefinition());
        ColumnDefinition cEdge = new ColumnDefinition();
        cEdge.Width = new GridLength(MarginWidth);
        ColumnDefinition cEdge2 = new ColumnDefinition();
        cEdge2.Width = new GridLength(MarginWidth);
        this.commentGrid.ColumnDefinitions.Add(cEdge);
        this.commentGrid.ColumnDefinitions.Add(new ColumnDefinition());
        this.commentGrid.ColumnDefinitions.Add(cEdge2);
    
        System.Windows.Shapes.Rectangle rect = new System.Windows.Shapes.Rectangle();
        rect.RadiusX = 6;
        rect.RadiusY = 3;
        rect.Fill = brush;
        rect.Stroke = Brushes.Green;
    
            Size inf = new Size(double.PositiveInfinity, double.PositiveInfinity);
            tb1.Measure(inf);
            tb2.Measure(inf);
            double middleWidth = Math.Max(tb1.DesiredSize.Width, tb2.DesiredSize.Width);
            this.commentGrid.Width = middleWidth + 2 * MarginWidth;
    
        Grid.SetColumn(rect, 0);
        Grid.SetRow(rect, 0);
        Grid.SetRowSpan(rect, 2);
        Grid.SetColumnSpan(rect, 3);
        Grid.SetRow(tb1, 0);
        Grid.SetColumn(tb1, 1);
        Grid.SetRow(tb2, 1);
        Grid.SetColumn(tb2, 1);
        this.commentGrid.Children.Add(rect);
        this.commentGrid.Children.Add(tb1);
        this.commentGrid.Children.Add(tb2);
    
        Canvas.SetLeft(this.commentGrid, Math.Max(viewRightEdge - this.commentGrid.Width - 20.0, textRightEdge + 20.0));
        Canvas.SetTop(this.commentGrid, textGeometry.GetRenderBounds(solidPen).Top);
    
        this.Children.Add(this.commentGrid);
    }
    
  6. Terapkan juga penanganan OnRender aktivitas yang menarik hiasan.

    protected override void OnRender(DrawingContext dc)
    {
        base.OnRender(dc);
        if (this.textGeometry != null)
        {
            dc.DrawGeometry(brush, solidPen, this.textGeometry);
            Rect textBounds = this.textGeometry.GetRenderBounds(solidPen);
            Point p1 = new Point(textBounds.Right, textBounds.Bottom);
            Point p2 = new Point(Math.Max(Canvas.GetLeft(this.commentGrid) - 20.0, p1.X), p1.Y);
            Point p3 = new Point(Math.Max(Canvas.GetLeft(this.commentGrid), p1.X), (Canvas.GetTop(this.commentGrid) + p1.Y) * 0.5);
            dc.DrawLine(dashPen, p1, p2);
            dc.DrawLine(dashPen, p2, p3);
        }
    }
    

Menambahkan IWpfTextViewCreationListener

IWpfTextViewCreationListener adalah bagian komponen MEF yang dapat Anda gunakan untuk mendengarkan melihat peristiwa pembuatan.

  1. Tambahkan file kelas ke proyek CommentAdornmentTest dan beri nama Connector.

  2. Tambahkan direktif berikut using .

    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Utilities;
    
  3. Deklarasikan kelas yang mengimplementasikan IWpfTextViewCreationListener, dan mengekspornya dengan ContentTypeAttribute "teks" dan TextViewRoleAttribute dari Document. Atribut jenis konten menentukan jenis konten yang diterapkan komponen. Jenis teks adalah jenis dasar untuk semua jenis file non-biner. Oleh karena itu, hampir setiap tampilan teks yang dibuat akan berjenis ini. Atribut peran tampilan teks menentukan jenis tampilan teks yang diterapkan komponen. Peran tampilan teks dokumen umumnya memperlihatkan teks yang terdiri dari baris dan disimpan dalam file.

    [Export(typeof(IWpfTextViewCreationListener))]
    [ContentType("text")]
    [TextViewRole(PredefinedTextViewRoles.Document)]
    public sealed class Connector : IWpfTextViewCreationListener
    
  4. Terapkan TextViewCreated metode sehingga memanggil peristiwa statis Create() dari CommentAdornmentManager.

    public void TextViewCreated(IWpfTextView textView)
    {
        CommentAdornmentManager.Create(textView);
    }
    
  5. Tambahkan metode yang dapat Anda gunakan untuk menjalankan perintah.

    static public void Execute(IWpfTextViewHost host)
    {
        IWpfTextView view = host.TextView;
        //Add a comment on the selected text. 
        if (!view.Selection.IsEmpty)
        {
            //Get the provider for the comment adornments in the property bag of the view.
            CommentAdornmentProvider provider = view.Properties.GetProperty<CommentAdornmentProvider>(typeof(CommentAdornmentProvider));
    
            //Add some arbitrary author and comment text. 
            string author = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
            string comment = "Four score....";
    
            //Add the comment adornment using the provider.
            provider.Add(view.Selection.SelectedSpans[0], author, comment);
        }
    }
    

Menentukan lapisan hiasan

Untuk menambahkan hiasan baru, Anda harus menentukan lapisan hiasan.

Untuk menentukan lapisan hiasan

  1. Connector Di kelas , deklarasikan bidang publik jenis AdornmentLayerDefinition, dan ekspor dengan NameAttribute yang menentukan nama unik untuk lapisan hiasan dan OrderAttribute yang menentukan hubungan urutan Z lapisan hiasan ini ke lapisan tampilan teks lainnya (teks, tanda sisipan, dan pilihan).

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

Berikan hiasan komentar

Saat Anda menentukan hiasan, terapkan juga penyedia hiasan komentar dan manajer hiasan komentar. Penyedia hiasan komentar menyimpan daftar hiasan komentar, mendengarkan Changed peristiwa pada buffer teks yang mendasarinya, dan menghapus hiasan komentar saat teks yang mendasarinya dihapus.

  1. Tambahkan file kelas baru ke proyek CommentAdornmentTest dan beri nama CommentAdornmentProvider.

  2. Tambahkan direktif berikut using .

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    
  3. Tambahkan kelas bernama CommentAdornmentProvider.

    internal class CommentAdornmentProvider
    {
    }
    
  4. Tambahkan bidang privat untuk buffer teks dan daftar hiasan komentar yang terkait dengan buffer.

    private ITextBuffer buffer;
    private IList<CommentAdornment> comments = new List<CommentAdornment>();
    
    
  5. Tambahkan konstruktor untuk CommentAdornmentProvider. Konstruktor ini harus memiliki akses privat karena penyedia dibuat oleh Create() metode . Konstruktor menambahkan OnBufferChanged penanganan aktivitas ke Changed peristiwa.

    private CommentAdornmentProvider(ITextBuffer buffer)
    {
        this.buffer = buffer;
        //listen to the Changed event so we can react to deletions. 
        this.buffer.Changed += OnBufferChanged;
    }
    
    
  6. Tambahkan metode Create().

    public static CommentAdornmentProvider Create(IWpfTextView view)
    {
        return view.Properties.GetOrCreateSingletonProperty<CommentAdornmentProvider>(delegate { return new CommentAdornmentProvider(view.TextBuffer); });
    }
    
    
  7. Tambahkan metode Detach().

    public void Detach()
    {
        if (this.buffer != null)
        {
            //remove the Changed listener 
            this.buffer.Changed -= OnBufferChanged;
            this.buffer = null;
        }
    }
    
  8. Tambahkan penanganan OnBufferChanged aktivitas.

    private void OnBufferChanged(object sender, TextContentChangedEventArgs e)
    {
        //Make a list of all comments that have a span of at least one character after applying the change. There is no need to raise a changed event for the deleted adornments. The adornments are deleted only if a text change would cause the view to reformat the line and discard the adornments.
        IList<CommentAdornment> keptComments = new List<CommentAdornment>(this.comments.Count);
    
        foreach (CommentAdornment comment in this.comments)
        {
            Span span = comment.Span.GetSpan(e.After);
            //if a comment does not span at least one character, its text was deleted.
            if (span.Length != 0)
            {
                keptComments.Add(comment);
            }
        }
    
        this.comments = keptComments;
    }
    
  9. Tambahkan deklarasi untuk suatu CommentsChanged acara.

    public event EventHandler<CommentsChangedEventArgs> CommentsChanged;
    
  10. Buat Add() metode untuk menambahkan hiasan.

    public void Add(SnapshotSpan span, string author, string text)
    {
        if (span.Length == 0)
            throw new ArgumentOutOfRangeException("span");
        if (author == null)
            throw new ArgumentNullException("author");
        if (text == null)
            throw new ArgumentNullException("text");
    
        //Create a comment adornment given the span, author and text.
        CommentAdornment comment = new CommentAdornment(span, author, text);
    
        //Add it to the list of comments. 
        this.comments.Add(comment);
    
        //Raise the changed event.
        EventHandler<CommentsChangedEventArgs> commentsChanged = this.CommentsChanged;
        if (commentsChanged != null)
            commentsChanged(this, new CommentsChangedEventArgs(comment, null));
    }
    
    
  11. RemoveComments() Tambahkan metode .

    public void RemoveComments(SnapshotSpan span)
    {
        EventHandler<CommentsChangedEventArgs> commentsChanged = this.CommentsChanged;
    
        //Get a list of all the comments that are being kept
        IList<CommentAdornment> keptComments = new List<CommentAdornment>(this.comments.Count);
    
        foreach (CommentAdornment comment in this.comments)
        {
            //find out if the given span overlaps with the comment text span. If two spans are adjacent, they do not overlap. To consider adjacent spans, use IntersectsWith. 
            if (comment.Span.GetSpan(span.Snapshot).OverlapsWith(span))
            {
                //Raise the change event to delete this comment. 
                if (commentsChanged != null)
                    commentsChanged(this, new CommentsChangedEventArgs(null, comment));
            }
            else
                keptComments.Add(comment);
        }
    
        this.comments = keptComments;
    }
    
  12. GetComments() Tambahkan metode yang mengembalikan semua komentar dalam rentang rekam jepret tertentu.

    public Collection<CommentAdornment> GetComments(SnapshotSpan span)
    {
        IList<CommentAdornment> overlappingComments = new List<CommentAdornment>();
        foreach (CommentAdornment comment in this.comments)
        {
            if (comment.Span.GetSpan(span.Snapshot).OverlapsWith(span))
                overlappingComments.Add(comment);
        }
    
        return new Collection<CommentAdornment>(overlappingComments);
    }
    
  13. Tambahkan kelas bernama CommentsChangedEventArgs, sebagai berikut.

    internal class CommentsChangedEventArgs : EventArgs
    {
        public readonly CommentAdornment CommentAdded;
    
        public readonly CommentAdornment CommentRemoved;
    
        public CommentsChangedEventArgs(CommentAdornment added, CommentAdornment removed)
        {
            this.CommentAdded = added;
            this.CommentRemoved = removed;
        }
    }
    

Mengelola hiasan komentar

Manajer hiasan komentar membuat hiasan dan menambahkannya ke lapisan hiasan. Ini mendengarkan LayoutChanged peristiwa dan Closed sehingga dapat memindahkan atau menghapus hiasan. Ini juga mendengarkan CommentsChanged peristiwa yang dipicu oleh penyedia hiasan komentar saat komentar ditambahkan atau dihapus.

  1. Tambahkan file kelas ke proyek CommentAdornmentTest dan beri nama CommentAdornmentManager.

  2. Tambahkan direktif berikut using .

    using System;
    using System.Collections.Generic;
    using System.Windows.Media;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Text.Formatting;
    
  3. Tambahkan kelas bernama CommentAdornmentManager.

    internal class CommentAdornmentManager
        {
        }
    
  4. Tambahkan beberapa bidang privat.

    private readonly IWpfTextView view;
    private readonly IAdornmentLayer layer;
    private readonly CommentAdornmentProvider provider;
    
  5. Tambahkan konstruktor yang berlangganan manajer ke LayoutChanged peristiwa dan Closed , dan juga ke CommentsChanged acara. Konstruktor bersifat privat karena manajer dibuat oleh metode statis Create() .

    private CommentAdornmentManager(IWpfTextView view)
    {
        this.view = view;
        this.view.LayoutChanged += OnLayoutChanged;
        this.view.Closed += OnClosed;
    
        this.layer = view.GetAdornmentLayer("CommentAdornmentLayer");
    
        this.provider = CommentAdornmentProvider.Create(view);
        this.provider.CommentsChanged += OnCommentsChanged;
    }
    
  6. Create() Tambahkan metode yang mendapatkan penyedia atau buat jika perlu.

    public static CommentAdornmentManager Create(IWpfTextView view)
    {
        return view.Properties.GetOrCreateSingletonProperty<CommentAdornmentManager>(delegate { return new CommentAdornmentManager(view); });
    }
    
  7. Tambahkan handler CommentsChanged .

    private void OnCommentsChanged(object sender, CommentsChangedEventArgs e)
    {
        //Remove the comment (when the adornment was added, the comment adornment was used as the tag). 
        if (e.CommentRemoved != null)
            this.layer.RemoveAdornmentsByTag(e.CommentRemoved);
    
        //Draw the newly added comment (this will appear immediately: the view does not need to do a layout). 
        if (e.CommentAdded != null)
            this.DrawComment(e.CommentAdded);
    }
    
  8. Tambahkan handler Closed .

    private void OnClosed(object sender, EventArgs e)
    {
        this.provider.Detach();
        this.view.LayoutChanged -= OnLayoutChanged;
        this.view.Closed -= OnClosed;
    }
    
  9. Tambahkan handler LayoutChanged .

    private void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
    {
        //Get all of the comments that intersect any of the new or reformatted lines of text.
        List<CommentAdornment> newComments = new List<CommentAdornment>();
    
        //The event args contain a list of modified lines and a NormalizedSpanCollection of the spans of the modified lines.  
        //Use the latter to find the comments that intersect the new or reformatted lines of text. 
        foreach (Span span in e.NewOrReformattedSpans)
        {
            newComments.AddRange(this.provider.GetComments(new SnapshotSpan(this.view.TextSnapshot, span)));
        }
    
        //It is possible to get duplicates in this list if a comment spanned 3 lines, and the first and last lines were modified but the middle line was not. 
        //Sort the list and skip duplicates.
        newComments.Sort(delegate(CommentAdornment a, CommentAdornment b) { return a.GetHashCode().CompareTo(b.GetHashCode()); });
    
        CommentAdornment lastComment = null;
        foreach (CommentAdornment comment in newComments)
        {
            if (comment != lastComment)
            {
                lastComment = comment;
                this.DrawComment(comment);
            }
        }
    }
    
  10. Tambahkan metode privat yang menggambar komentar.

    private void DrawComment(CommentAdornment comment)
    {
        SnapshotSpan span = comment.Span.GetSpan(this.view.TextSnapshot);
        Geometry g = this.view.TextViewLines.GetMarkerGeometry(span);
    
        if (g != null)
        {
            //Find the rightmost coordinate of all the lines that intersect the adornment.
            double maxRight = 0.0;
            foreach (ITextViewLine line in this.view.TextViewLines.GetTextViewLinesIntersectingSpan(span))
                maxRight = Math.Max(maxRight, line.Right);
    
            //Create the visualization.
            CommentBlock block = new CommentBlock(maxRight, this.view.ViewportRight, g, comment.Author, comment.Text);
    
            //Add it to the layer.
            this.layer.AddAdornment(span, comment, block);
        }
    }
    

Gunakan perintah menu untuk menambahkan hiasan komentar

Anda dapat menggunakan perintah menu untuk membuat hiasan komentar dengan menerapkan MenuItemCallback metode VSPackage.

  1. Tambahkan referensi berikut ke proyek MenuCommandTest:

    • Microsoft.VisualStudio.TextManager.Interop

    • Microsoft.VisualStudio.Editor

    • Microsoft.VisualStudio.Text.UI.Wpf

  2. Buka file AddAdornment.cs dan tambahkan direktif berikutusing.

    using Microsoft.VisualStudio.TextManager.Interop;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Editor;
    using CommentAdornmentTest;
    
  3. Execute() Hapus metode dan tambahkan handler perintah berikut.

    private async void AddAdornmentHandler(object sender, EventArgs e)
    {
    }
    
  4. Tambahkan kode untuk mendapatkan tampilan aktif. Anda harus mendapatkan SVsTextManager shell Visual Studio untuk mendapatkan yang aktif IVsTextView.

    private async void AddAdornmentHandler(object sender, EventArgs e)
    {
        IVsTextManager txtMgr = (IVsTextManager) await ServiceProvider.GetServiceAsync(typeof(SVsTextManager));
        IVsTextView vTextView = null;
        int mustHaveFocus = 1;
        txtMgr.GetActiveView(mustHaveFocus, null, out vTextView);
    }
    
  5. Jika tampilan teks ini adalah contoh tampilan teks editor, Anda dapat mentransmisikannya ke IVsUserData antarmuka lalu mendapatkan IWpfTextViewHost dan yang terkait IWpfTextView. IWpfTextViewHost Gunakan untuk memanggil Connector.Execute() metode , yang mendapatkan penyedia hiasan komentar dan menambahkan hiasan. Handler perintah sekarang akan terlihat seperti kode ini:

    private async void AddAdornmentHandler(object sender, EventArgs e)
    {
        IVsTextManager txtMgr = (IVsTextManager) await ServiceProvider.GetServiceAsync(typeof(SVsTextManager));
        IVsTextView vTextView = null;
        int mustHaveFocus = 1;
        txtMgr.GetActiveView(mustHaveFocus, null, out vTextView);
        IVsUserData userData = vTextView as IVsUserData;
         if (userData == null)
        {
            Console.WriteLine("No text view is currently open");
            return;
        }
        IWpfTextViewHost viewHost;
        object holder;
        Guid guidViewHost = DefGuidList.guidIWpfTextViewHost;
        userData.GetData(ref guidViewHost, out holder);
        viewHost = (IWpfTextViewHost)holder;
        Connector.Execute(viewHost);
    }
    
  6. Atur metode AddAdornmentHandler sebagai handler untuk perintah AddAdornment di konstruktor AddAdornment.

    private AddAdornment(AsyncPackage package, OleMenuCommandService commandService)
    {
        this.package = package ?? throw new ArgumentNullException(nameof(package));
        commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));
    
        var menuCommandID = new CommandID(CommandSet, CommandId);
        var menuItem = new MenuCommand(this.AddAdornmentHandler, menuCommandID);
        commandService.AddCommand(menuItem);
    }
    

Membangun dan menguji kode

  1. Bangun solusi dan mulai penelusuran kesalahan. Instans eksperimental akan muncul.

  2. Buat file teks. Ketik beberapa teks lalu pilih teks tersebut.

  3. Pada menu Alat , klik Panggil Tambahkan Hiasan. Balon harus ditampilkan di sisi kanan jendela teks, dan harus berisi teks yang menyerupai teks berikut.

    YourUserName

    Fourscore...