Partager via


Procédure pas - à - pas : Afficher l'assistance de signature

L'assistance de signature (également appelés informations sur les paramètres) affiche la signature d'une méthode dans une info-bulle lorsqu'un utilisateur le caractère de début de la liste de paramètres (en général une parenthèse ouvrante). Comme un paramètre et un séparateur de paramètre (en général une virgule) sont typés, l'info-bulle est mise à jour pour afficher le paramètre suivant en gras. Vous pouvez définir l'assistance de signature dans le contexte d'un service de langage, ou vous pouvez définir votre propre utilisation d'extension de nom de fichier et de signature de type de contenu et d'affichage uniquement pour ce type, ou vous pouvez consulter l'assistance de signature pour un type de contenu existant (par exemple, « texte »). Cette procédure pas - à - pas montre comment afficher l'assistance de signature pour le type de contenu de « texte ».

L'assistance de signature est généralement levée en tapant un caractère spécifique, par exemple, « (" (parenthèse ouvrante), et fait disparaître en tapant un autre caractère, par exemple, ") » (parenthèse fermante). Les fonctionnalités Intellisense qui sont déclenchées en tapant un caractère peuvent être implémentées à l'aide d'un gestionnaire de commandes pour les séquences de touches (l'interface d' IOleCommandTarget ) et un fournisseur de gestionnaire qui implémente l'interface d' IVsTextViewCreationListener . Pour créer la signature la source, qui est la liste des signatures qui participent à l'assistance de signature, implémentent l'interface d' ISignatureHelpSource et un fournisseur de sources qui implémente l'interface d' ISignatureHelpSourceProvider . Les fournisseurs 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, par exemple, ITextStructureNavigatorSelectorService, qui vous permet de naviguer dans la mémoire tampon de texte, et ISignatureHelpBroker, qui déclenche la session d'assistance de signature.

Cette procédure pas - à - pas montre comment implémenter l'assistance de signature pour un jeu codé en dur des identificateurs. Dans les implémentations intégrales, le langage est chargé 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 SignatureHelpTest.

  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 à SignatureHelpTest.dll.

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

  5. ajoutez les références suivantes au projet, et CopyLocal défini à false:

    Microsoft.VisualStudio.Editor

    Microsoft.VisualStudio.Language.Intellisense

    Microsoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell

    Microsoft.VisualStudio.TextManager.Interop

  6. supprimez les fichiers de classe existants.

Implémenter les signatures de l'aide et des paramètres de signature

La source d'assistance de signature est basé sur les signatures qui implémentent ISignature, qui contient des paramètres qui implémentent IParameter. Dans une implémentation complète, ces informations sont obtenues à partir de la documentation du langage, mais dans cet exemple, les signatures sont codées en dur.

