Compartir a través de


tutorial: Mostrar información sobre herramientas de QuickInfo

QuickInfo es una característica de IntelliSense que muestra las signaturas y descripciones de método cuando el usuario mueve el puntero sobre un nombre de método. Puede implementar características basadas en el lenguaje como QuickInfo definiendo los identificadores para los que desea proporcionar descripciones de QuickInfo, y después crear una información sobre herramientas en la que mostrar contenido. Puede definir QuickInfo en el contexto de un servicio de, o puede definir dispone de la extensión de nombre de archivo y el tipo de contenido y mostrar el QuickInfo sólo para ese tipo, o puede mostrar QuickInfo para un tipo de contenido existente (como “text”). Este tutorial muestra cómo mostrar QuickInfo para el tipo de contenido “text”.

El ejemplo de QuickInfo en este tutorial se muestra la información sobre herramientas cuando el usuario mueve el puntero sobre un nombre de método. Este diseño requiere implementar estas cuatro interfaces:

  • interfaz de origen

  • interfaz del proveedor de origen

  • interfaz de controlador

  • interfaz de proveedor de controlador

Los proveedores de origen y controlador son elementos (MEF) de managed extensibility framework, y son responsables de exportar el origen y las clases de controlador e importar servicios y agentes como ITextBufferFactoryService, que crea el búfer de texto de información sobre herramientas, y IQuickInfoBroker, que activa la sesión de QuickInfo.

En este ejemplo, el origen de QuickInfo utiliza una lista especificada de nombres y descripciones de método, pero en implementaciones completas, el servicio de lenguaje y documentación de lenguaje son responsables de proporcionar al contenido.

Requisitos previos

Para completar este tutorial, debe instalar Visual Studio 2010 SDK.

NotaNota

Para obtener más información sobre el SDK de Visual Studio, vea Información general de Visual Studio que extiende.Para averiguar cómo descargar el SDK de Visual Studio, vea Centro para desarrolladores de extensibilidad de Visual Studio en el sitio web de MSDN.

Crear un proyecto MEF

Para crear un proyecto de MEF

  1. Cree un proyecto del clasificador del editor. Llame a la solución QuickInfoTest.

  2. Abra el archivo Source.extension.vsixmanifest del editor de Manifiesto VSIX.

  3. Asegúrese de que la dirección de Content contiene un tipo de contenido componente MEF y que Path está establecido en QuickInfoTest.dll.

  4. Guarde y cierre Source.extension.vsixmanifest.

  5. Agregue la siguiente referencia al proyecto y, a CopyLocal establecido en false:

    Microsoft.VisualStudio.Language.Intellisense

  6. elimine los archivos existentes de la clase.

implementar el origen de QuickInfo

El origen de QuickInfo es responsable de obtener el conjunto de identificadores y sus descripciones y agregar contenido al búfer de texto de información sobre herramientas a uno de los identificadores se encuentra. En este ejemplo, los identificadores y sus descripciones simplemente se agregan en el constructor de origen.

