Compartilhar via


Demonstra Passo a passo: Exibir dicas de ferramentas do QuickInfo

QuickInfo é um recurso do IntelliSense que exibe assinaturas e descrições de método quando um usuário move o ponteiro sobre um nome de método. Você pode implementar recursos baseados em idioma, como QuickInfo, definindo os identificadores para os quais deseja fornecer descrições QuickInfo e, em seguida, criando uma dica de ferramenta na qual exibir o conteúdo. Você pode definir QuickInfo no contexto de um serviço de idioma, ou você pode definir sua própria extensão de nome de arquivo e tipo de conteúdo e exibir o QuickInfo apenas para esse tipo, ou você pode exibir QuickInfo para um tipo de conteúdo existente (como "texto"). Este passo a passo mostra como exibir QuickInfo para o tipo de conteúdo "texto".

O exemplo QuickInfo neste passo a passo exibe as dicas de ferramentas quando um usuário move o ponteiro sobre um nome de método. Esse design requer que você implemente estas quatro interfaces:

  • Interface de origem

  • Interface do provedor de origem

  • Interface do controlador

  • Interface do provedor do controlador

    Os provedores de origem e controlador são partes do componente MEF (Managed Extensibility Framework) e são responsáveis por exportar as classes de origem e controlador e importar serviços e brokers, como o , que cria o buffer de texto de dica de ferramenta e o ITextBufferFactoryServiceIQuickInfoBroker, que dispara a sessão QuickInfo.

    Neste exemplo, a fonte QuickInfo usa uma lista codificada de nomes e descrições de métodos, mas em implementações completas, o serviço de idioma e a documentação de idioma são responsáveis por fornecer esse conteúdo.

Criar um projeto MEF

Para criar um projeto MEF

  1. Crie um projeto C# VSIX. (No Caixa de diálogo Novo Projeto, selecione Visual C# / Extensibilidade e, em seguida, Projeto VSIX.) Nomeie a solução QuickInfoTest.

  2. Adicione um modelo de item Editor Classificador ao projeto. Para obter mais informações, consulte Criar uma extensão com um modelo de item do editor.

  3. Exclua os arquivos de classe existentes.

Implementar a fonte QuickInfo

A fonte QuickInfo é responsável por coletar o conjunto de identificadores e suas descrições e adicionar o conteúdo ao buffer de texto da dica de ferramenta quando um dos identificadores é encontrado. Neste exemplo, os identificadores e suas descrições são apenas adicionados no construtor source.