Pour implémenter la signature les signatures et les paramètres

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

  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 System.Runtime.InteropServices
    Imports Microsoft.VisualStudio.Language.Intellisense
    Imports Microsoft.VisualStudio.Text
    Imports Microsoft.VisualStudio.Text.Editor
    Imports Microsoft.VisualStudio.Utilities
    Imports Microsoft.VisualStudio.Editor
    Imports Microsoft.VisualStudio.Text.Operations
    Imports Microsoft.VisualStudio
    Imports Microsoft.VisualStudio.TextManager.Interop
    Imports Microsoft.VisualStudio.OLE.Interop
    
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel.Composition;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.Language.Intellisense;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Utilities;
    using Microsoft.VisualStudio.Editor;
    using Microsoft.VisualStudio.Text.Operations;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.TextManager.Interop;
    using Microsoft.VisualStudio.OLE.Interop;
    
  3. ajoutez une classe nommée TestParameter qui implémente IParameter.

    Friend Class TestParameter
        Implements IParameter
    
    internal class TestParameter : IParameter
    
  4. ajoutez un constructeur qui définit toutes les propriétés.

    Public Sub New(ByVal documentation As String, ByVal locus As Span, ByVal name As String, ByVal signature As ISignature)
        Me.privateDocumentation = documentation
        Me.privateLocus = locus
        Me.privateName = name
        Me.privateSignature = signature
    End Sub
    
    public TestParameter(string documentation, Span locus, string name, ISignature signature)
    {
        Documentation = documentation;
        Locus = locus;
        Name = name;
        Signature = signature;
    }
    
  5. Ajoutez des propriétés d' IParameter.

    Private privateDocumentation As String 
    ReadOnly Property Documentation() As String Implements IParameter.Documentation
        Get 
            Return privateDocumentation
        End Get 
    
    End Property 
    Private privateLocus As Span
    ReadOnly Property Locus() As Span Implements IParameter.Locus
        Get 
            Return privateLocus
        End Get 
    End Property 
    Private privateName As String 
    ReadOnly Property Name() As String Implements IParameter.Name
        Get 
            Return privateName
        End Get 
    End Property 
    Private privateSignature As ISignature
    ReadOnly Property Signature() As ISignature Implements IParameter.Signature
        Get 
            Return privateSignature
        End Get 
    End Property 
    Private privatePrettyPrintedLocus As Span
    ReadOnly Property PrettyPrintedLocus() As Span Implements IParameter.PrettyPrintedLocus
        Get 
            Return privatePrettyPrintedLocus
        End Get 
    End Property
    
    public string Documentation { get; private set; }
    public Span Locus { get; private set; }
    public string Name { get; private set; }
    public ISignature Signature { get; private set; }
    public Span PrettyPrintedLocus { get; private set; }
    
  6. ajoutez une classe nommée TestSignature qui implémente ISignature.

    Friend Class TestSignature
        Implements ISignature
    
    internal class TestSignature : ISignature
    
  7. Ajoutez des champs privés.

    Private m_subjectBuffer As ITextBuffer
    Private m_currentParameter As IParameter
    Private m_content As String 
    Private m_documentation As String 
    Friend m_applicableToSpan As ITrackingSpan
    Friend m_parameters As ReadOnlyCollection(Of IParameter)
    Private m_printContent As String
    
    private ITextBuffer m_subjectBuffer;
    private IParameter m_currentParameter;
    private string m_content;
    private string m_documentation;
    private ITrackingSpan m_applicableToSpan;
    private ReadOnlyCollection<IParameter> m_parameters;
    private string m_printContent;
    
  8. ajoutez un constructeur qui définit les champs et abonne à Changed l'événement.

    Friend Sub New(ByVal subjectBuffer As ITextBuffer, ByVal content As String, ByVal doc As String, ByVal parameters As ReadOnlyCollection(Of IParameter))
        m_subjectBuffer = subjectBuffer
        m_content = content
        m_documentation = doc
        m_parameters = parameters
        AddHandler m_subjectBuffer.Changed, AddressOf OnSubjectBufferChanged
    End Sub
    
    internal TestSignature(ITextBuffer subjectBuffer, string content, string doc, ReadOnlyCollection<IParameter> parameters)
    {
        m_subjectBuffer = subjectBuffer;
        m_content = content;
        m_documentation = doc;
        m_parameters = parameters;
        m_subjectBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(OnSubjectBufferChanged);
    }
    
  9. déclarez un événement d' CurrentParameterChanged . Cet événement est déclenché lorsque l'utilisateur exécute l'un des paramètres dans la signature.

    Public Event CurrentParameterChanged As EventHandler(Of CurrentParameterChangedEventArgs) Implements ISignature.CurrentParameterChanged
    
    public event EventHandler<CurrentParameterChangedEventArgs> CurrentParameterChanged;
    
  10. Implémentez la propriété d' CurrentParameter afin qu'elle déclenche l'événement d' CurrentParameterChanged lorsque la valeur de propriété est modifiée.

    ReadOnly Property CurrentParameter() As IParameter Implements ISignature.CurrentParameter
        Get 
            Return m_currentParameter
        End Get 
    End Property
    
    public IParameter CurrentParameter
    {
        get { return m_currentParameter; }
        internal set
        {
            if (m_currentParameter != value)
            {
                IParameter prevCurrentParameter = m_currentParameter;
                m_currentParameter = value;
                this.RaiseCurrentParameterChanged(prevCurrentParameter, m_currentParameter);
            }
        }
    }
    
  11. ajoutez une méthode qui déclenche l'événement d' CurrentParameterChanged .

    Private Sub RaiseCurrentParameterChanged(ByVal prevCurrentParameter As IParameter, ByVal newCurrentParameter As IParameter)
        Dim tempHandler As EventHandler(Of CurrentParameterChangedEventArgs) = Me.CurrentParameterChangedEvent
        If tempHandler IsNot Nothing Then
            tempHandler(Me, New CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter))
        End If 
    End Sub
    
    private void RaiseCurrentParameterChanged(IParameter prevCurrentParameter, IParameter newCurrentParameter)
    {
        EventHandler<CurrentParameterChangedEventArgs> tempHandler = this.CurrentParameterChanged;
        if (tempHandler != null)
        {
            tempHandler(this, new CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter));
        }
    }
    
  12. ajoutez une méthode qui calcule le paramètre actuel en comparant le nombre de virgules dans ApplicableToSpan au nombre de virgules dans la signature.

    Friend Sub ComputeCurrentParameter()
        If Parameters.Count = 0 Then 
            Me.m_currentParameter = Nothing 
            Return 
        End If 
    
        'the number of commas in the string is the index of the current parameter 
        Dim sigText As String = ApplicableToSpan.GetText(m_subjectBuffer.CurrentSnapshot)
    
        Dim currentIndex As Integer = 0
        Dim commaCount As Integer = 0
        Do While currentIndex < sigText.Length
            Dim commaIndex As Integer = sigText.IndexOf(","c, currentIndex)
            If commaIndex = -1 Then 
                Exit Do 
            End If
            commaCount += 1
            currentIndex = commaIndex + 1
        Loop 
    
        If commaCount < Parameters.Count Then 
            Me.m_currentParameter = Parameters(commaCount)
        Else 
            'too many commas, so use the last parameter as the current one. 
            Me.m_currentParameter = Parameters(Parameters.Count - 1)
        End If 
    End Sub
    
    internal void ComputeCurrentParameter()
    {
        if (Parameters.Count == 0)
        {
            this.CurrentParameter = null;
            return;
        }
    
        //the number of commas in the string is the index of the current parameter 
        string sigText = ApplicableToSpan.GetText(m_subjectBuffer.CurrentSnapshot);
    
        int currentIndex = 0;
        int commaCount = 0;
        while (currentIndex < sigText.Length)
        {
            int commaIndex = sigText.IndexOf(',', currentIndex);
            if (commaIndex == -1)
            {
                break;
            }
            commaCount++;
            currentIndex = commaIndex + 1;
        }
    
        if (commaCount < Parameters.Count)
        {
            this.CurrentParameter = Parameters[commaCount];
        }
        else
        {
            //too many commas, so use the last parameter as the current one. 
            this.CurrentParameter = Parameters[Parameters.Count - 1];
        }
    }
    
  13. ajoutez un gestionnaire d'événements pour l'événement d' Changed qui appelle la méthode d' ComputeCurrentParameter() .

    Friend Sub OnSubjectBufferChanged(ByVal sender As Object, ByVal e As TextContentChangedEventArgs)
        Me.ComputeCurrentParameter()
    End Sub
    
    internal void OnSubjectBufferChanged(object sender, TextContentChangedEventArgs e)
    {
        this.ComputeCurrentParameter();
    }
    
  14. Implémentez la propriété ApplicableToSpan. Cette propriété contient ITrackingSpan correspondant à l'étendue de texte de la mémoire tampon à laquelle la signature applique.

    ReadOnly Property ApplicableToSpan() As ITrackingSpan Implements ISignature.ApplicableToSpan
        Get 
            Return (m_applicableToSpan)
        End Get 
    End Property
    
    public ITrackingSpan ApplicableToSpan
    {
        get { return (m_applicableToSpan); }
        internal set { m_applicableToSpan = value; }
    }
    
  15. implémentez les autres paramètres.

    ReadOnly Property Content() As String Implements ISignature.Content
        Get 
            Return (m_content)
        End Get 
    End Property 
    
    ReadOnly Property Documentation() As String Implements ISignature.Documentation
        Get 
            Return (m_documentation)
        End Get 
    End Property 
    
    ReadOnly Property Parameters() As ReadOnlyCollection(Of IParameter) Implements ISignature.Parameters
        Get 
            Return (m_parameters)
        End Get 
    End Property 
    
    ReadOnly Property PrettyPrintedContent() As String Implements ISignature.PrettyPrintedContent
        Get 
            Return (m_printContent)
        End Get 
    End Property
    
    public string Content
    {
        get { return (m_content); }
        internal set { m_content = value; }
    }
    
    public string Documentation
    {
        get { return (m_documentation); }
        internal set { m_documentation = value; }
    }
    
    public ReadOnlyCollection<IParameter> Parameters
    {
        get { return (m_parameters); }
        internal set { m_parameters = value; }
    }
    
    public string PrettyPrintedContent
    {
        get { return (m_printContent); }
        internal set { m_printContent = value; }
    }
    