para implementar el origen de QuickInfo

  1. Agregue un archivo de clase y denomínelo TestQuickInfoSource.

  2. Agregue imports.

    Imports System
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Text
    Imports System.Collections.ObjectModel
    Imports System.ComponentModel.Composition
    Imports Microsoft.VisualStudio.Language.Intellisense
    Imports Microsoft.VisualStudio.Text
    Imports Microsoft.VisualStudio.Text.Editor
    Imports Microsoft.VisualStudio.Text.Operations
    Imports Microsoft.VisualStudio.Text.Tagging
    Imports Microsoft.VisualStudio.Utilities
    
    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;
    
  3. Declare una clase que implemente IQuickInfoSource, y denomínela TestQuickInfoSource.

    Friend Class TestQuickInfoSource
        Implements IQuickInfoSource
    
    internal class TestQuickInfoSource : IQuickInfoSource
    
  4. Agregue campos para el proveedor de origen de QuickInfo, el búfer de texto, y un conjunto de nombres de método y de firmas de método. En este ejemplo, los nombres y las firmas de método se inicializan en el constructor de TestQuickInfoSource .

    Private m_provider As TestQuickInfoSourceProvider
    Private m_subjectBuffer As ITextBuffer
    Private m_dictionary As Dictionary(Of String, String)
    
    private TestQuickInfoSourceProvider m_provider;
    private ITextBuffer m_subjectBuffer;
    private Dictionary<string, string> m_dictionary;
    
  5. Agregue un constructor que establezca el proveedor de origen de QuickInfo y el búfer de texto, y llena el conjunto de nombres del método, y firmas y descripciones del método.

    Public Sub New(ByVal provider As TestQuickInfoSourceProvider, ByVal subjectBuffer As ITextBuffer)
        m_provider = provider
        m_subjectBuffer = subjectBuffer
    
        'these are the method names and their descriptions
        m_dictionary = New Dictionary(Of String, String)()
        m_dictionary.Add("add", "int add(int firstInt, int secondInt)" & vbLf & "Adds one integer to another.")
        m_dictionary.Add("subtract", "int subtract(int firstInt, int secondInt)" & vbLf & "Subtracts one integer from another.")
        m_dictionary.Add("multiply", "int multiply(int firstInt, int secondInt)" & vbLf & "Multiplies one integer by another.")
        m_dictionary.Add("divide", "int divide(int firstInt, int secondInt)" & vbLf & "Divides one integer by another.")
    End Sub
    
    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.");
    }
    
  6. Implemente el método AugmentQuickInfoSession. En este ejemplo, el método busca la palabra actual, o la palabra anterior si el cursor está en el final de una línea o un búfer de texto. Si la palabra es uno de los nombres de método, la descripción para ese nombre de método se agrega al contenido de QuickInfo.

    Public Sub AugmentQuickInfoSession(ByVal session As IQuickInfoSession, ByVal qiContent As IList(Of Object), ByRef applicableToSpan As ITrackingSpan) Implements IQuickInfoSource.AugmentQuickInfoSession
        ' Map the trigger point down to our buffer. 
        Dim subjectTriggerPoint As System.Nullable(Of SnapshotPoint) = session.GetTriggerPoint(m_subjectBuffer.CurrentSnapshot)
        If Not subjectTriggerPoint.HasValue Then
            applicableToSpan = Nothing 
            Exit Sub 
        End If 
    
        Dim currentSnapshot As ITextSnapshot = subjectTriggerPoint.Value.Snapshot
        Dim querySpan As New SnapshotSpan(subjectTriggerPoint.Value, 0)
    
        'look for occurrences of our QuickInfo words in the span 
        Dim navigator As ITextStructureNavigator = m_provider.NavigatorService.GetTextStructureNavigator(m_subjectBuffer)
        Dim extent As TextExtent = navigator.GetExtentOfWord(subjectTriggerPoint.Value)
        Dim searchText As String = extent.Span.GetText()
    
        For Each key As String In m_dictionary.Keys
            Dim foundIndex As Integer = searchText.IndexOf(key, StringComparison.CurrentCultureIgnoreCase)
            If foundIndex > -1 Then
                applicableToSpan = currentSnapshot.CreateTrackingSpan(querySpan.Start.Add(foundIndex).Position, 9, SpanTrackingMode.EdgeInclusive)
    
                Dim value As String = ""
                m_dictionary.TryGetValue(key, value)
                If value IsNot Nothing Then
                    qiContent.Add(value)
                Else
                    qiContent.Add("")
                End If 
    
                Exit Sub 
            End If 
        Next
    
        applicableToSpan = Nothing 
    End Sub
    
    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
                    );
    
                string value;
                m_dictionary.TryGetValue(key, out value);
                if (value != null)
                    qiContent.Add(value);
                else
                    qiContent.Add("");
    
                return;
            }
        }
    
        applicableToSpan = null;
    }
    
  7. También debe implementar un método de Dispose(), ya que IQuickInfoSource implementa IDisposable:

    Private m_isDisposed As Boolean 
    Public Sub Dispose() Implements IDisposable.Dispose
        If Not m_isDisposed Then
            GC.SuppressFinalize(Me)
            m_isDisposed = True 
        End If 
    End Sub
    
    private bool m_isDisposed;
    public void Dispose()
    {
        if (!m_isDisposed)
        {
            GC.SuppressFinalize(this);
            m_isDisposed = true;
        }
    }
    

implementar un proveedor de origen de QuickInfo

El proveedor de origen de QuickInfo sirve principalmente exportarse como parte MEF y crear instancias del origen de QuickInfo. Porque es una parte MEF, puede importar otros elementos MEF.

