Compartilhar via


Passo a passo: Criando um glifo de margem

Você pode personalizar a aparência das margens do editor usando as extensões de editor personalizado. Este passo a passo coloca um glifo personalizado na margem indicadora sempre que a palavra "todo" é exibida em um comentário do código.

Pré-requisitos

Para concluir este passo a passo, você deve instalar o SDL do Visual Studio 2010.

Dica

Para obter mais informações sobre o SDK de Visual Studio, consulte Ampliando a visão geral de Visual Studio.Para descobrir como fazer o download do SDK do Visual Studio, consulte Visual Studio extensibilidade Developer Center no site do MSDN.

Criando um projeto do Framework (MEF) de extensibilidade gerenciada

Para criar um projeto MEF

  1. Crie um projeto do Visual C# ou Visual Basic Editor classificador. Nomeie a solução TodoGlyphTest.

  2. Abra o arquivo de Source.extension.vsixmanifest no Editor de VSIX de manifesto.

  3. Certifique-se de que o Content título contém um tipo de conteúdo do componente MEF e que o Path for definido como TodoGlyphTest.dll.

  4. Salve e feche o Source.extension.vsixmanifest.

  5. Remova os arquivos de classe existentes.

Definindo o glifo.

Definir um glifo, Implementando o IGlyphFactory interface.

Para definir o glifo.

  1. Adicione um arquivo de classe e denomine- TodoGlyphFactory.

  2. Adicione as importações a seguintes.

    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. Adicionar uma classe chamada TodoGlyphFactory que implementa IGlyphFactory.

    Friend Class TodoGlyphFactory
        Implements IGlyphFactory
    
    internal class TodoGlyphFactory : IGlyphFactory
    
  4. Adicione um campo privado que define as dimensões do glifo.

    Const m_glyphSize As Double = 16.0
    
    const double m_glyphSize = 16.0;
    
  5. Implementar GenerateGlyph , definindo o elemento de interface (UI) do usuário de glifo. TodoTagé definida mais adiante neste passo a passo.

    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. Adicionar uma classe chamada TodoGlyphFactoryProvider que implementa IGlyphFactoryProvider. Exportar essa classe com um NameAttribute de "TodoGlyph", um OrderAttribute de VsTextMarker de após um ContentTypeAttribute de "código" e um TagTypeAttribute de 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. Implementar a GetGlyphFactory método instanciando o 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();
    }
    

Definição de uma marca de Todo e Tagger

Defina a relação entre o elemento de interface do usuário que você definiu nas etapas anteriores e a margem do indicador, criando um tipo de marca e tagger e, em seguida, exportá-la usando um provedor de tagger.

Para definir uma marca de todo e tagger

  1. Adicione uma nova classe ao projeto e denomine- TodoTagger.

  2. Adicione as importações a seguintes.

    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. Adicionar uma classe chamada TodoTag.

    Friend Class TodoTag
        Implements IGlyphTag
    
        Public Sub New()
            MyBase.New()
        End Sub 
    End Class
    
    internal class TodoTag : IGlyphTag
    
  4. Modificar a classe chamada TodoTagger que implementa ITagger do tipo TodoTag.

    Friend Class TodoTagger
        Implements ITagger(Of TodoTag)
    
    internal class TodoTagger : ITagger<TodoTag>
    
  5. Para o TodoTagger classe, adicionar campos privados para um IClassifier e para o texto a ser localizado na classificação abrange.

    Private m_classifier As IClassifier
    Private Const m_searchText As String = "todo"
    
    private IClassifier m_classifier;
    private const string m_searchText = "todo";
    
  6. Adicione um construtor que defina o classificador.

    Friend Sub New(ByVal classifier As IClassifier)
        m_classifier = classifier
    End Sub
    
    internal TodoTagger(IClassifier classifier)
    {
        m_classifier = classifier;
    }
    
  7. Implementar a GetTags método encontrando todas a classificação abrange cujos nomes incluem a palavra "comentário" e cujo texto inclua o texto de pesquisa. Sempre que o texto de pesquisa for encontrado, volta gerar uma nova TagSpan do tipo 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. Declarar um TagsChanged evento.

    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. Adicionar uma classe chamada TodoTaggerProvider que implementa ITaggerProvidere exportá-lo com um ContentTypeAttribute de "código" e um TagTypeAttribute de 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. Importação de IClassifierAggregatorService.

    <Import()>
    Friend AggregatorService As IClassifierAggregatorService
    
    [Import]
    internal IClassifierAggregatorService AggregatorService;
    
  11. Implementar a CreateTagger``1 método instanciando o 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>;
    }
    

Criar e testar o código

Para testar esse código, crie a solução de TodoGlyphTest e execute-o na instância experimental.

Para criar e testar a solução de TodoGlyphTest

  1. Crie a solução.

  2. Execute o projeto pressionando F5. Uma segunda instância do Visual Studio é instanciada.

  3. Certifique-se de que a margem do indicador está mostrando. (Sobre o Ferramentas menu, clique em Opções de. Diante do Editor de texto de página, certifique-se de que margem do indicador está selecionada.)

  4. Abra um arquivo de código tem comentários. Adicione a palavra "todo" para uma das seções de comentário.

  5. Um círculo azul claro que tem um contorno azul escuro deve aparecer na margem indicadora à esquerda da janela de código.