Compartir a través de


tutorial: Mostrar la Ayuda para las firmas

Ayuda de la firma (también conocida como información de parámetros) muestra la firma de un método en una información sobre herramientas cuando un usuario el carácter inicial de la lista de parámetros (normalmente el paréntesis de apertura). Mientras se escriben un parámetro y un separador de parámetro (normalmente una coma), la información sobre herramientas se actualiza para mostrar el parámetro siguiente en negrita. Puede definir la Ayuda para las firmas en el contexto de un servicio de, o puede definir dispone de Ayuda de la extensión de nombre de archivo y la firma del tipo de contenido y mostrar sólo para ese tipo, o puede proporcionar Ayuda para un tipo de contenido existente (por ejemplo, “text” de la firma.) Este tutorial muestra cómo mostrar Ayuda para las firmas para el tipo de contenido “text”.

Ayuda de la firma se activan normalmente escribiendo un carácter concreto, por ejemplo, “(” (paréntesis de apertura), y despedido escribiendo otro carácter, por ejemplo, ")” (paréntesis de cierre). Las características de IntelliSense que son desencadenadas escribiendo un carácter se pueden implementar mediante un controlador de comandos por presiones de tecla (la interfaz de IOleCommandTarget ) y un proveedor de controlador que implementa la interfaz de IVsTextViewCreationListener . Para crear la firmas el origen, que es la lista de firmas que participan en la Ayuda de la firma, implementan la interfaz de ISignatureHelpSource y un proveedor de origen que implementa la interfaz de ISignatureHelpSourceProvider . Los proveedores son elementos (MEF) de managed extensibility framework, y son responsables de exportar el origen y las clases de controlador e importar los servicios y los agentes, por ejemplo, ITextStructureNavigatorSelectorService, que permite navegar en el búfer de texto, y ISignatureHelpBroker, que activa una sesión de Ayuda para las firmas.

Este tutorial muestra cómo implementar la Ayuda para las firmas para un conjunto codificadas de forma rígida de identificadores. En implementaciones completas, el lenguaje es responsable de proporcionar al contenido.

Requisitos previos

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

Nota

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

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

  4. Guarde y cierre Source.extension.vsixmanifest.

  5. Agregue las referencias siguientes al proyecto y, a CopyLocal establecido en false:

    Microsoft.VisualStudio.Editor

    Microsoft.VisualStudio.Language.Intellisense

    Microsoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell

    Microsoft.VisualStudio.TextManager.Interop

  6. elimine los archivos existentes de la clase.

Implementar las signaturas y parámetros de Ayuda para las firmas

el origen de la Ayuda de la firma se basa en las firmas que implementan ISignature, que contiene los parámetros que implementan IParameter. En una implementación completa, esta información se obtiene de la documentación del lenguaje, pero en este ejemplo, las firmas están codificados de forma rígida.

Para implementar la firmas las firmas y parámetros

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

  2. Agregue imports.

    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. agregue una clase denominada TestParameter que implemente IParameter.

    Friend Class TestParameter
        Implements IParameter
    
    internal class TestParameter : IParameter
    
  4. Agregue un constructor que establezca todas las propiedades.

    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. Agregue propiedades de 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. agregue una clase denominada TestSignature que implemente ISignature.

    Friend Class TestSignature
        Implements ISignature
    
    internal class TestSignature : ISignature
    
  7. agregue algunos campos privados.

    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. Agregue un constructor que establezca los campos y suscriba Changed el evento.

    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. declare un evento de CurrentParameterChanged . Se provoca este evento cuando el usuario rellena uno de los parámetros en la firma.

    Public Event CurrentParameterChanged As EventHandler(Of CurrentParameterChangedEventArgs) Implements ISignature.CurrentParameterChanged
    
    public event EventHandler<CurrentParameterChangedEventArgs> CurrentParameterChanged;
    
  10. Implemente la propiedad de CurrentParameter de modo que provoque el evento de CurrentParameterChanged cuando cambia el valor de propiedad.

    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. Agregue un método que genera el evento de 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. Agregue un método que calcule el parámetro actual comparando el número de comas en ApplicableToSpan al número de comas en la firma.

    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. Agregue un controlador de eventos para el evento Changed que llama al método de 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. Implemente la propiedad ApplicableToSpan. Esta propiedad contiene ITrackingSpan que corresponde al intervalo de texto en el búfer al que la firma aplica.

    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. implemente los otros parámetros.

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

Implementar el origen de Ayuda para las firmas

El origen de Ayuda para las firmas es el conjunto de firmas que proporcione información.

Para implementar el origen de Ayuda para las firmas

  1. agregue una clase denominada TestSignatureHelpSource que implemente ISignatureHelpSource.

    Friend Class TestSignatureHelpSource
        Implements ISignatureHelpSource
    
    internal class TestSignatureHelpSource : ISignatureHelpSource
    
  2. Agregue una referencia al búfer de texto.

    Private m_textBuffer As ITextBuffer
    
    private ITextBuffer m_textBuffer;
    
  3. Agregue un constructor que establezca el búfer de texto y el proveedor de origen de Ayuda para las firmas.

    Public Sub New(ByVal textBuffer As ITextBuffer)
        m_textBuffer = textBuffer
    End Sub
    
    public TestSignatureHelpSource(ITextBuffer textBuffer)
    {
        m_textBuffer = textBuffer;
    }
    
  4. Implemente el método AugmentSignatureHelpSession. En este ejemplo, las firmas está incluido en el código, pero en una implementación completa obtendría esta información en la documentación del lenguaje.

    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. El método auxiliar CreateSignature() se proporciona solo para la ilustración.

    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. Implemente el método GetBestMatch. En este ejemplo, hay sólo dos firmas, que tiene dos parámetros. Por consiguiente, este método no se requiere. En una implementación más completa, en la que más de un origen de Ayuda para las firmas está disponible, este método se utiliza para decidir si el origen prioridad de Ayuda para las firmas puede proporcionar una firma coincidente. En caso contrario, el método devuelve null y el origen de la NeXT-alto-prioridad se pide proporcionar una coincidencia.

    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. implemente el método 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;
        }
    }
    