Implémenter la source d'assistance de signature

La source d'assistance de signature est le jeu de signatures pour lesquelles vous fournissez des informations.

Pour implémenter la source d'assistance de signature

  1. ajoutez une classe nommée TestSignatureHelpSource qui implémente ISignatureHelpSource.

    Friend Class TestSignatureHelpSource
        Implements ISignatureHelpSource
    
    internal class TestSignatureHelpSource : ISignatureHelpSource
    
  2. ajoutez une référence à la mémoire tampon de texte.

    Private m_textBuffer As ITextBuffer
    
    private ITextBuffer m_textBuffer;
    
  3. Ajoutez un constructeur qui définit la mémoire tampon de texte et le fournisseur de sources d'assistance de signature.

    Public Sub New(ByVal textBuffer As ITextBuffer)
        m_textBuffer = textBuffer
    End Sub
    
    public TestSignatureHelpSource(ITextBuffer textBuffer)
    {
        m_textBuffer = textBuffer;
    }
    
  4. Implémentez la méthode AugmentSignatureHelpSession. Dans cet exemple, les signatures sont codées en dur, mais dans une implémentation complète vous obtiendriez ces informations dans la documentation du langage.

    Public Sub AugmentSignatureHelpSession(ByVal session As ISignatureHelpSession, ByVal signatures As IList(Of ISignature)) Implements ISignatureHelpSource.AugmentSignatureHelpSession
        Dim snapshot As ITextSnapshot = m_textBuffer.CurrentSnapshot
        Dim position As Integer = session.GetTriggerPoint(m_textBuffer).GetPosition(snapshot)
    
        Dim applicableToSpan As ITrackingSpan = m_textBuffer.CurrentSnapshot.CreateTrackingSpan(New Span(position, 0), SpanTrackingMode.EdgeInclusive, 0)
    
        signatures.Add(CreateSignature(m_textBuffer, "add(int firstInt, int secondInt)", "Documentation for adding integers.", applicableToSpan))
        signatures.Add(CreateSignature(m_textBuffer, "add(double firstDouble, double secondDouble)", "Documentation for adding doubles.", applicableToSpan))
    End Sub
    
    public void AugmentSignatureHelpSession(ISignatureHelpSession session, IList<ISignature> signatures)
    {
        ITextSnapshot snapshot = m_textBuffer.CurrentSnapshot;
        int position = session.GetTriggerPoint(m_textBuffer).GetPosition(snapshot);
    
        ITrackingSpan applicableToSpan = m_textBuffer.CurrentSnapshot.CreateTrackingSpan(
         new Span(position, 0), SpanTrackingMode.EdgeInclusive, 0);
    
        signatures.Add(CreateSignature(m_textBuffer, "add(int firstInt, int secondInt)", "Documentation for adding integers.", applicableToSpan));
        signatures.Add(CreateSignature(m_textBuffer, "add(double firstDouble, double secondDouble)", "Documentation for adding doubles.", applicableToSpan));
    
    }
    
  5. La méthode d'assistance CreateSignature() est données à des fins de illustration.

    Private Function CreateSignature(ByVal textBuffer As ITextBuffer, ByVal methodSig As String, ByVal methodDoc As String, ByVal span As ITrackingSpan) As TestSignature
        Dim sig As New TestSignature(textBuffer, methodSig, methodDoc, Nothing)
        AddHandler textBuffer.Changed, AddressOf sig.OnSubjectBufferChanged
    
        'find the parameters in the method signature (expect methodname(one, two) 
        Dim pars() As String = methodSig.Split(New Char() {"("c, ","c, ")"c})
        Dim paramList As New List(Of IParameter)()
    
        Dim locusSearchStart As Integer = 0
        For i As Integer = 1 To pars.Length - 1
            Dim param As String = pars(i).Trim()
    
            If String.IsNullOrEmpty(param) Then 
                Continue For 
            End If 
    
            'find where this parameter is located in the method signature 
            Dim locusStart As Integer = methodSig.IndexOf(param, locusSearchStart)
            If locusStart >= 0 Then 
                Dim locus As New Span(locusStart, param.Length)
                locusSearchStart = locusStart + param.Length
                paramList.Add(New TestParameter("Documentation for the parameter.", locus, param, sig))
            End If 
        Next i
    
        sig.m_Parameters = New ReadOnlyCollection(Of IParameter)(paramList)
        sig.m_ApplicableToSpan = span
        sig.ComputeCurrentParameter()
        Return sig
    End Function
    
    private TestSignature CreateSignature(ITextBuffer textBuffer, string methodSig, string methodDoc, ITrackingSpan span)
    {
        TestSignature sig = new TestSignature(textBuffer, methodSig, methodDoc, null);
        textBuffer.Changed += new EventHandler<TextContentChangedEventArgs>(sig.OnSubjectBufferChanged);
    
        //find the parameters in the method signature (expect methodname(one, two) 
        string[] pars = methodSig.Split(new char[] { '(', ',', ')' });
        List<IParameter> paramList = new List<IParameter>();
    
        int locusSearchStart = 0;
        for (int i = 1; i < pars.Length; i++)
        {
            string param = pars[i].Trim();
    
            if (string.IsNullOrEmpty(param))
                continue;
    
            //find where this parameter is located in the method signature 
            int locusStart = methodSig.IndexOf(param, locusSearchStart);
            if (locusStart >= 0)
            {
                Span locus = new Span(locusStart, param.Length);
                locusSearchStart = locusStart + param.Length;
                paramList.Add(new TestParameter("Documentation for the parameter.", locus, param, sig));
            }
        }
    
        sig.Parameters = new ReadOnlyCollection<IParameter>(paramList);
        sig.ApplicableToSpan = span;
        sig.ComputeCurrentParameter();
        return sig;
    }
    
  6. Implémentez la méthode GetBestMatch. Dans cet exemple, il n'existe qu'deux signatures, avec deux paramètres. par conséquent, cette méthode n'est pas requise. Dans une implémentation plus complète, dans laquelle plusieurs sources d'assistance de signature est disponible, cette méthode est utilisée pour décider si la source d'assistance de signature la plus élevée peut fournir une signature correspondante. S'il n'est pas le cas, retourne null de méthode et la source de NeXT-plus haute priorité est de fournir une correspondance.

    Public Function GetBestMatch(ByVal session As ISignatureHelpSession) As ISignature Implements ISignatureHelpSource.GetBestMatch
        If session.Signatures.Count > 0 Then 
            Dim applicableToSpan As ITrackingSpan = session.Signatures(0).ApplicableToSpan
            Dim text As String = applicableToSpan.GetText(applicableToSpan.TextBuffer.CurrentSnapshot)
    
            If text.Trim().Equals("add") Then 'get only "add" 
                Return session.Signatures(0)
            End If 
        End If 
        Return Nothing 
    End Function
    
    public ISignature GetBestMatch(ISignatureHelpSession session)
    {
        if (session.Signatures.Count > 0)
        {
            ITrackingSpan applicableToSpan = session.Signatures[0].ApplicableToSpan;
            string text = applicableToSpan.GetText(applicableToSpan.TextBuffer.CurrentSnapshot);
    
            if (text.Trim().Equals("add"))  //get only "add"  
                return session.Signatures[0];
        }
        return null;
    }
    
  7. Implémentez la méthode de Dispose() :

    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 le fournisseur de sources d'assistance de signature