Para implementar a fonte QuickInfo

  1. Adicione um arquivo de classe e nomeie-o TestQuickInfoSource.

  2. Adicione uma referência a Microsoft.VisualStudio.Language.IntelliSense.

  3. Adicione as seguintes importações.

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.Language.Intellisense;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Text.Operations;
    using Microsoft.VisualStudio.Text.Tagging;
    using Microsoft.VisualStudio.Utilities;
    
  4. Declare uma classe que implementa IQuickInfoSourceo e nomeie-a TestQuickInfoSource.

    internal class TestQuickInfoSource : IQuickInfoSource
    
  5. Adicione campos para o provedor de origem QuickInfo, o buffer de texto e um conjunto de nomes de método e assinaturas de método. Neste exemplo, os nomes de método e assinaturas são inicializados no TestQuickInfoSource construtor.

    private TestQuickInfoSourceProvider m_provider;
    private ITextBuffer m_subjectBuffer;
    private Dictionary<string, string> m_dictionary;
    
  6. Adicione um construtor que defina o provedor de origem QuickInfo e o buffer de texto e preencha o conjunto de nomes de método e assinaturas e descrições de método.

    public TestQuickInfoSource(TestQuickInfoSourceProvider provider, ITextBuffer subjectBuffer)
    {
        m_provider = provider;
        m_subjectBuffer = subjectBuffer;
    
        //these are the method names and their descriptions
        m_dictionary = new Dictionary<string, string>();
        m_dictionary.Add("add", "int add(int firstInt, int secondInt)\nAdds one integer to another.");
        m_dictionary.Add("subtract", "int subtract(int firstInt, int secondInt)\nSubtracts one integer from another.");
        m_dictionary.Add("multiply", "int multiply(int firstInt, int secondInt)\nMultiplies one integer by another.");
        m_dictionary.Add("divide", "int divide(int firstInt, int secondInt)\nDivides one integer by another.");
    }
    
  7. Implementar o método de AugmentQuickInfoSession . Neste exemplo, o método localiza a palavra atual ou a palavra anterior se o cursor estiver no final de uma linha ou de um buffer de texto. Se a palavra for um dos nomes de método, a descrição desse nome de método será adicionada ao conteúdo QuickInfo.

    public void AugmentQuickInfoSession(IQuickInfoSession session, IList<object> qiContent, out ITrackingSpan applicableToSpan)
    {
        // Map the trigger point down to our buffer.
        SnapshotPoint? subjectTriggerPoint = session.GetTriggerPoint(m_subjectBuffer.CurrentSnapshot);
        if (!subjectTriggerPoint.HasValue)
        {
            applicableToSpan = null;
            return;
        }
    
        ITextSnapshot currentSnapshot = subjectTriggerPoint.Value.Snapshot;
        SnapshotSpan querySpan = new SnapshotSpan(subjectTriggerPoint.Value, 0);
    
        //look for occurrences of our QuickInfo words in the span
        ITextStructureNavigator navigator = m_provider.NavigatorService.GetTextStructureNavigator(m_subjectBuffer);
        TextExtent extent = navigator.GetExtentOfWord(subjectTriggerPoint.Value);
        string searchText = extent.Span.GetText();
    
        foreach (string key in m_dictionary.Keys)
        {
            int foundIndex = searchText.IndexOf(key, StringComparison.CurrentCultureIgnoreCase);
            if (foundIndex > -1)
            {
                applicableToSpan = currentSnapshot.CreateTrackingSpan
                    (
                    //querySpan.Start.Add(foundIndex).Position, 9, SpanTrackingMode.EdgeInclusive
                                            extent.Span.Start + foundIndex, key.Length, SpanTrackingMode.EdgeInclusive
                    );
    
                string value;
                m_dictionary.TryGetValue(key, out value);
                if (value != null)
                    qiContent.Add(value);
                else
                    qiContent.Add("");
    
                return;
            }
        }
    
        applicableToSpan = null;
    }
    
  8. Você também deve implementar um método Dispose(), já que IQuickInfoSource implementa IDisposable:

    private bool m_isDisposed;
    public void Dispose()
    {
        if (!m_isDisposed)
        {
            GC.SuppressFinalize(this);
            m_isDisposed = true;
        }
    }
    

Implementar um provedor de origem QuickInfo

O provedor da fonte QuickInfo serve principalmente para exportar a si mesmo como uma parte do componente MEF e instanciar a fonte QuickInfo. Como é uma parte do componente MEF, ele pode importar outras partes do componente MEF.

Para implementar um provedor de origem QuickInfo

  1. Declare um provedor de origem QuickInfo chamado TestQuickInfoSourceProvider que implementa IQuickInfoSourceProvidero e exporte-o com um de "ToolTip QuickInfo Source", um de Before="default" e um NameAttributeOrderAttributeContentTypeAttribute de "text".

    [Export(typeof(IQuickInfoSourceProvider))]
    [Name("ToolTip QuickInfo Source")]
    [Order(Before = "Default Quick Info Presenter")]
    [ContentType("text")]
    internal class TestQuickInfoSourceProvider : IQuickInfoSourceProvider
    
  2. Importe dois serviços ITextStructureNavigatorSelectorService de editor e ITextBufferFactoryService, como propriedades de TestQuickInfoSourceProvider.

    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
    [Import]
    internal ITextBufferFactoryService TextBufferFactoryService { get; set; }
    
  3. Implementar TryCreateQuickInfoSource para retornar um novo TestQuickInfoSourcearquivo .

    public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer)
    {
        return new TestQuickInfoSource(this, textBuffer);
    }
    

Implementar um controlador QuickInfo

Os controladores QuickInfo determinam quando o QuickInfo é exibido. Neste exemplo, QuickInfo aparece quando o ponteiro está sobre uma palavra que corresponde a um dos nomes de método. O controlador QuickInfo implementa um manipulador de eventos de foco do mouse que dispara uma sessão QuickInfo.

