共用方式為


逐步解說: 顯示 QuickInfo 的工具提示

QuickInfo 是一種 IntelliSense 功能,會顯示方法簽名碼,並描述當使用者將指標移方法名稱。 您可以定義您要提供 QuickInfo 描述識別的項,然後再建立 [顯示內容的工具提示,以實作語言為基礎的功能,例如 QuickInfo。 您可以定義 QuickInfo 語言服務層,也可以定義您自己的檔案名稱副檔名和內容類型,並顯示只是該型別的 QuickInfo 或對於現有的內容類型 (例如,"text"),您可以顯示 QuickInfo。 這個逐步解說會示範如何顯示 QuickInfo,「 文字 」 的內容型別。

QuickInfo 範例中的,在這個逐步解說中會顯示工具提示,當使用者將滑鼠指標移方法名稱。 此設計會要求您實作下列四個介面:

  • 來源介面

  • 來源提供者介面

  • 控制器介面

  • 控制站提供者介面

來源和控制站的提供者管理擴充性架構 (MEF) 元件組件,而負責匯出的來源和控制器類別和匯入服務,並如 brokers ITextBufferFactoryService,以建立工具提示文字緩衝區中,以及IQuickInfoBroker,它會觸發 QuickInfo 工作階段。

在這個範例中,QuickInfo 來源使用硬式編碼清單的方法名稱和描述,但在完整的實作中,語言服務和語言文件都是負責提供該內容。

必要條件

若要完成這個逐步解說中,您必須安裝Visual Studio 2010 SDK。

注意事項注意事項

如需有關 Visual Studio 的 SDK 的詳細資訊,請參閱擴充 Visual Studio 的概觀。若要了解如何下載 Visual Studio 的 SDK,請參閱Visual Studio 擴充性開發人員中心 MSDN 網站上。

建立 MEF 專案

若要建立 MEF 專案

  1. 建立編輯器類別器的專案。 為方案命名 QuickInfoTest。

  2. VSIX 資訊清單編輯器中開啟 Source.extension.vsixmanifest 檔案。

  3. 請確定Content名包含 MEF 元件的內容類型,並Path設定為 QuickInfoTest.dll。

  4. 儲存並關閉 Source.extension.vsixmanifest。

  5. 將下列參考加入至專案,並設定 CopyLocal 到false:

    Microsoft.VisualStudio.Language.Intellisense

  6. 刪除現有的類別檔案。

實作 QuickInfo 的來源

QuickInfo 來源負責收集的識別項和其說明集合,並加入工具提示文字緩衝區的內容,其中一個識別項發生時。 在這個範例中,識別項和其說明剛加入來源的建構函式。

若要實作 QuickInfo 的來源

  1. 將類別檔案,並命名為 TestQuickInfoSource。

  2. 加入下列匯入。

    Imports System
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Text
    Imports System.Collections.ObjectModel
    Imports System.ComponentModel.Composition
    Imports Microsoft.VisualStudio.Language.Intellisense
    Imports Microsoft.VisualStudio.Text
    Imports Microsoft.VisualStudio.Text.Editor
    Imports Microsoft.VisualStudio.Text.Operations
    Imports Microsoft.VisualStudio.Text.Tagging
    Imports Microsoft.VisualStudio.Utilities
    
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.Language.Intellisense;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.Text.Operations;
    using Microsoft.VisualStudio.Text.Tagging;
    using Microsoft.VisualStudio.Utilities;
    
  3. 宣告一個類別,實作IQuickInfoSource,並命名為TestQuickInfoSource

    Friend Class TestQuickInfoSource
        Implements IQuickInfoSource
    
    internal class TestQuickInfoSource : IQuickInfoSource
    
  4. QuickInfo 來源提供者]、 [文字緩衝區中,和 [方法名稱和方法簽名碼的一組中新增欄位。 在這個範例中,方法名稱和簽章中初始化TestQuickInfoSource建構函式。

    Private m_provider As TestQuickInfoSourceProvider
    Private m_subjectBuffer As ITextBuffer
    Private m_dictionary As Dictionary(Of String, String)
    
    private TestQuickInfoSourceProvider m_provider;
    private ITextBuffer m_subjectBuffer;
    private Dictionary<string, string> m_dictionary;
    
  5. 加入建構函式,設定 QuickInfo 的原始檔提供者和文字緩衝區中,並且會填入集合的方法名稱和方法簽名碼和描述。

    Public Sub New(ByVal provider As TestQuickInfoSourceProvider, ByVal subjectBuffer As ITextBuffer)
        m_provider = provider
        m_subjectBuffer = subjectBuffer
    
        'these are the method names and their descriptions
        m_dictionary = New Dictionary(Of String, String)()
        m_dictionary.Add("add", "int add(int firstInt, int secondInt)" & vbLf & "Adds one integer to another.")
        m_dictionary.Add("subtract", "int subtract(int firstInt, int secondInt)" & vbLf & "Subtracts one integer from another.")
        m_dictionary.Add("multiply", "int multiply(int firstInt, int secondInt)" & vbLf & "Multiplies one integer by another.")
        m_dictionary.Add("divide", "int divide(int firstInt, int secondInt)" & vbLf & "Divides one integer by another.")
    End Sub
    
    public TestQuickInfoSource(TestQuickInfoSourceProvider provider, ITextBuffer subjectBuffer)
    {
        m_provider = provider;
        m_subjectBuffer = subjectBuffer;
    
        //these are the method names and their descriptions
        m_dictionary = new Dictionary<string, string>();
        m_dictionary.Add("add", "int add(int firstInt, int secondInt)\nAdds one integer to another.");
        m_dictionary.Add("subtract", "int subtract(int firstInt, int secondInt)\nSubtracts one integer from another.");
        m_dictionary.Add("multiply", "int multiply(int firstInt, int secondInt)\nMultiplies one integer by another.");
        m_dictionary.Add("divide", "int divide(int firstInt, int secondInt)\nDivides one integer by another.");
    }
    
  6. 實作 AugmentQuickInfoSession 方法。 在這個範例中,方法會尋找目前的文字或前一個字游標是否在線條或文字緩衝區的結尾處。 如果 word 是其中一個方法名稱,該方法名稱的描述會加入 QuickInfo 的內容。

    Public Sub AugmentQuickInfoSession(ByVal session As IQuickInfoSession, ByVal qiContent As IList(Of Object), ByRef applicableToSpan As ITrackingSpan) Implements IQuickInfoSource.AugmentQuickInfoSession
        ' Map the trigger point down to our buffer. 
        Dim subjectTriggerPoint As System.Nullable(Of SnapshotPoint) = session.GetTriggerPoint(m_subjectBuffer.CurrentSnapshot)
        If Not subjectTriggerPoint.HasValue Then
            applicableToSpan = Nothing 
            Exit Sub 
        End If 
    
        Dim currentSnapshot As ITextSnapshot = subjectTriggerPoint.Value.Snapshot
        Dim querySpan As New SnapshotSpan(subjectTriggerPoint.Value, 0)
    
        'look for occurrences of our QuickInfo words in the span 
        Dim navigator As ITextStructureNavigator = m_provider.NavigatorService.GetTextStructureNavigator(m_subjectBuffer)
        Dim extent As TextExtent = navigator.GetExtentOfWord(subjectTriggerPoint.Value)
        Dim searchText As String = extent.Span.GetText()
    
        For Each key As String In m_dictionary.Keys
            Dim foundIndex As Integer = searchText.IndexOf(key, StringComparison.CurrentCultureIgnoreCase)
            If foundIndex > -1 Then
                applicableToSpan = currentSnapshot.CreateTrackingSpan(querySpan.Start.Add(foundIndex).Position, 9, SpanTrackingMode.EdgeInclusive)
    
                Dim value As String = ""
                m_dictionary.TryGetValue(key, value)
                If value IsNot Nothing Then
                    qiContent.Add(value)
                Else
                    qiContent.Add("")
                End If 
    
                Exit Sub 
            End If 
        Next
    
        applicableToSpan = Nothing 
    End Sub
    
    public void AugmentQuickInfoSession(IQuickInfoSession session, IList<object> qiContent, out ITrackingSpan applicableToSpan)
    {
        // Map the trigger point down to our buffer.
        SnapshotPoint? subjectTriggerPoint = session.GetTriggerPoint(m_subjectBuffer.CurrentSnapshot);
        if (!subjectTriggerPoint.HasValue)
        {
            applicableToSpan = null;
            return;
        }
    
        ITextSnapshot currentSnapshot = subjectTriggerPoint.Value.Snapshot;
        SnapshotSpan querySpan = new SnapshotSpan(subjectTriggerPoint.Value, 0);
    
        //look for occurrences of our QuickInfo words in the span
        ITextStructureNavigator navigator = m_provider.NavigatorService.GetTextStructureNavigator(m_subjectBuffer);
        TextExtent extent = navigator.GetExtentOfWord(subjectTriggerPoint.Value);
        string searchText = extent.Span.GetText();
    
        foreach (string key in m_dictionary.Keys)
        {
            int foundIndex = searchText.IndexOf(key, StringComparison.CurrentCultureIgnoreCase);
            if (foundIndex > -1)
            {
                applicableToSpan = currentSnapshot.CreateTrackingSpan
                    (
                    querySpan.Start.Add(foundIndex).Position, 9, SpanTrackingMode.EdgeInclusive
                    );
    
                string value;
                m_dictionary.TryGetValue(key, out value);
                if (value != null)
                    qiContent.Add(value);
                else
                    qiContent.Add("");
    
                return;
            }
        }
    
        applicableToSpan = null;
    }
    
  7. 您尚必須實作 dispose () 方法,因為IQuickInfoSource實作IDisposable

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

實作 QuickInfo 來源提供者

QuickInfo 來源提供者負責主要是為 MEF 的元件組件匯出本身,並具現化 QuickInfo 的來源。 因為它是將 MEF 元件組件時,它可以匯入其他的 MEF 元件組件。

若要實作 QuickInfo 的原始檔提供者

  1. 宣告名為 QuickInfo 來源提供者TestQuickInfoSourceProvider實作IQuickInfoSourceProvider,並將其與匯出NameAttribute的 「 工具提示 QuickInfo 來源 」 OrderAttribute的早於 ="default",和ContentTypeAttribute的 「 文字 」。

    <Export(GetType(IQuickInfoSourceProvider))> _
    <Name("ToolTip QuickInfo Source")> _
    <Order(Before:=" Default Quick Info Presenter")> _
    <ContentType("text")> _
    Friend Class TestQuickInfoSourceProvider
        Implements IQuickInfoSourceProvider
    
    [Export(typeof(IQuickInfoSourceProvider))]
    [Name("ToolTip QuickInfo Source")]
    [Order(Before = "Default Quick Info Presenter")]
    [ContentType("text")]
    internal class TestQuickInfoSourceProvider : IQuickInfoSourceProvider
    
  2. 匯入兩個編輯器服務, ITextStructureNavigatorSelectorServiceITextBufferFactoryService,為屬性, TestQuickInfoSourceProvider

    Private _NavigatorService As ITextStructureNavigatorSelectorService
    <Import()> _
    Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
        Get 
            Return _NavigatorService
        End Get 
        Set(ByVal value As ITextStructureNavigatorSelectorService)
            _NavigatorService = value
        End Set 
    End Property 
    
    Private _TextBufferFactoryService As ITextBufferFactoryService
    <Import()> _
    Friend Property TextBufferFactoryService() As ITextBufferFactoryService
        Get 
            Return _TextBufferFactoryService
        End Get 
        Set(ByVal value As ITextBufferFactoryService)
            _TextBufferFactoryService = value
        End Set 
    End Property
    
    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
    [Import]
    internal ITextBufferFactoryService TextBufferFactoryService { get; set; }
    
  3. 實作TryCreateQuickInfoSource傳回新的TestQuickInfoSource

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

實作 QuickInfo 控制站

QuickInfo 控制站會決定何時應該顯示 QuickInfo。 在這個範例中,當指標位於其中一個方法名稱對應某個字上方時,會顯示 QuickInfo。 QuickInfo 控制站會實作滑鼠停留事件處理常式,會觸發 QuickInfo 工作階段。

若要實作 QuickInfo 控制站

  1. 宣告一個類別,實作IIntellisenseController,並命名為 TestQuickInfoController。

    Friend Class TestQuickInfoController
        Implements IIntellisenseController
    
    internal class TestQuickInfoController : IIntellisenseController
    
  2. 加入私用欄位的文字] 檢視中,表示文字檢視、 QuickInfo 的工作階段和 QuickInfo 控制站提供者中的文字緩衝區。

    Private m_textView As ITextView
    Private m_subjectBuffers As IList(Of ITextBuffer)
    Private m_provider As TestQuickInfoControllerProvider
    Private m_session As IQuickInfoSession
    
    private ITextView m_textView;
    private IList<ITextBuffer> m_subjectBuffers;
    private TestQuickInfoControllerProvider m_provider;
    private IQuickInfoSession m_session;
    
  3. 加入建構函式所設定的欄位,並將滑鼠停留事件處理常式。

    Friend Sub New(ByVal textView As ITextView, ByVal subjectBuffers As IList(Of ITextBuffer), ByVal provider As TestQuickInfoControllerProvider)
        m_textView = textView
        m_subjectBuffers = subjectBuffers
        m_provider = provider
    
        AddHandler m_textView.MouseHover, AddressOf Me.OnTextViewMouseHover
    End Sub
    
    internal TestQuickInfoController(ITextView textView, IList<ITextBuffer> subjectBuffers, TestQuickInfoControllerProvider provider)
    {
        m_textView = textView;
        m_subjectBuffers = subjectBuffers;
        m_provider = provider;
    
        m_textView.MouseHover += this.OnTextViewMouseHover;
    }
    
  4. 將滑鼠停留事件處理常式會觸發 QuickInfo 工作階段。

    Private Sub OnTextViewMouseHover(ByVal sender As Object, ByVal e As MouseHoverEventArgs)
        'find the mouse position by mapping down to the subject buffer 
        Dim point As System.Nullable(Of SnapshotPoint) = m_textView.BufferGraph.MapDownToFirstMatch(New SnapshotPoint(m_textView.TextSnapshot, e.Position), PointTrackingMode.Positive, Function(snapshot) m_subjectBuffers.Contains(snapshot.TextBuffer), PositionAffinity.Predecessor)
    
        If point IsNot Nothing Then 
            Dim triggerPoint As ITrackingPoint = point.Value.Snapshot.CreateTrackingPoint(point.Value.Position, PointTrackingMode.Positive)
    
            If Not m_provider.QuickInfoBroker.IsQuickInfoActive(m_textView) Then
                m_session = m_provider.QuickInfoBroker.TriggerQuickInfo(m_textView, triggerPoint, True)
            End If 
        End If 
    End Sub
    
    private void OnTextViewMouseHover(object sender, MouseHoverEventArgs e)
    {
        //find the mouse position by mapping down to the subject buffer
        SnapshotPoint? point = m_textView.BufferGraph.MapDownToFirstMatch
             (new SnapshotPoint(m_textView.TextSnapshot, e.Position),
            PointTrackingMode.Positive,
            snapshot => m_subjectBuffers.Contains(snapshot.TextBuffer),
            PositionAffinity.Predecessor);
    
        if (point != null)
        {
            ITrackingPoint triggerPoint = point.Value.Snapshot.CreateTrackingPoint(point.Value.Position,
            PointTrackingMode.Positive);
    
            if (!m_provider.QuickInfoBroker.IsQuickInfoActive(m_textView))
            {
                m_session = m_provider.QuickInfoBroker.TriggerQuickInfo(m_textView, triggerPoint, true);
            }
        }
    }
    
  5. 實作Detach方法,它會控制站中斷文字檢視時,移除滑鼠停留事件處理常式。

    Public Sub Detach(ByVal textView As ITextView) Implements IIntellisenseController.Detach
        If m_textView Is textView Then 
            AddHandler m_textView.MouseHover, AddressOf Me.OnTextViewMouseHover
            m_textView = Nothing 
        End If 
    End Sub
    
    public void Detach(ITextView textView)
    {
        if (m_textView == textView)
        {
            m_textView.MouseHover -= this.OnTextViewMouseHover;
            m_textView = null;
        }
    }
    
  6. 實作ConnectSubjectBuffer方法,並DisconnectSubjectBuffer為空的方法,這個範例中的方法。

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

實作 QuickInfo 控制站提供者

QuickInfo 控制站的提供者負責主要是為 MEF 的元件組件匯出本身,並具現化 QuickInfo 控制站。 因為它是將 MEF 元件組件時,它可以匯入其他的 MEF 元件組件。

若要實作 QuickInfo 的控制站提供者

  1. 宣告類別,名為TestQuickInfoControllerProvider實作IIntellisenseControllerProvider,並將其與匯出NameAttribute的 「 工具提示 QuickInfo 控制站 」 和ContentTypeAttribute的 「 文字 」:

    <Export(GetType(IIntellisenseControllerProvider))> _
    <Name("ToolTip QuickInfo Controller")> _
    <ContentType("text")> _
    Friend Class TestQuickInfoControllerProvider
        Implements IIntellisenseControllerProvider
    
    [Export(typeof(IIntellisenseControllerProvider))]
    [Name("ToolTip QuickInfo Controller")]
    [ContentType("text")]
    internal class TestQuickInfoControllerProvider : IIntellisenseControllerProvider
    
  2. 匯入IQuickInfoBroker做為屬性。

    Private _QuickInfoBroker As IQuickInfoBroker
    <Import()> _
    Friend Property QuickInfoBroker() As IQuickInfoBroker
        Get 
            Return _QuickInfoBroker
        End Get 
        Set(ByVal value As IQuickInfoBroker)
            _QuickInfoBroker = value
        End Set 
    End Property
    
    [Import]
    internal IQuickInfoBroker QuickInfoBroker { get; set; }
    
  3. 實作TryCreateIntellisenseController QuickInfo 控制器具現化的方法。

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

建置和測試程式碼

若要測試這段程式碼,建置 QuickInfoTest 方案並執行它實驗性的執行個體中。

若要建置和測試 QuickInfoTest 的解決方案

  1. 建置方案。

  2. 當您執行此專案在偵錯工具時,會執行個體化 Visual Studio 的第二個執行個體。

  3. 建立文字檔並輸入一些文字,包括單字"新增"和"減去"。

  4. 請將指標置於其中一個 「 新增 」 項目。 簽章和描述add方法應該會顯示。

請參閱

工作

逐步解說: 連結至檔案的副檔名的內容類型