Partager via


Procédure pas - à - pas : afficher la saisie semi-automatique des instructions

Vous pouvez implémenter les fonctionnalités basées sur un langage telles que la saisie semi-automatique des instructions en définissant les identificateurs pour lesquels vous souhaitez fournir l'achèvement, puis en levant une session de saisie semi-automatique. Vous pouvez définir la saisie semi-automatique des instructions dans le contexte d'un service de langage, ou vous pouvez définir votre propre extension de nom de fichier et type de contenu, et achèvement d'affichage uniquement pour ce type, ou vous pouvez déclencher l'achèvement d'un type de contenu existant (tel que « texte brut »). Cette procédure pas - à - pas montre comment déclencher la saisie semi-automatique des instructions pour le type de contenu « texte brut », qui est le type de contenu de fichiers texte. Le type de contenu de « texte » est l'ancêtre de tous les autres types de contenu, notamment le code et les fichiers XML.

La saisie semi-automatique des instructions est généralement levée en tapant certains caractères, par exemple, en tapant le début d'un identificateur par exemple « à ». Il est généralement fermée en appuyant sur la touche ESPACE, TAB, ou ENTRÉE pour valider une sélection. Les fonctionnalités Intellisense qui sont déclenchées en tapant un caractère peuvent être implémentées à l'aide d'un gestionnaire de commandes pour les séquences de touches (l'interface d' IOleCommandTarget ) et un fournisseur de gestionnaire qui implémente l'interface d' IVsTextViewCreationListener . Pour créer la source d'achèvement, qui est la liste des identificateurs qui participent à la fin, implémentez l'interface d' ICompletionSource et un fournisseur de sources d'achèvement (l'interface d' ICompletionSourceProvider ). Les fournisseurs sont les éléments gérées (MEF) managed extensibility framework, et sont chargées d'exporter la source et les classes de contrôleur et d'importer des services et des courtiers, par exemple, ITextStructureNavigatorSelectorService, qui vous permet de naviguer dans la mémoire tampon de texte, et ICompletionBroker, qui déclenche la session de saisie semi-automatique.

Cette procédure pas - à - pas indique comment implémenter la saisie semi-automatique des instructions pour un jeu codé en dur des identificateurs. Dans les implémentations intégrales, le service de langage et de la documentation de langage sont chargées de fournir ce contenu.

Composants requis

Pour exécuter cette procédure, vous devez installer Kit de développement logiciel Visual Studio 2010.

Notes

Pour plus d'informations sur le kit de développement Visual Studio, consultez Étendre la présentation de Visual Studio.Pour savoir comment télécharger le kit de développement Visual Studio, consultez Visual Studio Extensibility Developer Center sur le site Web MSDN.

Créer un projet MEF

Pour créer un projet MEF

  1. Créez un projet de classifieur d'éditeur. nommez la solution CompletionTest.

  2. Ouvrez le fichier source.extension.vsixmanifest dans l'éditeur de manifeste VSIX.

  3. Assurez -vous que le titre de Contenu contient un type de contenu de Composant MEF et que Path est défini à CompletionTest.dll.

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

  5. Ajoutez les références suivantes au projet et vérifiez que CopyLocal est défini à 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. supprimez les fichiers de classe existants.

implémenter la source d'achèvement

La source d'achèvement est chargé de collecter l'ensemble d'identificateurs et d'ajouter du contenu à la fenêtre d'achèvement lorsqu'un utilisateur un déclencheur d'achèvement, tel que les premières lettres d'un identificateur. Dans cet exemple, les identificateurs et leurs descriptions sont codés en dur dans la méthode d'AugmentCompletionSession . Dans la plupart des applications réelles, vous devez utiliser l'analyseur de votre langage pour obtenir les jetons pour remplir la liste de saisie semi-automatique.

pour implémenter la source d'achèvement

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

  2. Ajoutez les importations ci-après.

    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. Modifiez la déclaration de classe de TestCompletionSource afin qu'il implémente ICompletionSource.

    Friend Class TestCompletionSource
        Implements ICompletionSource
    
    internal class TestCompletionSource : ICompletionSource
    
  4. Ajoutez des champs privés pour le fournisseur de sources, la mémoire tampon de texte, et une liste d'objets d' Completion (qui correspondent aux identificateurs qui participeront à la session de saisie semi-automatique).

    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. Ajoutez un constructeur qui définit le fournisseur de sources et la mémoire tampon. La classe de TestCompletionSourceProvider est définie dans les étapes ultérieures.

    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. Implémentez la méthode d' AugmentCompletionSession en ajoutant un jeu de saisies semi-automatiques qui contient les saisies semi-automatiques que vous souhaitez fournir dans le contexte. Chaque jeu de saisies semi-automatiques contient un jeu de saisies semi-automatiques d' Completion , et correspond à un onglet de la fenêtre d'achèvement. (Dans les projets Visual Basic, les onglets de la fenêtre d'achèvement sont nommés Commun et Tout.) la méthode de FindTokenSpanAtPosition est définie dans l'étape suivante.

    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. la méthode suivante est utilisée pour rechercher le mot actuel de la position du signe insertion.

    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. Implémentez la méthode de Dispose() :

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