Implementar el proveedor de origen de Ayuda para las firmas

El proveedor de origen de Ayuda para las firmas es responsable de exportar la parte (MEF) de managed extensibility framework y crear una instancia del origen de Ayuda para las firmas.

Para implementar el proveedor de origen de Ayuda para las firmas

  1. Agregue una clase denominada TestSignatureHelpSourceProvider que implemente ISignatureHelpSourceProvider, y exportar la con NameAttribute, ContentTypeAttribute “text”, y OrderAttribute de Before= " predeterminado”.

    <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. implemente el TryCreateSignatureHelpSource creando instancias 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);
    }
    

Implementar el controlador de comandos

Ayuda de la firma se activan normalmente por (carácter y despedido por a) el carácter. Puede controlar estas pulsaciones de tecla implementando IOleCommandTarget para desencadenar una sesión de Ayuda para las firmas cuando recibe a (el carácter precedido por un nombre conocido del método, y descarta la sesión cuando recibe una) el carácter.

Para implementar el controlador de comandos

  1. agregue una clase denominada TestSignatureHelpCommand que implemente IOleCommandTarget.

    Friend NotInheritable Class TestSignatureHelpCommandHandler
        Implements IOleCommandTarget
    
    internal sealed class TestSignatureHelpCommandHandler : IOleCommandTarget
    
  2. Agregue campos privados para el adaptador de IVsTextView (que permite agregar el controlador de comandos a la cadena de controladores de comandos), la vista de texto, el agente y la sesión de Ayuda para las firmas, ITextStructureNavigator, y IOleCommandTargetsiguiente.

    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. Agregue un constructor para inicializar estos campos y agregar el filtro de comando a los filtros de la cadena de comandos.

    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. Implemente el método de Exec para desencadenar una sesión de Ayuda para las firmas cuando el filtro de comando recibe a (carácter después de uno de los nombres conocidos de método, y descartar la sesión cuando recibe una) el carácter mientras la sesión todavía está activa. En todos los casos, reenvían al comando.

    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. Implemente el método de QueryStatus para que reenvíe siempre el comando.

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

Implementar el proveedor de comando de Ayuda para las firmas

Puede proporcionar el comando de Ayuda para las firmas implementando IVsTextViewCreationListener para crear instancias del controlador de comandos cuando se crea la vista de texto.

Para implementar el proveedor de comando de Ayuda para las firmas

  1. agregue una clase denominada TestSignatureHelpController que implemente IVsTextViewCreationListener y exportela con NameAttribute, ContentTypeAttribute, y 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. Cantidad IVsEditorAdaptersFactoryService (usado para obtener ITextView, dado el objeto de IVsTextView ), ITextStructureNavigatorSelectorService (utilizado para buscar la palabra actual), y ISignatureHelpBroker (desencadenar una sesión de Ayuda para las firmas).

    <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. Implemente el método de VsTextViewCreated creando instancias 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));
    }
    

Compilar y probar el código

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

para compilar y probar la solución de SignatureHelpTest

  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 la palabra “agregar” más paréntesis de apertura.

  4. Después de escribir el paréntesis de apertura, debería ver una información sobre herramientas que muestra una lista de las dos firmas para el método de add() .

Vea también

Tareas

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