共用方式為


逐步解說: 建立邊界的圖像 (glyph)

藉由使用自訂的編輯器延伸模組,您可以自訂編輯器邊界的外觀。 這個逐步解說中放置自訂的圖像 (glyph) 的指示區邊界"todo"這個字出現在程式碼註解時。

必要條件

若要完成這個逐步解說中,您必須安裝Visual Studio 2010 SDK。

注意事項注意事項

如需有關 Visual Studio 的 SDK 的詳細資訊,請參閱擴充 Visual Studio 的概觀。若要了解如何下載 Visual Studio 的 SDK,請參閱Visual Studio 擴充性開發人員中心 MSDN 網站上。

建立受管理的擴充性架構 (MEF) 專案

若要建立 MEF 專案

  1. 建立視覺化的 C# 或 Visual Basic 編輯器類別器的專案。 為方案命名 TodoGlyphTest。

  2. VSIX 資訊清單編輯器中開啟 Source.extension.vsixmanifest 檔案。

  3. 請確定Content名包含 MEF 元件的內容類型,並Path設定為 TodoGlyphTest.dll。

  4. 儲存並關閉 Source.extension.vsixmanifest。

  5. 移除現有的類別檔案。

定義圖像 (glyph)

藉由實作定義的圖像 (glyph) IGlyphFactory介面。

若要定義圖像 (glyph)

  1. 將類別檔案,並命名為 TodoGlyphFactory。

  2. 加入下列匯入。

    Imports System.ComponentModel.Composition
    Imports System.Windows
    Imports System.Windows.Shapes
    Imports System.Windows.Media
    Imports System.Windows.Controls
    Imports Microsoft.VisualStudio.Text
    Imports Microsoft.VisualStudio.Text.Editor
    Imports Microsoft.VisualStudio.Text.Formatting
    Imports Microsoft.VisualStudio.Text.Tagging
    Imports Microsoft.VisualStudio.Utilities
    
    using System.ComponentModel.Composition;
    using System.Windows;
    using System.Windows.Shapes;
    using System.Windows.Media;
    using System.Windows.Controls;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Text.Formatting;
    using Microsoft.VisualStudio.Text.Tagging;
    using Microsoft.VisualStudio.Utilities;
    
  3. 新增類別,名為TodoGlyphFactory實作IGlyphFactory

    Friend Class TodoGlyphFactory
        Implements IGlyphFactory
    
    internal class TodoGlyphFactory : IGlyphFactory
    
  4. 新增圖像的維度會定義一個私用欄位。

    Const m_glyphSize As Double = 16.0
    
    const double m_glyphSize = 16.0;
    
  5. 實作GenerateGlyph所定義的圖像 (glyph) 使用者介面 (UI) 項目。 TodoTag在這個逐步解說稍後定義。

    Public Function GenerateGlyph(ByVal line As IWpfTextViewLine, ByVal tag As IGlyphTag) As System.Windows.UIElement Implements IGlyphFactory.GenerateGlyph
        ' Ensure we can draw a glyph for this marker. 
        If tag Is Nothing OrElse Not (TypeOf tag Is TodoTag) Then 
            Return Nothing 
        End If 
    
        Dim ellipse As Ellipse = New Ellipse()
        ellipse.Fill = Brushes.LightBlue
        ellipse.StrokeThickness = 2
        ellipse.Stroke = Brushes.DarkBlue
        ellipse.Height = m_glyphSize
        ellipse.Width = m_glyphSize
    
        Return ellipse
    
    End Function
    
    public UIElement GenerateGlyph(IWpfTextViewLine line, IGlyphTag tag)
    {
        // Ensure we can draw a glyph for this marker. 
        if (tag == null || !(tag is TodoTag))
        {
            return null;
        }
    
        System.Windows.Shapes.Ellipse ellipse = new Ellipse();
        ellipse.Fill = Brushes.LightBlue;
        ellipse.StrokeThickness = 2;
        ellipse.Stroke = Brushes.DarkBlue;
        ellipse.Height = m_glyphSize;
        ellipse.Width = m_glyphSize;
    
        return ellipse;
    }
    
  6. 新增類別,名為TodoGlyphFactoryProvider實作IGlyphFactoryProvider。 匯出類別與NameAttribute的"TodoGlyph", OrderAttribute的後 VsTextMarker ContentTypeAttribute的 「 代碼 」,和TagTypeAttribute的 TodoTag。

    <Export(GetType(IGlyphFactoryProvider)), Name("TodoGlyph"), Order(After:="VsTextMarker"), ContentType("code"), TagType(GetType(TodoTag))>
    Friend NotInheritable Class TodoGlyphFactoryProvider
        Implements IGlyphFactoryProvider
    
    [Export(typeof(IGlyphFactoryProvider))]
    [Name("TodoGlyph")]
    [Order(After = "VsTextMarker")]
    [ContentType("code")]
    [TagType(typeof(TodoTag))]
    internal sealed class TodoGlyphFactoryProvider : IGlyphFactoryProvider
    
  7. 實作GetGlyphFactory具現化的方法TodoGlyphFactory

    Public Function GetGlyphFactory(ByVal view As IWpfTextView, ByVal margin As IWpfTextViewMargin) As IGlyphFactory Implements IGlyphFactoryProvider.GetGlyphFactory
        Return New TodoGlyphFactory()
    End Function
    
    public IGlyphFactory GetGlyphFactory(IWpfTextView view, IWpfTextViewMargin margin)
    {
        return new TodoGlyphFactory();
    }
    