para implementar un proveedor de origen de QuickInfo

  1. Declare un proveedor de origen de QuickInfo denominado TestQuickInfoSourceProvider que implemente IQuickInfoSourceProvider, y exportelo con NameAttribute “del origen de QuickInfo de información sobre herramientas”, OrderAttribute de Before= " predeterminado”, y ContentTypeAttribute “text”.

    <Export(GetType(IQuickInfoSourceProvider))> _
    <Name("ToolTip QuickInfo Source")> _
    <Order(Before:=" Default Quick Info Presenter")> _
    <ContentType("text")> _
    Friend Class TestQuickInfoSourceProvider
        Implements IQuickInfoSourceProvider
    
    [Export(typeof(IQuickInfoSourceProvider))]
    [Name("ToolTip QuickInfo Source")]
    [Order(Before = "Default Quick Info Presenter")]
    [ContentType("text")]
    internal class TestQuickInfoSourceProvider : IQuickInfoSourceProvider
    
  2. Cantidad dos servicios del editor, ITextStructureNavigatorSelectorService y ITextBufferFactoryService, como propiedades de TestQuickInfoSourceProvider.

    Private _NavigatorService As ITextStructureNavigatorSelectorService
    <Import()> _
    Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
        Get 
            Return _NavigatorService
        End Get 
        Set(ByVal value As ITextStructureNavigatorSelectorService)
            _NavigatorService = value
        End Set 
    End Property 
    
    Private _TextBufferFactoryService As ITextBufferFactoryService
    <Import()> _
    Friend Property TextBufferFactoryService() As ITextBufferFactoryService
        Get 
            Return _TextBufferFactoryService
        End Get 
        Set(ByVal value As ITextBufferFactoryService)
            _TextBufferFactoryService = value
        End Set 
    End Property
    
    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
    [Import]
    internal ITextBufferFactoryService TextBufferFactoryService { get; set; }
    
  3. TryCreateQuickInfoSource de implementan para devolver nuevo TestQuickInfoSource.

    Public Function TryCreateQuickInfoSource(ByVal textBuffer As ITextBuffer) As IQuickInfoSource Implements IQuickInfoSourceProvider.TryCreateQuickInfoSource
        Return New TestQuickInfoSource(Me, textBuffer)
    End Function
    
    public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer)
    {
        return new TestQuickInfoSource(this, textBuffer);
    }
    

implementar un controlador de QuickInfo

Los controladores de QuickInfo determinan cuándo QuickInfo debe mostrar. En este ejemplo, se muestra QuickInfo cuando el puntero está sobre una palabra que corresponde a uno de los nombres de método. El controlador de QuickInfo implementa un controlador de eventos al desplazar el puntero del mouse que se activa una sesión de QuickInfo.

para implementar un controlador de QuickInfo

  1. Declare una clase que implemente IIntellisenseController, y denomínela TestQuickInfoController.

    Friend Class TestQuickInfoController
        Implements IIntellisenseController
    
    internal class TestQuickInfoController : IIntellisenseController
    
  2. Agregue campos privados para la vista de texto, los búferes de texto representados en la vista de texto, la sesión de QuickInfo, y el proveedor de controlador de QuickInfo.

    Private m_textView As ITextView
    Private m_subjectBuffers As IList(Of ITextBuffer)
    Private m_provider As TestQuickInfoControllerProvider
    Private m_session As IQuickInfoSession
    
    private ITextView m_textView;
    private IList<ITextBuffer> m_subjectBuffers;
    private TestQuickInfoControllerProvider m_provider;
    private IQuickInfoSession m_session;
    
  3. Agregue un constructor que establezca los campos y agregue el controlador de eventos de desplazamiento.

    Friend Sub New(ByVal textView As ITextView, ByVal subjectBuffers As IList(Of ITextBuffer), ByVal provider As TestQuickInfoControllerProvider)
        m_textView = textView
        m_subjectBuffers = subjectBuffers
        m_provider = provider
    
        AddHandler m_textView.MouseHover, AddressOf Me.OnTextViewMouseHover
    End Sub
    
    internal TestQuickInfoController(ITextView textView, IList<ITextBuffer> subjectBuffers, TestQuickInfoControllerProvider provider)
    {
        m_textView = textView;
        m_subjectBuffers = subjectBuffers;
        m_provider = provider;
    
        m_textView.MouseHover += this.OnTextViewMouseHover;
    }
    
  4. Agregue el controlador de eventos al desplazar el puntero del mouse que desencadena la sesión de QuickInfo.

    Private Sub OnTextViewMouseHover(ByVal sender As Object, ByVal e As MouseHoverEventArgs)
        'find the mouse position by mapping down to the subject buffer 
        Dim point As System.Nullable(Of SnapshotPoint) = m_textView.BufferGraph.MapDownToFirstMatch(New SnapshotPoint(m_textView.TextSnapshot, e.Position), PointTrackingMode.Positive, Function(snapshot) m_subjectBuffers.Contains(snapshot.TextBuffer), PositionAffinity.Predecessor)
    
        If point IsNot Nothing Then 
            Dim triggerPoint As ITrackingPoint = point.Value.Snapshot.CreateTrackingPoint(point.Value.Position, PointTrackingMode.Positive)
    
            If Not m_provider.QuickInfoBroker.IsQuickInfoActive(m_textView) Then
                m_session = m_provider.QuickInfoBroker.TriggerQuickInfo(m_textView, triggerPoint, True)
            End If 
        End If 
    End Sub
    
    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 el método de Detach para quitar el controlador de eventos al desplazar el puntero del mouse cuando el controlador está asociado a la vista de texto.

    Public Sub Detach(ByVal textView As ITextView) Implements IIntellisenseController.Detach
        If m_textView Is textView Then 
            AddHandler m_textView.MouseHover, AddressOf Me.OnTextViewMouseHover
            m_textView = Nothing 
        End If 
    End Sub
    
    public void Detach(ITextView textView)
    {
        if (m_textView == textView)
        {
            m_textView.MouseHover -= this.OnTextViewMouseHover;
            m_textView = null;
        }
    }
    
  6. Implemente el método de ConnectSubjectBuffer y el método de DisconnectSubjectBuffer como métodos vacíos para este ejemplo.

    Public Sub ConnectSubjectBuffer(ByVal subjectBuffer As ITextBuffer) Implements IIntellisenseController.ConnectSubjectBuffer
    
    End Sub 
    
    Public Sub DisconnectSubjectBuffer(ByVal subjectBuffer As ITextBuffer) Implements IIntellisenseController.DisconnectSubjectBuffer
    
    End Sub
    
    public void ConnectSubjectBuffer(ITextBuffer subjectBuffer)
    {
    }
    
    public void DisconnectSubjectBuffer(ITextBuffer subjectBuffer)
    {
    }
    

