Compartilhar via


Passo a passo: Exibindo a conclusão da instrução

Você pode implementar os recursos baseados em linguagem, como a conclusão da instrução definindo os identificadores para o qual você deseja fornecer a conclusão e, em seguida, disparar uma sessão de conclusão. Você pode definir a conclusão da instrução no contexto de um serviço de idioma, você pode definir sua própria extensão de nome de arquivo e o tipo de conteúdo e exibir conclusão apenas desse tipo ou você pode acionar a conclusão de um tipo de conteúdo existente (como "texto sem formatação"). Esta explicação passo a passo mostra como acionar a conclusão da instrução para o tipo de conteúdo "texto sem formatação", que é o tipo de conteúdo de arquivos de texto. O tipo de conteúdo "texto" é o ancestral de todos os outros tipos de conteúdo, incluindo o código e arquivos XML.

Conclusão da instrução é normalmente acionado digitando certos caracteres, por exemplo, digitando o início de um identificador, como "using". Normalmente, ele é descartado, pressionando a barra de espaços, TAB ou ENTER para confirmar uma seleção. Recursos de IntelliSense que são acionados, digitando um caractere podem ser implementados usando um manipulador de comandos para os pressionamentos de teclas (o IOleCommandTarget interface) e um provedor de manipulador que implementa o IVsTextViewCreationListener interface. Para criar a fonte de conclusão, que é a lista de identificadores que participam da conclusão, implementar a ICompletionSource interface e um provedor de origem de conclusão (o ICompletionSourceProvider interface). Os provedores são partes do componente Managed Extensibility Framework (MEF) e são responsáveis por classes de origem e o controlador de exportação e importação de serviços e agentes, por exemplo, o ITextStructureNavigatorSelectorService, que permite que você navegue no buffer de texto, e o ICompletionBroker, que dispara a sessão de conclusão.

Esta explicação passo a passo mostra como implementar a conclusão da instrução para um conjunto de literais de identificadores. Em implementações completas, o serviço de linguagem e a documentação da linguagem serão responsáveis por fornecer o conteúdo.

Pré-requisitos

Para concluir este passo a passo, você deve instalar o SDL do Visual Studio 2010.

Dica

Para obter mais informações sobre o SDK de Visual Studio, consulte Ampliando a visão geral de Visual Studio.Para descobrir como fazer o download do SDK do Visual Studio, consulte Visual Studio extensibilidade Developer Center no site do MSDN.

Criando um projeto MEF

Para criar um projeto MEF

  1. Crie um projeto do classificador de Editor. Nomeie a solução CompletionTest.

  2. Abra o arquivo de source.extension.vsixmanifest no Editor de VSIX de manifesto.

  3. Certifique-se de que o conteúdo título contém um MEF componente conteúdo de tipo e que o caminho for definido como CompletionTest.dll.

  4. Salve e feche o source.extension.vsixmanifest.

  5. Adicione as seguintes referências ao projeto e certifique-se de que CopyLocal for definido como false:

    Microsoft.VisualStudio.Editor

    Microsoft.VisualStudio.Language.IntelliSense

    Microsoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell.10.0

    Microsoft.VisualStudio.Shell.Immutable.10.0

    Microsoft.VisualStudio.TextManager.Interop

  6. Exclua os arquivos de classe existentes.

Implementando a origem de conclusão

A origem de conclusão é responsável por coletar o conjunto de identificadores e adicionando o conteúdo para a janela de conclusão, quando um usuário digita um disparador de conclusão, como, por exemplo, as primeiras letras de um identificador. Neste exemplo, os identificadores e suas descrições são codificados naAugmentCompletionSession método. A maioria dos usos do mundo real, você usaria o analisador da sua linguagem para obter tokens para preencher a lista de conclusão.