定義 Todo 標記和 Tagger

藉由建立標籤型別和 tagger,並使用 tagger 提供者來匯出定義您在先前步驟中所定義的 UI 項目和指示區邊界之間的關係。

若要定義 todo 標記和 tagger

  1. 將新的類別加入至專案,並命名為 TodoTagger。

  2. 加入下列匯入。

    Imports System
    Imports System.Collections.Generic
    Imports System.ComponentModel.Composition
    Imports Microsoft.VisualStudio.Text
    Imports Microsoft.VisualStudio.Text.Tagging
    Imports Microsoft.VisualStudio.Text.Editor
    Imports Microsoft.VisualStudio.Text.Classification
    Imports Microsoft.VisualStudio.Utilities
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Tagging;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Text.Classification;
    using Microsoft.VisualStudio.Utilities;
    
  3. 新增類別,名為TodoTag

    Friend Class TodoTag
        Implements IGlyphTag
    
        Public Sub New()
            MyBase.New()
        End Sub 
    End Class
    
    internal class TodoTag : IGlyphTag
    
  4. 修改類別,名為TodoTagger實作ITagger型別的TodoTag

    Friend Class TodoTagger
        Implements ITagger(Of TodoTag)
    
    internal class TodoTagger : ITagger<TodoTag>
    
  5. 若要TodoTagger類別中,加入私用欄位IClassifier並尋找 「 類別 」 中的文字跨越。

    Private m_classifier As IClassifier
    Private Const m_searchText As String = "todo"
    
    private IClassifier m_classifier;
    private const string m_searchText = "todo";
    
  6. 將設定類別器的建構函式。

    Friend Sub New(ByVal classifier As IClassifier)
        m_classifier = classifier
    End Sub
    
    internal TodoTagger(IClassifier classifier)
    {
        m_classifier = classifier;
    }
    
  7. 實作GetTags方法中找到所有的分類所跨越其名稱內含 word 「 註解 」 以及其文字的搜尋文字。 每當找到搜尋文字後重新產生新TagSpan型別的TodoTag

    Private Function GetTags(ByVal spans As NormalizedSnapshotSpanCollection) As IEnumerable(Of ITagSpan(Of TodoTag)) Implements ITagger(Of TodoTag).GetTags
        Dim list As List(Of ITagSpan(Of TodoTag))
        list = New List(Of ITagSpan(Of TodoTag))()
    
        For Each span As SnapshotSpan In spans
            'look at each classification span \ 
            For Each classification As ClassificationSpan In m_classifier.GetClassificationSpans(span)
                'if the classification is a comment 
                If classification.ClassificationType.Classification.ToLower().Contains("comment") Then 
                    'if the word "todo" is in the comment, 
                    'create a new TodoTag TagSpan 
                    Dim index As Integer = classification.Span.GetText().ToLower().IndexOf(m_searchText)
                    If index <> -1 Then
                        list.Add(New TagSpan(Of TodoTag)(New SnapshotSpan(classification.Span.Start + index, m_searchText.Length), New TodoTag()))
                    End If 
                End If 
            Next classification
        Next span
    
        Return list
    End Function
    
    IEnumerable<ITagSpan<TodoTag>> ITagger<TodoTag>.GetTags(NormalizedSnapshotSpanCollection spans)
    {
        foreach (SnapshotSpan span in spans)
        {
            //look at each classification span \ 
            foreach (ClassificationSpan classification in m_classifier.GetClassificationSpans(span))
            {
                //if the classification is a comment 
                if (classification.ClassificationType.Classification.ToLower().Contains("comment"))
                {
                    //if the word "todo" is in the comment,
                    //create a new TodoTag TagSpan 
                    int index = classification.Span.GetText().ToLower().IndexOf(m_searchText);
                    if (index != -1)
                    {
                        yield return new TagSpan<TodoTag>(new SnapshotSpan(classification.Span.Start + index, m_searchText.Length), new TodoTag());
                    }
                }
            }
        }
    }
    
  8. 宣告TagsChanged事件。

    Public Event TagsChanged(ByVal sender As Object, ByVal e As Microsoft.VisualStudio.Text.SnapshotSpanEventArgs) Implements Microsoft.VisualStudio.Text.Tagging.ITagger(Of TodoTag).TagsChanged
    
    public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
    
  9. 加入類別,名為TodoTaggerProvider實作ITaggerProvider,並將其與匯出ContentTypeAttribute的 「 代碼 」 與TagTypeAttribute TodoTag。

    <Export(GetType(ITaggerProvider)), ContentType("code"), TagType(GetType(TodoTag))>
    Friend Class TodoTaggerProvider
        Implements ITaggerProvider
    
    [Export(typeof(ITaggerProvider))]
    [ContentType("code")]
    [TagType(typeof(TodoTag))]
    class TodoTaggerProvider : ITaggerProvider
    
  10. 匯入IClassifierAggregatorService

    <Import()>
    Friend AggregatorService As IClassifierAggregatorService
    
    [Import]
    internal IClassifierAggregatorService AggregatorService;
    
  11. 實作CreateTagger``1具現化的方法TodoTagger

    Public Function CreateTagger(Of T As Microsoft.VisualStudio.Text.Tagging.ITag)(ByVal buffer As Microsoft.VisualStudio.Text.ITextBuffer) As Microsoft.VisualStudio.Text.Tagging.ITagger(Of T) Implements Microsoft.VisualStudio.Text.Tagging.ITaggerProvider.CreateTagger
        If buffer Is Nothing Then 
            Throw New ArgumentNullException("buffer")
        End If 
    
        Return TryCast(New TodoTagger(AggregatorService.GetClassifier(buffer)), ITagger(Of T))
    End Function
    
    public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag
    {
        if (buffer == null)
        {
            throw new ArgumentNullException("buffer");
        }
    
        return new TodoTagger(AggregatorService.GetClassifier(buffer)) as ITagger<T>;
    }
    

建置和測試程式碼

若要測試這段程式碼,建置 TodoGlyphTest 方案並執行它實驗性的執行個體中。

若要建置和測試 TodoGlyphTest 的解決方案

  1. 建置方案。

  2. 按 F5 執行專案。 Visual Studio 的第二個執行個體都具現化。

  3. 請確定已顯示 [指示區邊界。 (在工具 ] 功能表中,按一下 選項。 在文字編輯器 頁面上,請確定 指示區邊界已選取。)

  4. 開啟有註解的程式碼檔。 "Todo"這個字加入的註解區段。

  5. 深藍色外框的淡藍色圓圈,應該會出現在左邊的 [程式碼] 視窗中的指示區邊界。