当用户键入参数列表起始字符(通常是左括号)时,签名帮助(也称为 参数信息)在工具提示中显示方法的签名。 作为参数和参数分隔符(通常为逗号),工具提示将更新为以粗体显示下一个参数。 可以通过以下方式定义签名帮助:在语言服务的上下文中,定义自己的文件扩展名和内容类型,并仅显示该类型的签名帮助,或显示现有内容类型的签名帮助(例如“text”)。 本演练演示如何显示“text”内容类型的签名帮助。
签名帮助通常通过键入特定字符(例如“(”)(左括号)触发,并通过键入另一个字符(例如“)”(右括号)来消除。 可以通过使用键击( IOleCommandTarget 接口)的命令处理程序和实现 IVsTextViewCreationListener 接口的处理程序提供程序来实现通过键入字符触发的 IntelliSense 功能。 若要创建签名帮助源,该源是参与签名帮助的签名列表,请实现 ISignatureHelpSource 该接口和运行接口的 ISignatureHelpSourceProvider 源提供程序。 提供程序是托管扩展性框架(MEF)组件部件,负责导出源和控制器类以及导入服务和中转站,例如 ITextStructureNavigatorSelectorService,允许在文本缓冲区中导航,以及 ISignatureHelpBroker触发签名帮助会话的提供程序。
本演练演示如何为硬编码的标识符集设置签名帮助。 在完整的实现中,语言负责提供该内容。
创建 MEF 项目
创建 MEF 项目
- 创建 C# VSIX 项目。 (在 “新建项目 ”对话框,选择 Visual C# /扩展性,然后选择 VSIX Project。)将解决方案 - SignatureHelpTest命名为 。
 
- 向项目添加编辑器分类器项模板。 有关详细信息,请参阅使用编辑器项模板创建扩展。 
- 删除现有的类文件。 
- 将以下引用添加到项目,并确保 CopyLocal 设置为 - false:
 - Microsoft.VisualStudio.Editor - Microsoft.VisualStudio.Language.Intellisense - Microsoft.VisualStudio.OLE.Interop - Microsoft.VisualStudio.Shell.14.0 - Microsoft.VisualStudio.TextManager.Interop 
实现签名帮助签名和参数
签名帮助源基于实现 ISignature的签名,每个签名都包含实现 IParameter的参数。 在完整实现中,此信息将从语言文档获取,但在此示例中,签名是硬编码的。
实现签名帮助签名和参数
- 添加一个类文件并将其命名为 - SignatureHelpSource。
 
- 添加以下 import 语句。 - 
- 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;
 - 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
 
 
- 添加一个名为 - TestParameter实现的 IParameter类。
 - 
- internal class TestParameter : IParameter
 - Friend Class TestParameter
    Implements IParameter
 
 
- 添加设置所有属性的构造函数。 - 
- public TestParameter(string documentation, Span locus, string name, ISignature signature)
{
    Documentation = documentation;
    Locus = locus;
    Name = name;
    Signature = signature;
}
 - 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
 
 
- 添加 . IParameter的属性 - 
- 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; }
 - 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
 
 
- 添加一个名为 - TestSignature实现的 ISignature类。
 - 
- internal class TestSignature : ISignature
 - Friend Class TestSignature
    Implements ISignature
 
 
- 添加一些专用字段。 - 
- 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;
 - 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
 
 
- 添加一个构造函数,用于设置字段并订阅事件 Changed 。 - 
- 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);
}
 - 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
 
 
- 声明事件 - CurrentParameterChanged。 当用户填写签名中的某个参数时,将引发此事件。
 - 
- public event EventHandler<CurrentParameterChangedEventArgs> CurrentParameterChanged;
 - Public Event CurrentParameterChanged As EventHandler(Of CurrentParameterChangedEventArgs) Implements ISignature.CurrentParameterChanged
 
 
- 实现该 CurrentParameter 属性,以便在属性值发生更改时引发 - CurrentParameterChanged事件。
 - 
- 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);
        }
    }
}
 - ReadOnly Property CurrentParameter() As IParameter Implements ISignature.CurrentParameter
    Get
        Return m_currentParameter
    End Get
End Property
 
 
- 添加引发 - CurrentParameterChanged事件的方法。
 - 