Para implementar a origem de conclusão

  1. Adicione um arquivo de classe e denomine- TestCompletionSource.

  2. Adicione as importações a seguintes.

    Imports System
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Text
    Imports System.ComponentModel.Composition
    Imports Microsoft.VisualStudio.Language.Intellisense
    Imports Microsoft.VisualStudio.Text
    Imports Microsoft.VisualStudio.Text.Operations
    Imports Microsoft.VisualStudio.Utilities
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel.Composition;
    using Microsoft.VisualStudio.Language.Intellisense;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Operations;
    using Microsoft.VisualStudio.Utilities;
    
  3. Modificar a declaração de classe para TestCompletionSource para que ele implementa ICompletionSource.

    Friend Class TestCompletionSource
        Implements ICompletionSource
    
    internal class TestCompletionSource : ICompletionSource
    
  4. Adicionar campos privados para o provedor de origem, o buffer de texto e uma lista de Completion objetos (que correspondem aos identificadores que participarão da sessão de conclusão).

    Private m_sourceProvider As TestCompletionSourceProvider
    Private m_textBuffer As ITextBuffer
    Private m_compList As List(Of Completion)
    
    private TestCompletionSourceProvider m_sourceProvider;
    private ITextBuffer m_textBuffer;
    private List<Completion> m_compList;
    
  5. Adicione um construtor que define o provedor de origem e o buffer. A classe TestCompletionSourceProvider é definida em etapas posteriores.

    Public Sub New(ByVal sourceProvider As TestCompletionSourceProvider, ByVal textBuffer As ITextBuffer)
        m_sourceProvider = sourceProvider
        m_textBuffer = textBuffer
    End Sub
    
    public TestCompletionSource(TestCompletionSourceProvider sourceProvider, ITextBuffer textBuffer)
    {
        m_sourceProvider = sourceProvider;
        m_textBuffer = textBuffer;
    }
    
  6. Implementar a AugmentCompletionSession método adicionando um conjunto de conclusão que contém as conclusões que você deseja fornecer no contexto. Cada conjunto de conclusão contém um conjunto de Completion conclusões e corresponde a uma guia da janela de conclusão. (Em projetos de Visual Basic, as guias da janela de conclusão são nomeadas Common e todos os.) O método FindTokenSpanAtPosition é definido na próxima etapa.

    Private Sub AugmentCompletionSession(ByVal session As ICompletionSession, ByVal completionSets As IList(Of CompletionSet)) Implements ICompletionSource.AugmentCompletionSession
        Dim strList As New List(Of String)()
        strList.Add("addition")
        strList.Add("adaptation")
        strList.Add("subtraction")
        strList.Add("summation")
    
        m_compList = New List(Of Completion)()
        For Each str As String In strList
            m_compList.Add(New Completion(str, str, str, Nothing, Nothing))
        Next str
    
        completionSets.Add(New CompletionSet(
            "Tokens",
            "Tokens",
            FindTokenSpanAtPosition(session.GetTriggerPoint(m_textBuffer),
                session),
            m_compList,
            Nothing))
    End Sub
    
    void ICompletionSource.AugmentCompletionSession(ICompletionSession session, IList<CompletionSet> completionSets)
    {
        List<string> strList = new List<string>();
        strList.Add("addition");
        strList.Add("adaptation");
        strList.Add("subtraction");
        strList.Add("summation");
        m_compList = new List<Completion>();
        foreach (string str in strList)
            m_compList.Add(new Completion(str, str, str, null, null));
    
        completionSets.Add(new CompletionSet(
            "Tokens",    //the non-localized title of the tab 
            "Tokens",    //the display title of the tab
            FindTokenSpanAtPosition(session.GetTriggerPoint(m_textBuffer),
                session),
            m_compList,
            null));
    }
    
  7. O seguinte método é usado para localizar a palavra atual a partir da posição do cursor.

    Private Function FindTokenSpanAtPosition(ByVal point As ITrackingPoint, ByVal session As ICompletionSession) As ITrackingSpan
        Dim currentPoint As SnapshotPoint = (session.TextView.Caret.Position.BufferPosition) - 1
        Dim navigator As ITextStructureNavigator = m_sourceProvider.NavigatorService.GetTextStructureNavigator(m_textBuffer)
        Dim extent As TextExtent = navigator.GetExtentOfWord(currentPoint)
        Return currentPoint.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive)
    End Function
    
    private ITrackingSpan FindTokenSpanAtPosition(ITrackingPoint point, ICompletionSession session)
    {
        SnapshotPoint currentPoint = (session.TextView.Caret.Position.BufferPosition) - 1;
        ITextStructureNavigator navigator = m_sourceProvider.NavigatorService.GetTextStructureNavigator(m_textBuffer);
        TextExtent extent = navigator.GetExtentOfWord(currentPoint);
        return currentPoint.Snapshot.CreateTrackingSpan(extent.Span, SpanTrackingMode.EdgeInclusive);
    }
    
  8. Implemente o método 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;
        }
    }
    