Implémenter le fournisseur de sources d'achèvement

Le fournisseur de sources d'achèvement est la composant MEF qui instancie la source d'achèvement.

Pour implémenter le fournisseur de sources d'achèvement

  1. ajoutez une classe nommée TestCompletionSourceProvider qui implémente ICompletionSourceProvider. Exportez cette classe avec ContentTypeAttribute « texte brut » et NameAttribute de « achèvement de test ».

    <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. Importez ITextStructureNavigatorSelectorService, qui doit être utilisé pour rechercher le mot actuel de la source d'achèvement.

    <Import()>
    Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
    
    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
  3. Implémentez la méthode d' TryCreateCompletionSource pour instancier la source d'achèvement.

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

Implémenter le fournisseur du gestionnaire de commandes d'achèvement

Le fournisseur du gestionnaire de commandes d'achèvement est dérivé d' IVsTextViewCreationListener, qui écoute un événement de création d'affichage de texte et convertit la vue d' IVsTextView (qui permet la commande d'être ajouté à la chaîne de commande du shell Visual Studio) à ITextView. Étant donné que cette classe est une exportation MEF, vous pouvez également l'utiliser pour importer les services qui sont nécessaires par le gestionnaire de commandes lui-même.

Pour implémenter le fournisseur du gestionnaire de commandes d'achèvement

  1. ajoutez un fichier nommé TestCompletionCommandHandler.

  2. Ajoutez les instructions using suivantes.

    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. ajoutez une classe nommée TestCompletionHandlerProvider qui implémente IVsTextViewCreationListener. Exportez cette classe avec NameAttribute « du gestionnaire de jeton d'achèvement », ContentTypeAttribute « texte brut », et TextViewRoleAttribute d' 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. Importez IVsEditorAdaptersFactoryService, qui vous permet de convertir d' IVsTextView à ITextView, à ICompletionBroker, et à SVsServiceProvider, qui vous permet aux services standard de Visual Studio d'accès.

    <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. Implémentez la méthode d' VsTextViewCreated pour instancier le gestionnaire de commandes.

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

Implémentation du gestionnaire de commandes d'achèvement

Étant donné que la saisie semi-automatique des instructions est déclenchée par des séquences de touches, vous devez implémenter l'interface d' IOleCommandTarget afin de recevoir et traiter les séquences de touches qui déclenchent, valider, et écartent la session de saisie semi-automatique.

pour implémenter le gestionnaire de commandes d'achèvement

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

    Friend Class TestCompletionCommandHandler
        Implements IOleCommandTarget
    
    internal class TestCompletionCommandHandler : IOleCommandTarget
    
  2. Ajoutez des champs privés pour le gestionnaire de commandes suivant (à ce que vous passez la commande), l'affichage de texte, le fournisseur du gestionnaire de commandes (ce qui vous permet à divers services d'accès), et une session de saisie semi-automatique.

    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. ajoutez un constructeur qui définit l'affichage de texte et les champs de fournisseur, et ajoutez la commande à la chaîne de commande.

    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. Implémentez la méthode d' QueryStatus en passant la commande le long.

    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. Implémentez la méthode Exec. Lorsque cette méthode accepte une séquence de touches, elle doit effectuer l'une des causes suivantes :

    • Autorisez le caractère à écrire dans la mémoire tampon, puis déclenchez ou filtrer l'achèvement (les caractères d'impression font).

    • Validez l'achèvement, mais n'autorisez pas le caractère à écrire dans la mémoire tampon (l'espace blanc, TAB, et l'utilisateur le faire lorsqu'une session de saisie semi-automatique est affichée).

    • Autorisez l'ordre d'être passé dans le code suivant au gestionnaire (toutes les autres commandes).

    Étant donné que cette méthode peut restituer l'interface utilisateur, vous devez vérifier qu'il n'est pas appelé dans un contexte d'automation en appelant 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. Le code suivant est une méthode privée qui déclenche la session de saisie semi-automatique.

    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. Le code suivant est une méthode privée qui annule un abonnement à l'événement d' Dismissed .

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

Génération et test de code

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

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

  1. Générez la solution.

  2. Lorsque vous exécutez ce projet dans le débogueur, une deuxième instance de Visual Studio est instanciée.

  3. Créez un fichier texte et tapez du texte qui inclut le mot « add ».

  4. Lorsque vous tapez d'abord « a » puis « d », une liste qui contient « ajout » et « adaptation » doit s'afficher. Notez que l'addition est sélectionné. Lorsque vous tapez un autre « d », cette liste doit contenir uniquement « ajout », qui est maintenant sélectionné. Vous pouvez valider « ajout de » en appuyant sur la touche ESPACE, TAB, ou SUR ENTRÉE, ou ferme la liste en tapant échap ou tout autre caractère.

Voir aussi

Tâches

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