Partager via


Procédure pas - à - pas : Afficher les info-bulles info Express

Info express est une fonctionnalité Intellisense qui affiche les signatures de méthode et des descriptions lorsqu'un utilisateur déplace le pointeur sur un nom de méthode. Vous pouvez implémenter les fonctionnalités basées sur un langage telles que info express en définissant les identificateurs pour lesquels vous souhaitez fournir des descriptions info Express, puis en créant une info-bulle dans laquelle afficher le contenu. Vous pouvez définir info express dans le contexte d'un service de langage, ou vous pouvez définir votre propre extension de nom de fichier et type de contenu et afficher le info express uniquement pour ce type, ou vous pouvez consulter info express pour un type de contenu existant (tel que « texte »). Cette procédure pas - à - pas indique comment afficher info express pour le type de contenu de « texte ».

L'exemple info Express dans cette procédure pas - à - pas affiche les info-bulles lorsqu'un utilisateur déplace le pointeur sur un nom de méthode. Cette conception vous obligent à implémenter ces quatre interfaces :

  • interface source

  • interface de fournisseur de sources

  • interface de contrôleur

  • interface du fournisseur de contrôleur

Les fournisseurs de source et du contrôleur sont les éléments gérées (MEF) managed extensibility framework, et sont chargées d'exporter la source et les classes de contrôleur et d'importer des services et des courtiers tels qu' ITextBufferFactoryService, qui crée la mémoire tampon de texte d'info-bulle, et IQuickInfoBroker, qui déclenche la session info Express.

Dans cet exemple, la source info Express utilise une liste codée en dur de noms de méthodes et de description, mais dans des implémentations intégrales, le service de langage et de la documentation de langage sont chargées de fournir ce contenu.

Composants requis

Pour exécuter cette procédure, vous devez installer Kit de développement logiciel Visual Studio 2010.

Notes

Pour plus d'informations sur le kit de développement Visual Studio, consultez Étendre la présentation de Visual Studio.Pour savoir comment télécharger le kit de développement Visual Studio, consultez Visual Studio Extensibility Developer Center sur le site Web MSDN.

Créer un projet MEF

Pour créer un projet MEF

  1. Créez un projet de classifieur d'éditeur. nommez la solution QuickInfoTest.

  2. Ouvrez le fichier Source.extension.vsixmanifest dans l'éditeur de manifeste VSIX.

  3. Assurez -vous que le titre d' Content contient un type de contenu composant MEF et qu' Path est défini à QuickInfoTest.dll.

  4. Enregistrez et fermez le fichier Source.extension.vsixmanifest.

  5. ajoutez la référence suivante au projet, et CopyLocal défini à false:

    Microsoft.VisualStudio.Language.Intellisense

  6. supprimez les fichiers de classe existants.

Implémenter la source info Express

La source info Express est chargé de collecter l'ensemble d'identificateurs et leurs descriptions et d'ajouter du contenu à la mémoire tampon de texte d'info-bulle lorsque l'un des identificateurs est produit. Dans cet exemple, les identificateurs et leurs descriptions sont simplement ajoutés dans le constructeur de source.

Pour implémenter la source info Express

  1. ajoutez un fichier de classe et nommez-le TestQuickInfoSource.

  2. Ajoutez les importations ci-après.

    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. Déclarez une classe qui implémente IQuickInfoSource, et nommez TestQuickInfoSource.

    Friend Class TestQuickInfoSource
        Implements IQuickInfoSource
    
    internal class TestQuickInfoSource : IQuickInfoSource
    
  4. Ajoutez des champs pour le fournisseur de sources info Express, la mémoire tampon de texte, et un ensemble de noms de méthodes et de signatures de méthode. dans cet exemple, les noms de méthode et les signatures sont initialisés dans le constructeur d' 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. Ajoutez un constructeur qui définit le fournisseur de sources info Express et la mémoire tampon de texte, et exécuter ensemble de noms de méthodes, et signatures de méthode et descriptions.

    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. Implémentez la méthode AugmentQuickInfoSession. Dans cet exemple, la méthode recherche le mot actuel, ou le mot précédent si le curseur figure en fin d'une ligne ou d'une mémoire tampon de texte. Si le mot est l'un des noms de méthode, la description de ce nom de méthode est ajoutée au contenu info Express.

    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. Vous devez également implémenter une méthode de Dispose(), car IQuickInfoSource implémente 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;
        }
    }
    