Implementando o provedor de origem de conclusão

O provedor de origem de conclusão é a parte do componente MEF que instancia a origem de conclusão.

Para implementar o provedor de origem de conclusão

  1. Adicionar uma classe chamada TestCompletionSourceProvider que implementa ICompletionSourceProvider. Exportar esta classe com um ContentTypeAttribute de "texto sem formatação" e um NameAttribute de "conclusão do teste".

    <Export(GetType(ICompletionSourceProvider)), ContentType("plaintext"), Name("token completion")>
    Friend Class TestCompletionSourceProvider
        Implements ICompletionSourceProvider
    
    [Export(typeof(ICompletionSourceProvider))]
    [ContentType("plaintext")]
    [Name("token completion")]
    internal class TestCompletionSourceProvider : ICompletionSourceProvider
    
  2. Importar um ITextStructureNavigatorSelectorService, que é para ser usado para localizar a palavra atual em uma fonte de conclusão.

    <Import()>
    Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
    
    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
  3. Implementar a TryCreateCompletionSource método para instanciar a origem de conclusão.

    Public Function TryCreateCompletionSource(ByVal textBuffer As ITextBuffer) As ICompletionSource Implements ICompletionSourceProvider.TryCreateCompletionSource
        Return New TestCompletionSource(Me, textBuffer)
    End Function
    
    public ICompletionSource TryCreateCompletionSource(ITextBuffer textBuffer)
    {
        return new TestCompletionSource(this, textBuffer);
    }
    

Implementando o provedor de manipulador de comando de conclusão

O provedor de manipulador de comando de conclusão é derivado de um IVsTextViewCreationListener, que escuta um evento de criação do modo de exibição de texto e converte o modo de exibição de um IVsTextView (que permite que o comando a ser adicionado à cadeia de comando do shell Visual Studio) para um ITextView. Como essa classe é uma exportação MEF, também pode usá-lo para importar os serviços que serão necessária para o manipulador de comandos de uma.