Implementar el proveedor de controlador de QuickInfo

El proveedor de controlador de QuickInfo sirve principalmente exportarse como parte MEF y crear instancias del controlador de QuickInfo. Porque es una parte MEF, puede importar otros elementos MEF.

Para implementar el proveedor de controlador de QuickInfo

  1. Declare una clase denominada TestQuickInfoControllerProvider que implemente IIntellisenseControllerProvider, y exportela con NameAttribute “de controlador de QuickInfo de información sobre herramientas” y ContentTypeAttribute “text”:

    <Export(GetType(IIntellisenseControllerProvider))> _
    <Name("ToolTip QuickInfo Controller")> _
    <ContentType("text")> _
    Friend Class TestQuickInfoControllerProvider
        Implements IIntellisenseControllerProvider
    
    [Export(typeof(IIntellisenseControllerProvider))]
    [Name("ToolTip QuickInfo Controller")]
    [ContentType("text")]
    internal class TestQuickInfoControllerProvider : IIntellisenseControllerProvider
    
  2. Cantidad IQuickInfoBroker como propiedad.

    Private _QuickInfoBroker As IQuickInfoBroker
    <Import()> _
    Friend Property QuickInfoBroker() As IQuickInfoBroker
        Get 
            Return _QuickInfoBroker
        End Get 
        Set(ByVal value As IQuickInfoBroker)
            _QuickInfoBroker = value
        End Set 
    End Property
    
    [Import]
    internal IQuickInfoBroker QuickInfoBroker { get; set; }
    
  3. Implemente el método de TryCreateIntellisenseController creando instancias del controlador de QuickInfo.

    Public Function TryCreateIntellisenseController(ByVal textView As ITextView, ByVal subjectBuffers As IList(Of ITextBuffer)) As IIntellisenseController Implements IIntellisenseControllerProvider.TryCreateIntellisenseController
        Return New TestQuickInfoController(textView, subjectBuffers, Me)
    End Function
    
    public IIntellisenseController TryCreateIntellisenseController(ITextView textView, IList<ITextBuffer> subjectBuffers)
    {
        return new TestQuickInfoController(textView, subjectBuffers, this);
    }
    

Compilar y probar el código

Para probar este código, compile la solución de QuickInfoTest y ejecútela en la instancia experimental.

para compilar y probar la solución de QuickInfoTest

  1. Compile la solución.

  2. Al ejecutar este proyecto en el depurador, una segunda instancia de Visual Studio se crea instancias.

  3. Cree un archivo de texto y escriba algún texto que incluya las palabras “agregar” y “restar”.

  4. Mueva el puntero sobre una de las apariciones de “add”. La firma y la descripción del método de add deben mostrar.

Vea también

Tareas

tutorial: vincular un tipo de contenido a una extensión de nombre de archivo