Le fournisseur de sources d'assistance de signature est chargé d'exporter une partie des éléments managée (MEF) managed extensibility framework et d'instancier la source d'assistance de signature.

Pour implémenter le fournisseur de sources d'assistance de signature

  1. Ajoutez une classe nommée TestSignatureHelpSourceProvider qui implémente ISignatureHelpSourceProvider, et réexportez elle avec NameAttribute, ContentTypeAttribute « texte », et OrderAttribute de Before= " défaut ».

    <Export(GetType(ISignatureHelpSourceProvider)), Name("Signature Help source"), Order(Before:="default"), ContentType("text")>
    Friend Class TestSignatureHelpSourceProvider
        Implements ISignatureHelpSourceProvider
    
    [Export(typeof(ISignatureHelpSourceProvider))]
    [Name("Signature Help source")]
    [Order(Before = "default")]
    [ContentType("text")]
    internal class TestSignatureHelpSourceProvider : ISignatureHelpSourceProvider
    
  2. implémentez l' TryCreateSignatureHelpSource en instanciant TestSignatureHelpSource.

    Public Function TryCreateSignatureHelpSource(ByVal textBuffer As ITextBuffer) As ISignatureHelpSource Implements ISignatureHelpSourceProvider.TryCreateSignatureHelpSource
        Return New TestSignatureHelpSource(textBuffer)
    End Function
    
    public ISignatureHelpSource TryCreateSignatureHelpSource(ITextBuffer textBuffer)
    {
        return new TestSignatureHelpSource(textBuffer);
    }
    