Para implementar o provedor de manipulador de comando de conclusão

  1. Adicione um arquivo chamado TestCompletionCommandHandler.

  2. Adicione o seguinte usando instruções.

    Imports System
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Text
    Imports System.ComponentModel.Composition
    Imports System.Runtime.InteropServices
    Imports Microsoft.VisualStudio
    Imports Microsoft.VisualStudio.Editor
    Imports Microsoft.VisualStudio.Language.Intellisense
    Imports Microsoft.VisualStudio.OLE.Interop
    Imports Microsoft.VisualStudio.Shell
    Imports Microsoft.VisualStudio.Text
    Imports Microsoft.VisualStudio.Text.Editor
    Imports Microsoft.VisualStudio.TextManager.Interop
    Imports Microsoft.VisualStudio.Utilities
    
    using System;
    using System.ComponentModel.Composition;
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Editor;
    using Microsoft.VisualStudio.Language.Intellisense;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio.Shell;
    using Microsoft.VisualStudio.Text;
    using Microsoft.VisualStudio.Text.Editor;
    using Microsoft.VisualStudio.TextManager.Interop;
    using Microsoft.VisualStudio.Utilities;
    
  3. Adicionar uma classe chamada TestCompletionHandlerProvider que implementa IVsTextViewCreationListener. Exportar esta classe com um NameAttribute do "manipulador de token de conclusão", um ContentTypeAttribute de "texto sem formatação" e um TextViewRoleAttribute de Editable.

    <Export(GetType(IVsTextViewCreationListener))>
    <Name("token completion handler")>
    <ContentType("plaintext")> <TextViewRole(PredefinedTextViewRoles.Editable)>
    Friend Class TestCompletionHandlerProvider
        Implements IVsTextViewCreationListener
    
    [Export(typeof(IVsTextViewCreationListener))]
    [Name("token completion handler")]
    [ContentType("plaintext")]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    internal class TestCompletionHandlerProvider : IVsTextViewCreationListener
    
  4. Importar a IVsEditorAdaptersFactoryService, que permite que você converte de um IVsTextView para um ITextView, um ICompletionBrokere um SVsServiceProvider, que permite que você acesse os serviços de Visual Studio padrão..

    <Import()>
    Friend AdapterService As IVsEditorAdaptersFactoryService = Nothing
    <Import()>
    Friend Property CompletionBroker() As ICompletionBroker
    <Import()>
    Friend Property ServiceProvider() As SVsServiceProvider
    
    [Import]
    internal IVsEditorAdaptersFactoryService AdapterService = null;
    [Import]
    internal ICompletionBroker CompletionBroker { get; set; }
    [Import]
    internal SVsServiceProvider ServiceProvider { get; set; }
    
  5. Implementar a VsTextViewCreated método para instanciar o manipulador de comandos.

    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 
    
        Dim createCommandHandler As Func(Of TestCompletionCommandHandler) = Function() New TestCompletionCommandHandler(textViewAdapter, textView, Me)
        textView.Properties.GetOrCreateSingletonProperty(createCommandHandler)
    End Sub
    
    public void VsTextViewCreated(IVsTextView textViewAdapter)
    {
        ITextView textView = AdapterService.GetWpfTextView(textViewAdapter);
        if (textView == null)
            return;
    
        Func<TestCompletionCommandHandler> createCommandHandler = delegate() { return new TestCompletionCommandHandler(textViewAdapter, textView, this); };
        textView.Properties.GetOrCreateSingletonProperty(createCommandHandler);
    }
    

Implementando o manipulador de comandos de conclusão

Porque a conclusão da instrução é disparado por pressionamentos de teclas, você deve implementar a IOleCommandTarget interface para receber e processar os pressionamentos de teclas que acionam, commit e descartar a sessão de conclusão.