- private void RaiseCurrentParameterChanged(IParameter prevCurrentParameter, IParameter newCurrentParameter)
{
    EventHandler<CurrentParameterChangedEventArgs> tempHandler = this.CurrentParameterChanged;
    if (tempHandler != null)
    {
        tempHandler(this, new CurrentParameterChangedEventArgs(prevCurrentParameter, newCurrentParameter));
    }
}
 - 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
 
 
- 添加一个方法,该方法通过将签名中的 ApplicableToSpan 逗号数与签名中的逗号数进行比较来计算当前参数。 - 
- 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];
    }
}
 - 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
 
 
- 为 Changed 调用 - ComputeCurrentParameter()该方法的事件添加事件处理程序。
 - 
- internal void OnSubjectBufferChanged(object sender, TextContentChangedEventArgs e)
{
    this.ComputeCurrentParameter();
}
 - Friend Sub OnSubjectBufferChanged(ByVal sender As Object, ByVal e As TextContentChangedEventArgs)
    Me.ComputeCurrentParameter()
End Sub
 
 
- 实现 ApplicableToSpan 属性。 此属性包含与 ITrackingSpan 签名应用到的缓冲区中的文本范围对应的属性。 - 
- public ITrackingSpan ApplicableToSpan
{
    get { return (m_applicableToSpan); }
    internal set { m_applicableToSpan = value; }
}
 - ReadOnly Property ApplicableToSpan() As ITrackingSpan Implements ISignature.ApplicableToSpan
    Get
        Return (m_applicableToSpan)
    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; }
}
 - 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
 
 
实现签名帮助源
签名帮助源是你为其提供信息的签名集。
实现签名帮助源
- 添加一个名为 - TestSignatureHelpSource实现的 ISignatureHelpSource类。
 - 
- internal class TestSignatureHelpSource : ISignatureHelpSource
 - Friend Class TestSignatureHelpSource
    Implements ISignatureHelpSource
 
 
- 添加对文本缓冲区的引用。 - 
- private ITextBuffer m_textBuffer;
 - Private m_textBuffer As ITextBuffer
 
 
- 添加设置文本缓冲区和签名帮助源提供程序的构造函数。 - 
- public TestSignatureHelpSource(ITextBuffer textBuffer)
{
    m_textBuffer = textBuffer;
}
 - Public Sub New(ByVal textBuffer As ITextBuffer)
    m_textBuffer = textBuffer
End Sub
 
 
- 实现 AugmentSignatureHelpSession 方法。 在此示例中,签名是硬编码的,但在完整实现中,你将从语言文档获取此信息。 - 
- 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));
}
 - 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
 
 
- 仅为了说明提供帮助程序方法 - CreateSignature()。
 - 
- 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;
}
 - 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
 
 
- 实现 GetBestMatch 方法。 在此示例中,只有两个签名,每个签名都有两个参数。 因此,不需要此方法。 在提供多个签名帮助源的更完整的实现中,此方法用于确定最高优先级的签名帮助源是否可以提供匹配的签名。 如果无法,该方法将返回 null,并要求下一个优先级最高的源提供匹配项。 - 
- 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;
}
 - 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
 
 
- Dispose()实现方法:
 - 
- private bool m_isDisposed;
public void Dispose()
{
    if (!m_isDisposed)
    {
        GC.SuppressFinalize(this);
        m_isDisposed = true;
    }
}
 - 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
 
 
实现签名帮助源提供程序
签名帮助源提供程序负责导出托管扩展性框架 (MEF) 组件部件,以及实例化签名帮助源。
实现签名帮助源提供程序
- 添加一个名为 - TestSignatureHelpSourceProvider实现 ISignatureHelpSourceProvider的类,并使用“text”和 Before=“default”的 a NameAttribute、一个 ContentTypeAttribute “text”和 a OrderAttribute of Before=“default”导出它。
 - 
- [Export(typeof(ISignatureHelpSourceProvider))]
[Name("Signature Help source")]
[Order(Before = "default")]
[ContentType("text")]
internal class TestSignatureHelpSourceProvider : ISignatureHelpSourceProvider
 - <Export(GetType(ISignatureHelpSourceProvider)), Name("Signature Help source"), Order(Before:="default"), ContentType("text")>
Friend Class TestSignatureHelpSourceProvider
    Implements ISignatureHelpSourceProvider
 
 
- TryCreateSignatureHelpSource通过实例化 - TestSignatureHelpSource.
 - 