Implémentation du gestionnaire de commandes

L'assistance de signature est généralement levée par (caractère et fermé par un) le caractère. Vous pouvez gérer ces séquences de touches en implémentant IOleCommandTarget afin qu'il déclenche une session d'assistance de signature lorsqu'il reçoit un (le caractère précédé d'un nom de méthode, et ferme la session lorsqu'il reçoit un) le caractère.

pour implémenter le gestionnaire de commandes

  1. ajoutez une classe nommée TestSignatureHelpCommand qui implémente IOleCommandTarget.

    Friend NotInheritable Class TestSignatureHelpCommandHandler
        Implements IOleCommandTarget
    
    internal sealed class TestSignatureHelpCommandHandler : IOleCommandTarget
    
  2. Ajoutez des champs privés pour l'adaptateur d' IVsTextView (qui vous permet d'ajouter le gestionnaire de commandes aux gestionnaires de hiérarchie de commandes), l'affichage de texte, le service broker et la session d'assistance de signature, ITextStructureNavigator, et IOleCommandTargetsuivant.

    Private m_nextCommandHandler As IOleCommandTarget
    Private m_textView As ITextView
    Private m_broker As ISignatureHelpBroker
    Private m_session As ISignatureHelpSession
    Private m_navigator As ITextStructureNavigator
    
    IOleCommandTarget m_nextCommandHandler;
    ITextView m_textView;
    ISignatureHelpBroker m_broker;
    ISignatureHelpSession m_session;
    ITextStructureNavigator m_navigator;
    
  3. Ajoutez un constructeur pour initialiser ces champs et pour ajouter le filtre de commande aux filtres de hiérarchie de commandes.

    Friend Sub New(ByVal textViewAdapter As IVsTextView, ByVal textView As ITextView, ByVal nav As ITextStructureNavigator, ByVal broker As ISignatureHelpBroker)
        Me.m_textView = textView
        Me.m_broker = broker
        Me.m_navigator = nav
    
        'add this to the filter chain
        textViewAdapter.AddCommandFilter(Me, m_nextCommandHandler)
    End Sub
    
    internal TestSignatureHelpCommandHandler(IVsTextView textViewAdapter, ITextView textView, ITextStructureNavigator nav, ISignatureHelpBroker broker)
    {
        this.m_textView = textView;
        this.m_broker = broker;
        this.m_navigator = nav;
    
        //add this to the filter chain
        textViewAdapter.AddCommandFilter(this, out m_nextCommandHandler);
    }
    
  4. Implémentez la méthode d' Exec pour déclencher la session d'assistance de signature lorsque le filtre de commande accepte un (caractère après un des noms de méthodes, et pour fermer la session lorsqu'il reçoit un) le caractère alors que la session est encore active. dans tous les cas, la commande est transférée.

    Public Function Exec(ByRef pguidCmdGroup As Guid, ByVal nCmdID As UInteger, ByVal nCmdexecopt As UInteger, ByVal pvaIn As IntPtr, ByVal pvaOut As IntPtr) As Integer Implements IOleCommandTarget.Exec
        Dim typedChar As Char = Char.MinValue
    
        If pguidCmdGroup = VSConstants.VSStd2K AndAlso nCmdID = CUInt(VSConstants.VSStd2KCmdID.TYPECHAR) Then
            typedChar = CChar(ChrW(CUShort(Marshal.GetObjectForNativeVariant(pvaIn))))
            If typedChar.Equals("("c) Then 
                'move the point back so it's in the preceding word 
                Dim point As SnapshotPoint = m_textView.Caret.Position.BufferPosition - 1
                Dim extent As TextExtent = m_navigator.GetExtentOfWord(point)
                Dim word As String = extent.Span.GetText()
                If word.Equals("add") Then
                    m_session = m_broker.TriggerSignatureHelp(m_textView)
                End If 
    
            ElseIf typedChar.Equals(")"c) AndAlso m_session IsNot Nothing Then
                m_session.Dismiss()
                m_session = Nothing 
            End If 
        End If 
        Return m_nextCommandHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut)
    End Function
    
    public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
    {
        char typedChar = char.MinValue;
    
        if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
        {
            typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
            if (typedChar.Equals('('))
            {
                //move the point back so it's in the preceding word
                SnapshotPoint point = m_textView.Caret.Position.BufferPosition - 1;
                TextExtent extent = m_navigator.GetExtentOfWord(point);
                string word = extent.Span.GetText();
                if (word.Equals("add"))
                    m_session = m_broker.TriggerSignatureHelp(m_textView);
    
            }
            else if (typedChar.Equals(')') && m_session != null)
            {
                m_session.Dismiss();
                m_session = null;
            }
        }
        return m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
    }
    
  5. Implémentez la méthode d' QueryStatus afin qu'elle transfère toujours la commande.

    Public Function QueryStatus(ByRef pguidCmdGroup As Guid, ByVal cCmds As UInteger, ByVal prgCmds() As OLECMD, ByVal pCmdText As IntPtr) As Integer Implements IOleCommandTarget.QueryStatus
        Return m_nextCommandHandler.QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText)
    End Function
    
    public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
    {
        return m_nextCommandHandler.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
    }
    