Implémenter un fournisseur de sources info Express

Le fournisseur de la source info Express sert principalement à s'exporter en tant que composant MEF et à instancier la source info Express. Comme il s'agit d'un composant MEF, il peut importer d'autres éléments MEF.

Pour implémenter un fournisseur de sources info Express

  1. Déclarez un fournisseur de sources info Express nommé TestQuickInfoSourceProvider qui implémente IQuickInfoSourceProvider, et l'exporter avec NameAttribute « source d'Info-bulle info express », OrderAttribute de Before= " défaut », et ContentTypeAttribute « texte ».

    <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. importez deux services d'éditeur, ITextStructureNavigatorSelectorService et ITextBufferFactoryService, comme propriétés d' 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. Implémentez l' TryCreateQuickInfoSource pour retourner nouvel 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);
    }
    

Implémenter un contrôleur info Express

Les contrôleurs info Express déterminer quand info express doit s'afficher. Dans cet exemple, info express s'affiche lorsque le pointeur se trouve sur un mot qui correspond à l'un des noms de méthodes. Le contrôleur info Express implémente un gestionnaire d'événement de pointage de la souris qui déclenche une session info Express.

Pour implémenter un contrôleur info Express

  1. Déclarez une classe qui implémente IIntellisenseController, et nommez TestQuickInfoController.

    Friend Class TestQuickInfoController
        Implements IIntellisenseController
    
    internal class TestQuickInfoController : IIntellisenseController
    
  2. Ajoutez des champs privés pour l'affichage de texte, les mémoires tampons de texte représentées dans l'affichage de texte, la session info Express, et le fournisseur de contrôleur info Express.

    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. Ajoutez un constructeur qui définit les champs et ajoute le gestionnaire d'événement de pointage de la souris.

    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. Ajoutez le gestionnaire d'événement de pointage de la souris qui déclenche la session info Express.

    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. Implémentez la méthode d' Detach afin qu'elle supprime le gestionnaire d'événement de pointage de la souris lorsque le contrôleur est détaché de l'affichage de texte.

    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. Implémentez la méthode d' ConnectSubjectBuffer et la méthode d' DisconnectSubjectBuffer en tant que méthodes vides pour cet exemple.

    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)
    {
    }
    

Implémenter le fournisseur de contrôleur info Express

Le fournisseur du contrôleur info Express sert principalement à s'exporter en tant que composant MEF et à instancier le contrôleur info Express. Comme il s'agit d'un composant MEF, il peut importer d'autres éléments MEF.

Pour implémenter le fournisseur de contrôleur info Express

  1. Déclarez une classe nommée TestQuickInfoControllerProvider qui implémente IIntellisenseControllerProvider, et exportez-la avec NameAttribute « controller d'Info-bulle info express » et ContentTypeAttribute « texte » :

    <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. Importez IQuickInfoBroker en tant que propriété.

    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. Implémentez la méthode d' TryCreateIntellisenseController en instanciant le contrôleur info Express.

    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);
    }
    

Génération et test de code

Pour tester ce code, générez la solution de QuickInfoTest et exécutez -la dans l'instance expérimentale.

Pour générer et tester la solution de QuickInfoTest

  1. Générez la solution.

  2. Lorsque vous exécutez ce projet dans le débogueur, une deuxième instance de Visual Studio est instanciée.

  3. Créez un fichier texte et tapez du texte qui inclut les mots « add » et « soustrayez ».

  4. Déplacez le pointeur sur l'une des occurrences de « add ». La signature et la description de la méthode d' add doivent être affichées.

Voir aussi

Tâches

Procédure pas - à - pas : lier un type de contenu à une extension de nom de fichier