Para implementar um controlador QuickInfo

  1. Declare uma classe que implementa IIntellisenseControllero e nomeie-a TestQuickInfoController.

    internal class TestQuickInfoController : IIntellisenseController
    
  2. Adicione campos particulares para o modo de exibição de texto, os buffers de texto representados no modo de exibição de texto, a sessão QuickInfo e o provedor do controlador QuickInfo.

    private ITextView m_textView;
    private IList<ITextBuffer> m_subjectBuffers;
    private TestQuickInfoControllerProvider m_provider;
    private IQuickInfoSession m_session;
    
  3. Adicione um construtor que defina os campos e adicione o manipulador de eventos de foco do mouse.

    internal TestQuickInfoController(ITextView textView, IList<ITextBuffer> subjectBuffers, TestQuickInfoControllerProvider provider)
    {
        m_textView = textView;
        m_subjectBuffers = subjectBuffers;
        m_provider = provider;
    
        m_textView.MouseHover += this.OnTextViewMouseHover;
    }
    
  4. Adicione o manipulador de eventos de foco do mouse que dispara a sessão QuickInfo.

    private void OnTextViewMouseHover(object sender, MouseHoverEventArgs e)
    {
        //find the mouse position by mapping down to the subject buffer
        SnapshotPoint? point = m_textView.BufferGraph.MapDownToFirstMatch
             (new SnapshotPoint(m_textView.TextSnapshot, e.Position),
            PointTrackingMode.Positive,
            snapshot => m_subjectBuffers.Contains(snapshot.TextBuffer),
            PositionAffinity.Predecessor);
    
        if (point != null)
        {
            ITrackingPoint triggerPoint = point.Value.Snapshot.CreateTrackingPoint(point.Value.Position,
            PointTrackingMode.Positive);
    
            if (!m_provider.QuickInfoBroker.IsQuickInfoActive(m_textView))
            {
                m_session = m_provider.QuickInfoBroker.TriggerQuickInfo(m_textView, triggerPoint, true);
            }
        }
    }
    
  5. Implemente o método para que ele remova o manipulador de eventos de foco do mouse quando o Detach controlador for desanexado do modo de exibição de texto.

    public void Detach(ITextView textView)
    {
        if (m_textView == textView)
        {
            m_textView.MouseHover -= this.OnTextViewMouseHover;
            m_textView = null;
        }
    }
    
  6. Implemente o método e o ConnectSubjectBufferDisconnectSubjectBuffer método como métodos vazios para este exemplo.

    public void ConnectSubjectBuffer(ITextBuffer subjectBuffer)
    {
    }
    
    public void DisconnectSubjectBuffer(ITextBuffer subjectBuffer)
    {
    }
    

Implementando o provedor do controlador QuickInfo

O provedor do controlador QuickInfo serve principalmente para exportar-se como uma parte do componente MEF e instanciar o controlador QuickInfo. Como é uma parte do componente MEF, ele pode importar outras partes do componente MEF.

Para implementar o provedor do controlador QuickInfo

  1. Declare uma classe chamada TestQuickInfoControllerProvider que implementa IIntellisenseControllerProvidero e exporte-a com um de "ToolTip QuickInfo Controller" e um NameAttributeContentTypeAttribute de "text":

    [Export(typeof(IIntellisenseControllerProvider))]
    [Name("ToolTip QuickInfo Controller")]
    [ContentType("text")]
    internal class TestQuickInfoControllerProvider : IIntellisenseControllerProvider
    
  2. Importe o IQuickInfoBroker como uma propriedade.

    [Import]
    internal IQuickInfoBroker QuickInfoBroker { get; set; }
    
  3. Implemente o método instanciando o TryCreateIntellisenseController controlador QuickInfo.

    public IIntellisenseController TryCreateIntellisenseController(ITextView textView, IList<ITextBuffer> subjectBuffers)
    {
        return new TestQuickInfoController(textView, subjectBuffers, this);
    }
    

Compilar e testar o código

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

Para criar e testar a solução QuickInfoTest

  1. Compile a solução.

  2. Quando você executa esse projeto no depurador, uma segunda instância do Visual Studio é iniciada.

  3. Crie um arquivo de texto e digite algum texto que inclua as palavras "adicionar" e "subtrair".

  4. Mova o ponteiro sobre uma das ocorrências de "adicionar". A assinatura e a descrição do add método devem ser exibidas.