Implémenter le fournisseur d'ordre d'assistance de signature

Vous pouvez fournir l'ordre d'assistance de signature en implémentant IVsTextViewCreationListener pour instancier le gestionnaire de commandes lorsque l'affichage de texte est créé.

Pour implémenter le fournisseur d'ordre d'assistance de signature

  1. ajoutez une classe nommée TestSignatureHelpController qui implémente IVsTextViewCreationListener et exportez-la avec NameAttribute, ContentTypeAttribute, et TextViewRoleAttribute.

    <Export(GetType(IVsTextViewCreationListener)), Name("Signature Help controller"), TextViewRole(PredefinedTextViewRoles.Editable), ContentType("text")>
    Friend Class TestSignatureHelpCommandProvider
        Implements IVsTextViewCreationListener
    
    [Export(typeof(IVsTextViewCreationListener))]
    [Name("Signature Help controller")]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    [ContentType("text")]
    internal class TestSignatureHelpCommandProvider : IVsTextViewCreationListener
    
  2. Importez IVsEditorAdaptersFactoryService (utilisé pour obtenir ITextView, en fonction de l'objet d' IVsTextView ), ITextStructureNavigatorSelectorService (utilisé pour rechercher le mot actuel), et ISignatureHelpBroker (pour déclencher la session d'assistance de signature.)

    <Import()>
    Friend AdapterService As IVsEditorAdaptersFactoryService
    
    <Import()>
    Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
    
    <Import()>
    Friend SignatureHelpBroker As ISignatureHelpBroker
    
    [Import]
    internal IVsEditorAdaptersFactoryService AdapterService;
    
    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
    [Import]
    internal ISignatureHelpBroker SignatureHelpBroker;
    
  3. Implémentez la méthode d' VsTextViewCreated en instanciant TestSignatureCommandHandler.

    Public Sub VsTextViewCreated(ByVal textViewAdapter As IVsTextView) Implements IVsTextViewCreationListener.VsTextViewCreated
        Dim textView As ITextView = AdapterService.GetWpfTextView(textViewAdapter)
        If textView Is Nothing Then 
            Return 
        End If
    
        textView.Properties.GetOrCreateSingletonProperty(Function() New TestSignatureHelpCommandHandler(textViewAdapter, textView, NavigatorService.GetTextStructureNavigator(textView.TextBuffer), SignatureHelpBroker))
    End Sub
    
    public void VsTextViewCreated(IVsTextView textViewAdapter)
    {
        ITextView textView = AdapterService.GetWpfTextView(textViewAdapter);
        if (textView == null)
            return;
    
        textView.Properties.GetOrCreateSingletonProperty(
             () => new TestSignatureHelpCommandHandler(textViewAdapter,
                textView,
                NavigatorService.GetTextStructureNavigator(textView.TextBuffer),
                SignatureHelpBroker));
    }
    

Génération et test de code

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

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

  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 le mot « add » plus une parenthèse ouvrante.

  4. Lorsque vous tapez la parenthèse ouvrante, vous devez afficher une info-bulle qui affiche une liste des deux signatures de la méthode d' add() .

Voir aussi

Tâches

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