Para implementar o manipulador de comandos de conclusão

  1. Adicionar uma classe chamada TestCompletionCommandHandler que implementa IOleCommandTarget.

    Friend Class TestCompletionCommandHandler
        Implements IOleCommandTarget
    
    internal class TestCompletionCommandHandler : IOleCommandTarget
    
  2. Adicionar campos privados para o próximo manipulador de comandos (para que você passar o comando), o modo de exibição de texto, o provedor do manipulador de comando (que permite acesso a vários serviços) e uma sessão de conclusão.

    Private m_nextCommandHandler As IOleCommandTarget
    Private m_textView As ITextView
    Private m_provider As TestCompletionHandlerProvider
    Private m_session As ICompletionSession
    
    private IOleCommandTarget m_nextCommandHandler;
    private ITextView m_textView;
    private TestCompletionHandlerProvider m_provider;
    private ICompletionSession m_session;
    
  3. Adicione um construtor que define o modo de exibição de texto e os campos de provedor e adiciona o comando para a cadeia de comando.

    Friend Sub New(ByVal textViewAdapter As IVsTextView, ByVal textView As ITextView, ByVal provider As TestCompletionHandlerProvider)
        Me.m_textView = textView
        Me.m_provider = provider
    
        'add the command to the command chain
        textViewAdapter.AddCommandFilter(Me, m_nextCommandHandler)
    End Sub
    
    internal TestCompletionCommandHandler(IVsTextView textViewAdapter, ITextView textView, TestCompletionHandlerProvider provider)
    {
        this.m_textView = textView;
        this.m_provider = provider;
    
        //add the command to the command chain
        textViewAdapter.AddCommandFilter(this, out m_nextCommandHandler);
    }
    
  4. Implementar a QueryStatus método passando o comando junto.

    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);
    }
    
  5. Implemente o método Exec. Quando esse método recebe um pressionamento de tecla, ele deve fazer uma dessas opções:

    • Permitir que o caractere a ser gravada no buffer e, em seguida, acionar ou filtrar conclusão (imprimindo caracteres fazer isso).

    • Confirmar a conclusão, mas não permitir que o caractere a ser gravada no buffer (espaço em branco, TAB e ENTER para fazer isso, quando uma sessão de conclusão é exibida).

    • Permitir que o comando para ser passados para o próximo manipulador (todos os outros comandos).

    Desde que esse método pode exibir a interface do usuário, você deve verificar que ele não é chamado em um contexto de automação chamando IsInAutomationFunction.

    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
        If VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider) Then 
            Return m_nextCommandHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut)
        End If 
        'make a copy of this so we can look at it after forwarding some commands 
        Dim commandID As UInteger = nCmdID
        Dim typedChar As Char = Char.MinValue
        'make sure the input is a char before getting it 
        If pguidCmdGroup = VSConstants.VSStd2K AndAlso nCmdID = CUInt(VSConstants.VSStd2KCmdID.TYPECHAR) Then
            typedChar = CChar(ChrW(CUShort(Marshal.GetObjectForNativeVariant(pvaIn))))
        End If 
    
        'check for a commit character 
        If nCmdID = CUInt(VSConstants.VSStd2KCmdID.RETURN) OrElse nCmdID = CUInt(VSConstants.VSStd2KCmdID.TAB) OrElse (Char.IsWhiteSpace(typedChar) OrElse Char.IsPunctuation(typedChar)) Then 
            'check for a a selection 
            If m_session IsNot Nothing AndAlso (Not m_session.IsDismissed) Then 
                'if the selection is fully selected, commit the current session 
                If m_session.SelectedCompletionSet.SelectionStatus.IsSelected Then
                    m_session.Commit()
                    'also, don't add the character to the buffer 
                    Return VSConstants.S_OK
                Else 
                    'if there is no selection, dismiss the session
                    m_session.Dismiss()
                End If 
            End If 
        End If 
    
        'pass along the command so the char is added to the buffer 
        Dim retVal As Integer = m_nextCommandHandler.Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut)
        Dim handled As Boolean = False 
        If (Not typedChar.Equals(Char.MinValue)) AndAlso Char.IsLetterOrDigit(typedChar) Then 
            If m_session Is Nothing OrElse m_session.IsDismissed Then ' If there is no active session, bring up completion
                Me.TriggerCompletion()
                m_session.Filter()
            Else 'the completion session is already active, so just filter
                m_session.Filter()
            End If
            handled = True 
        ElseIf commandID = CUInt(VSConstants.VSStd2KCmdID.BACKSPACE) OrElse commandID = CUInt(VSConstants.VSStd2KCmdID.DELETE) Then 'redo the filter if there is a deletion
            If m_session IsNot Nothing AndAlso (Not m_session.IsDismissed) Then
                m_session.Filter()
            End If
            handled = True 
        End If 
        If handled Then 
            Return VSConstants.S_OK
        End If 
        Return retVal
    End Function
    
    public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
    {
        if (VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider))
        {
            return m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
        }
        //make a copy of this so we can look at it after forwarding some commands 
        uint commandID = nCmdID;
        char typedChar = char.MinValue;
        //make sure the input is a char before getting it 
        if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
        {
            typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
        }
    
        //check for a commit character 
        if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN
            || nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB
            || (char.IsWhiteSpace(typedChar) || char.IsPunctuation(typedChar)))
        {
            //check for a a selection 
            if (m_session != null && !m_session.IsDismissed)
            {
                //if the selection is fully selected, commit the current session 
                if (m_session.SelectedCompletionSet.SelectionStatus.IsSelected)
                {
                    m_session.Commit();
                    //also, don't add the character to the buffer 
                    return VSConstants.S_OK;
                }
                else
                {
                    //if there is no selection, dismiss the session
                    m_session.Dismiss();
                }
            }
        }
    
        //pass along the command so the char is added to the buffer 
        int retVal = m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
        bool handled = false;
        if (!typedChar.Equals(char.MinValue) && char.IsLetterOrDigit(typedChar))
        {
            if (m_session == null || m_session.IsDismissed) // If there is no active session, bring up completion
            {
                this.TriggerCompletion();
                m_session.Filter();
            }
            else     //the completion session is already active, so just filter
            {
                m_session.Filter();
            }
            handled = true;
        }
        else if (commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE   //redo the filter if there is a deletion
            || commandID == (uint)VSConstants.VSStd2KCmdID.DELETE)
        {
            if (m_session != null && !m_session.IsDismissed)
                m_session.Filter();
            handled = true;
        }
        if (handled) return VSConstants.S_OK;
        return retVal;
    }
    
  6. O código a seguir é um método particular que dispara a sessão de conclusão.

    Private Function TriggerCompletion() As Boolean 
        'the caret must be in a non-projection location  
        Dim caretPoint As SnapshotPoint? = m_textView.Caret.Position.Point.GetPoint(Function(textBuffer) ((Not textBuffer.ContentType.IsOfType("projection"))), PositionAffinity.Predecessor)
        If Not caretPoint.HasValue Then 
            Return False 
        End If
    
        m_session = m_provider.CompletionBroker.CreateCompletionSession(m_textView, caretPoint.Value.Snapshot.CreateTrackingPoint(caretPoint.Value.Position, PointTrackingMode.Positive), True)
    
        'subscribe to the Dismissed event on the session  
        AddHandler m_session.Dismissed, AddressOf OnSessionDismissed
        m_session.Start()
    
        Return True 
    End Function
    
    private bool TriggerCompletion()
    {
        //the caret must be in a non-projection location 
        SnapshotPoint? caretPoint =
        m_textView.Caret.Position.Point.GetPoint(
        textBuffer => (!textBuffer.ContentType.IsOfType("projection")), PositionAffinity.Predecessor);
        if (!caretPoint.HasValue)
        {
            return false;
        }
    
        m_session = m_provider.CompletionBroker.CreateCompletionSession
     (m_textView,
            caretPoint.Value.Snapshot.CreateTrackingPoint(caretPoint.Value.Position, PointTrackingMode.Positive),
            true);
    
        //subscribe to the Dismissed event on the session 
        m_session.Dismissed += this.OnSessionDismissed;
        m_session.Start();
    
        return true;
    }
    
  7. O código a seguir é um método particular que cancela a inscrição da Dismissed evento.

    Private Sub OnSessionDismissed(ByVal sender As Object, ByVal e As EventArgs)
        RemoveHandler m_session.Dismissed, AddressOf OnSessionDismissed
        m_session = Nothing 
    End Sub
    
    private void OnSessionDismissed(object sender, EventArgs e)
    {
        m_session.Dismissed -= this.OnSessionDismissed;
        m_session = null;
    }
    

Criar e testar o código

Para testar esse código, crie a solução de CompletionTest e execute-o na instância experimental.

Para criar e testar a solução de CompletionTest

  1. Crie a solução.

  2. Ao executar este projeto no depurador, uma segunda instância do Visual Studio é instanciada.

  3. Crie um arquivo de texto e digite algum texto que inclui a palavra "Adicionar".

  4. Conforme você digita pela primeira vez "a" e, em seguida, "d", uma lista que contém "inclusão" e "adaptação" deve ser exibida. Observe que a adição é selecionada. Quando você digita outro "d", a lista deve conter somente "inclusão", que agora está selecionada. Você pode confirmar o "inclusão" pressionando a barra de espaços, TAB ou ENTER, ou descartar a lista digitando ESC ou qualquer outro caractere.

Consulte também

Tarefas

Passo a passo: Vinculação a um tipo de conteúdo a uma extensão de nome de arquivo