- public ISignatureHelpSource TryCreateSignatureHelpSource(ITextBuffer textBuffer)
{
    return new TestSignatureHelpSource(textBuffer);
}
 - Public Function TryCreateSignatureHelpSource(ByVal textBuffer As ITextBuffer) As ISignatureHelpSource Implements ISignatureHelpSourceProvider.TryCreateSignatureHelpSource
    Return New TestSignatureHelpSource(textBuffer)
End Function
 
 
实现命令处理程序
签名帮助通常由左括号“(”字符触发,右括号“)”字符消除。 你可以通过运行 a IOleCommandTarget 来处理这些击键,以便在它收到以已知方法名称开头的左括号字符时触发签名帮助会话,并在收到右括号字符时关闭会话。
实现命令处理程序
- 添加一个名为 - TestSignatureHelpCommand实现的 IOleCommandTarget类。
 - 
- internal sealed class TestSignatureHelpCommandHandler : IOleCommandTarget
 - Friend NotInheritable Class TestSignatureHelpCommandHandler
    Implements IOleCommandTarget
 
 
- 为 IVsTextView 适配器添加专用字段(这使你可以将命令处理程序添加到命令处理程序链)、文本视图、签名帮助代理和会话、a ITextStructureNavigator和下一个 IOleCommandTarget。 - 
- IOleCommandTarget m_nextCommandHandler;
ITextView m_textView;
ISignatureHelpBroker m_broker;
ISignatureHelpSession m_session;
ITextStructureNavigator m_navigator;
 - 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
 
 
- 添加构造函数来初始化这些字段,并将命令筛选器添加到命令筛选器链。 - 
- 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);
}
 - 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
 
 
- Exec实现当命令筛选器在已知方法名称后收到左括号“(”字符)时触发签名帮助会话的方法,并在会话仍然处于活动状态时接收右括号“)”字符时关闭会话。 在每种情况下,命令都会转发。 - 
- 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);
}
 - 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
 
 
- 实现该方法 QueryStatus ,使其始终转发命令。 - 
- public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
{
    return m_nextCommandHandler.QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
}
 - 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
 
 
实现签名帮助命令提供程序
可以通过实现 IVsTextViewCreationListener 创建文本视图时实例化命令处理程序来提供签名帮助命令。
实现签名帮助命令提供程序
- 使用  和  TextViewRoleAttribute添加一个名为- TestSignatureHelpController实现IVsTextViewCreationListener和导出它的NameAttribute类。 ContentTypeAttribute
 - 
- [Export(typeof(IVsTextViewCreationListener))]
[Name("Signature Help controller")]
[TextViewRole(PredefinedTextViewRoles.Editable)]
[ContentType("text")]
internal class TestSignatureHelpCommandProvider : IVsTextViewCreationListener
 - <Export(GetType(IVsTextViewCreationListener)), Name("Signature Help controller"), TextViewRole(PredefinedTextViewRoles.Editable), ContentType("text")>
Friend Class TestSignatureHelpCommandProvider
    Implements IVsTextViewCreationListener
 
 
- IVsEditorAdaptersFactoryService 导入(用于获取ITextView给定IVsTextView对象)、ITextStructureNavigatorSelectorService(用于查找当前单词)和ISignatureHelpBroker(用于触发签名帮助会话)。 - 
- [Import]
internal IVsEditorAdaptersFactoryService AdapterService;
[Import]
internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
[Import]
internal ISignatureHelpBroker SignatureHelpBroker;
 - <Import()>
Friend AdapterService As IVsEditorAdaptersFactoryService
<Import()>
Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
<Import()>
Friend SignatureHelpBroker As ISignatureHelpBroker
 
 
- VsTextViewCreated通过实例化- TestSignatureCommandHandler方法实现该方法。
 - 
- 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));
}
 - 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
 
 
生成并测试代码
若要测试此代码,请生成 SignatureHelpTest 解决方案并在实验实例中运行它。
生成和测试 SignatureHelpTest 解决方案
- 生成解决方案。 
- 在调试器中运行此项目时,将启动 Visual Studio 的第二个实例。 
- 创建文本文件并键入一些包含单词“add”和左括号的文本。 
- 键入左括号后,应会看到一个工具提示,其中显示该方法的两个签名 - add()的列表。
 
相关内容