Procédure pas à pas : Affichage de saisie semi-automatique des instructionsWalkthrough: Displaying Statement Completion

Vous pouvez implémenter basée sur le langage de saisie semi-automatique des instructions en définissant les identificateurs pour lequel vous souhaitez fournir la saisie semi-automatique et de déclenchement puis d’une session de saisie semi-automatique.You can implement language-based statement completion by defining the identifiers for which you want to provide completion and then triggering a completion session. Vous pouvez définir la saisie semi-automatique des instructions dans le contexte d’un service de langage, définissez votre propre extension de nom de fichier et le type de contenu et ensuite afficher la saisie semi-automatique pour uniquement ce type, ou vous pouvez déclencher la saisie semi-automatique pour un type de contenu existant, par exemple, « texte en clair ».You can define statement completion in the context of a language service, define your own file name extension and content type and then display completion for just that type, or you can trigger completion for an existing content type—for example, "plaintext". Cette procédure pas à pas montre comment déclencher la saisie semi-automatique des instructions pour le type de contenu « texte en clair », qui est le type de contenu des fichiers texte.This walkthrough shows how to trigger statement completion for the "plaintext" content type, which is the content type of text files. Le type de contenu « text » est l’ancêtre de tous les autres types de contenu, y compris le code et les fichiers XML.The "text" content type is the ancestor of all other content types, including code and XML files.

Saisie semi-automatique des instructions sont généralement déclenchée en tapant certains caractères, par exemple, en tapant le début d’un identificateur, tel que « using ».Statement completion is typically triggered by typing certain characters—for example, by typing the beginning of an identifier such as "using". En règle générale, il disparaît en appuyant sur la touche espace, tabulation ou entrée pour valider une sélection.It is typically dismissed by pressing the Spacebar, Tab, or Enter key to commit a selection. Vous pouvez implémenter les fonctionnalités IntelliSense qui sont déclenchées par la saisie d’un caractère à l’aide d’un gestionnaire de commandes pour les séquences de touches (la IOleCommandTarget interface) et un fournisseur gestionnaire qui implémente le IVsTextViewCreationListener interface.You can implement the IntelliSense features that are triggered by typing a character by using a command handler for the keystrokes (the IOleCommandTarget interface) and a handler provider that implements the IVsTextViewCreationListener interface. Pour créer la source de saisie semi-automatique, qui est la liste des identificateurs qui participent de saisie semi-automatique, implémentez le ICompletionSource interface et un fournisseur de source de saisie semi-automatique (le ICompletionSourceProvider interface).To create the completion source, which is the list of identifiers that participate in completion, implement the ICompletionSource interface and a completion source provider (the ICompletionSourceProvider interface). Les fournisseurs sont des composants de Managed Extensibility Framework (MEF).The providers are Managed Extensibility Framework (MEF) component parts. Dont il est responsable de l’exportation les classes source et le contrôleur et l’importation des services et aux courtiers : par exemple, le ITextStructureNavigatorSelectorService, ce qui permet la navigation dans la mémoire tampon de texte et le ICompletionBroker, ce qui déclenche la session de saisie semi-automatique.They are responsible for exporting the source and controller classes and importing services and brokers—for example, the ITextStructureNavigatorSelectorService, which enables navigation in the text buffer, and the ICompletionBroker, which triggers the completion session.

Cette procédure pas à pas montre comment implémenter la saisie semi-automatique des instructions pour un jeu codé en dur des identificateurs.This walkthrough shows how to implement statement completion for a hard-coded set of identifiers. Dans les implémentations complètes, le service de langage et de la documentation de langage sont chargés de fournir ce contenu.In full implementations, the language service and the language documentation are responsible for providing that content.

PrérequisPrerequisites

À partir de Visual Studio 2015, vous n’installez pas le Kit de développement logiciel Visual Studio à partir du centre de téléchargement.Starting in Visual Studio 2015, you do not install the Visual Studio SDK from the download center. Il est inclus comme une fonctionnalité facultative dans le programme d’installation de Visual Studio.It is included as an optional feature in Visual Studio setup. Vous pouvez également installer le kit SDK VS ultérieurement.You can also install the VS SDK later on. Pour plus d’informations, consultez l’installation de Visual Studio SDK.For more information, see Installing the Visual Studio SDK.

Création d’un projet MEFCreating a MEF Project

Pour créer un projet MEFTo create a MEF project

  1. Créez un projet VSIX c#.Create a C# VSIX project. (Dans le nouveau projet boîte de dialogue, sélectionnez Visual c# / extensibilité, puis projet VSIX.) Nommez la solution CompletionTest.(In the New Project dialog, select Visual C# / Extensibility, then VSIX Project.) Name the solution CompletionTest.

  2. Ajouter un modèle d’élément classifieur d’éditeur pour le projet.Add an Editor Classifier item template to the project. Pour plus d’informations, consultez création d’une Extension avec un éditeur de modèle d’élément.For more information, see Creating an Extension with an Editor Item Template.

  3. Supprimez les fichiers de classe existants.Delete the existing class files.

  4. Ajoutez les références suivantes au projet et vous assurer que CopyLocal a la valeur false:Add the following references to the project and make sure that CopyLocal is set to false:

    Microsoft.VisualStudio.EditorMicrosoft.VisualStudio.Editor

    Microsoft.VisualStudio.Language.IntellisenseMicrosoft.VisualStudio.Language.Intellisense

    Assemblys Microsoft.VisualStudio.OLE.InteropMicrosoft.VisualStudio.OLE.Interop

    Microsoft.VisualStudio.Shell.14.0Microsoft.VisualStudio.Shell.14.0

    Microsoft.VisualStudio.Shell.Immutable.10.0Microsoft.VisualStudio.Shell.Immutable.10.0

    Microsoft.VisualStudio.TextManager.InteropMicrosoft.VisualStudio.TextManager.Interop

Implémentation de la Source de saisie semi-automatiqueImplementing the Completion Source

La source de saisie semi-automatique est responsable de la collecte de l’ensemble des identificateurs et ajouter le contenu de la fenêtre de saisie semi-automatique lorsqu’un utilisateur tape un déclencheur d’achèvement, telles que les premières lettres d’un identificateur.The completion source is responsible for collecting the set of identifiers and adding the content to the completion window when a user types a completion trigger, such as the first letters of an identifier. Dans cet exemple, les identificateurs et leurs descriptions sont codés en dur dans le AugmentCompletionSession (méthode).In this example, the identifiers and their descriptions are hard-coded in the AugmentCompletionSession method. Dans la plupart des utilisations du monde réel, vous utiliseriez Analyseur de votre langage pour obtenir les jetons pour remplir la liste de saisie semi-automatique.In most real-world uses, you would use your language's parser to get the tokens to populate the completion list.

Pour implémenter la source de saisie semi-automatiqueTo implement the completion source

  1. Ajoutez un fichier de classe et nommez-le TestCompletionSource.Add a class file and name it TestCompletionSource.

  2. Ajoutez ces importations :Add these imports:

    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;
    
    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
    
  3. Modifiez la déclaration de classe pour TestCompletionSource afin qu’elle implémente ICompletionSource:Modify the class declaration for TestCompletionSource so that it implements ICompletionSource:

    internal class TestCompletionSource : ICompletionSource
    
    Friend Class TestCompletionSource
        Implements ICompletionSource
    
  4. Ajoutez des champs privés pour le fournisseur de code source, la mémoire tampon de texte et une liste de Completion objets (qui correspondent aux identificateurs qui participeront à la session de saisie semi-automatique) :Add private fields for the source provider, the text buffer, and a list of Completion objects (which correspond to the identifiers that will participate in the completion session):

    private TestCompletionSourceProvider m_sourceProvider;
    private ITextBuffer m_textBuffer;
    private List<Completion> m_compList;
    
    Private m_sourceProvider As TestCompletionSourceProvider
    Private m_textBuffer As ITextBuffer
    Private m_compList As List(Of Completion)
    
  5. Ajoutez un constructeur qui définit le fournisseur de source et de la mémoire tampon.Add a constructor that sets the source provider and buffer. La TestCompletionSourceProvider classe est définie dans les étapes suivantes :The TestCompletionSourceProvider class is defined in later steps:

    public TestCompletionSource(TestCompletionSourceProvider sourceProvider, ITextBuffer textBuffer)
    {
        m_sourceProvider = sourceProvider;
        m_textBuffer = textBuffer;
    }
    
    Public Sub New(ByVal sourceProvider As TestCompletionSourceProvider, ByVal textBuffer As ITextBuffer)
        m_sourceProvider = sourceProvider
        m_textBuffer = textBuffer
    End Sub
    
  6. Implémentez la AugmentCompletionSession méthode en ajoutant un jeu de saisie semi-automatique qui contient les saisies semi-automatiques que vous souhaitez fournir dans le contexte.Implement the AugmentCompletionSession method by adding a completion set that contains the completions you want to provide in the context. Chaque jeu de saisie semi-automatique contient un jeu de Completion réussies et correspond à un onglet de la fenêtre de saisie semi-automatique.Each completion set contains a set of Completion completions, and corresponds to a tab of the completion window. (Dans les projets Visual Basic, les onglets de fenêtre de saisie semi-automatique sont nommés commune et tous les.) La méthode FindTokenSpanAtPosition est définie dans l’étape suivante.(In Visual Basic projects, the completion window tabs are named Common and All.) The FindTokenSpanAtPosition method is defined in the next step.

    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));
    }
    
    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
    
  7. La méthode suivante est utilisée pour rechercher le mot actuel à partir de la position du curseur :The following method is used to find the current word from the position of the cursor:

    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);
    }
    
    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
    
  8. Implémentez la Dispose() méthode :Implement the Dispose() method:

    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
    

Implémentation du fournisseur de Source de saisie semi-automatiqueImplementing the Completion Source Provider

Le fournisseur de source de saisie semi-automatique est la partie du composant MEF qui instancie la source de saisie semi-automatique.The completion source provider is the MEF component part that instantiates the completion source.

Pour implémenter le fournisseur de source de saisie semi-automatiqueTo implement the completion source provider

  1. Ajoutez une classe nommée TestCompletionSourceProvider qui implémente ICompletionSourceProvider.Add a class named TestCompletionSourceProvider that implements ICompletionSourceProvider. Exporter cette classe avec un ContentTypeAttribute de « texte en clair » et un NameAttribute de « exécution de test ».Export this class with a ContentTypeAttribute of "plaintext" and a NameAttribute of "test completion".

    [Export(typeof(ICompletionSourceProvider))]
    [ContentType("plaintext")]
    [Name("token completion")]
    internal class TestCompletionSourceProvider : ICompletionSourceProvider
    
    <Export(GetType(ICompletionSourceProvider)), ContentType("plaintext"), Name("token completion")>
    Friend Class TestCompletionSourceProvider
        Implements ICompletionSourceProvider
    
  2. Importer un ITextStructureNavigatorSelectorService, qui est utilisé pour rechercher le mot actuel dans la source de saisie semi-automatique.Import a ITextStructureNavigatorSelectorService, which is used to find the current word in the completion source.

    [Import]
    internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
    <Import()>
    Friend Property NavigatorService() As ITextStructureNavigatorSelectorService
    
  3. Implémentez la TryCreateCompletionSource méthode pour instancier la source de saisie semi-automatique.Implement the TryCreateCompletionSource method to instantiate the completion source.

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

Implémentation du fournisseur de gestionnaire de commande de finImplementing the Completion Command Handler Provider

Le fournisseur de gestionnaire de commandes de saisie semi-automatique est dérivé d’un IVsTextViewCreationListener, qui écoute un événement de création de vue de texte et convertit la vue à partir une IVsTextView, ce qui permet l’ajout de la commande à la chaîne de commande de l’interpréteur de commandes de Visual Studio : à un ITextView.The completion command handler provider is derived from a IVsTextViewCreationListener, which listens for a text view creation event and converts the view from an IVsTextView—which enables the addition of the command to the command chain of the Visual Studio shell—to an ITextView. Étant donné que cette classe est une exportation MEF, vous pouvez l’utiliser également pour importer les services requis par le Gestionnaire de commande proprement dit.Because this class is a MEF export, you can also use it to import the services that are required by the command handler itself.

Pour implémenter le fournisseur de gestionnaire de commande de finTo implement the completion command handler provider

  1. Ajoutez un fichier nommé TestCompletionCommandHandler.Add a file named TestCompletionCommandHandler.

  2. Ajoutez ces instructions using :Add these using statements:

    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;
    
    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
    
  3. Ajoutez une classe nommée TestCompletionHandlerProvider qui implémente IVsTextViewCreationListener.Add a class named TestCompletionHandlerProvider that implements IVsTextViewCreationListener. Exporter cette classe avec un NameAttribute du « Gestionnaire de jeton d’achèvement », un ContentTypeAttribute de « texte en clair » et un TextViewRoleAttribute de Editable.Export this class with a NameAttribute of "token completion handler", a ContentTypeAttribute of "plaintext", and a TextViewRoleAttribute of Editable.

    [Export(typeof(IVsTextViewCreationListener))]
    [Name("token completion handler")]
    [ContentType("plaintext")]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    internal class TestCompletionHandlerProvider : IVsTextViewCreationListener
    
    <Export(GetType(IVsTextViewCreationListener))>
    <Name("token completion handler")>
    <ContentType("plaintext")> <TextViewRole(PredefinedTextViewRoles.Editable)>
    Friend Class TestCompletionHandlerProvider
        Implements IVsTextViewCreationListener
    
  4. Importer le IVsEditorAdaptersFactoryService, qui permet la conversion d’un IVsTextView à un ITextView, un ICompletionBrokeret un SVsServiceProvider qui permet d’accéder aux services de Visual Studio standard.Import the IVsEditorAdaptersFactoryService, which enables conversion from a IVsTextView to a ITextView, a ICompletionBroker, and a SVsServiceProvider that enables access to standard Visual Studio services.

    [Import]
    internal IVsEditorAdaptersFactoryService AdapterService = null;
    [Import]
    internal ICompletionBroker CompletionBroker { get; set; }
    [Import]
    internal SVsServiceProvider ServiceProvider { get; set; }
    
    <Import()>
    Friend AdapterService As IVsEditorAdaptersFactoryService = Nothing
    <Import()>
    Friend Property CompletionBroker() As ICompletionBroker
    <Import()>
    Friend Property ServiceProvider() As SVsServiceProvider
    
  5. Implémentez la VsTextViewCreated méthode pour instancier le Gestionnaire de commandes.Implement the VsTextViewCreated method to instantiate the command handler.

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

Implémentation du Gestionnaire de commande de finImplementing the Completion Command Handler

Étant donné que la saisie semi-automatique des instructions sont déclenchée par les séquences de touches, vous devez implémenter la IOleCommandTarget interface pour recevoir et traiter les séquences de touches qui déclenchent, valident et fermer la session de saisie semi-automatique.Because statement completion is triggered by keystrokes, you must implement the IOleCommandTarget interface to receive and process the keystrokes that trigger, commit, and dismiss the completion session.

Pour implémenter le Gestionnaire de commandes de saisie semi-automatiqueTo implement the completion command handler

  1. Ajoutez une classe nommée TestCompletionCommandHandler qui implémente IOleCommandTarget:Add a class named TestCompletionCommandHandler that implements IOleCommandTarget:

    internal class TestCompletionCommandHandler : IOleCommandTarget
    
    Friend Class TestCompletionCommandHandler
        Implements IOleCommandTarget
    
  2. Ajoutez des champs privés pour le Gestionnaire de commandes suivant (à laquelle vous passez la commande), l’affichage de texte, le fournisseur du Gestionnaire de commandes (ce qui permet d’accéder à divers services) et une session de saisie semi-automatique :Add private fields for the next command handler (to which you pass the command), the text view, the command handler provider (which enables access to various services), and a completion session:

    private IOleCommandTarget m_nextCommandHandler;
    private ITextView m_textView;
    private TestCompletionHandlerProvider m_provider;
    private ICompletionSession m_session;
    
    Private m_nextCommandHandler As IOleCommandTarget
    Private m_textView As ITextView
    Private m_provider As TestCompletionHandlerProvider
    Private m_session As ICompletionSession
    
  3. Ajoutez un constructeur qui définit l’affichage de texte et les champs du fournisseur et ajoute la commande à la chaîne de commande :Add a constructor that sets the text view and the provider fields, and adds the command to the command chain:

    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);
    }
    
    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
    
  4. Implémentez la QueryStatus méthode en passant la commande le long de :Implement the QueryStatus method by passing the command along:

    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
    
  5. Implémentez la méthode Exec.Implement the Exec method. Lorsque cette méthode reçoit une séquence de touches, il effectuez l’une des opérations suivantes :When this method receives a keystroke, it must do one of these things:

    • Autoriser le caractère à écrire dans la mémoire tampon et puis déclenche ou filtrer la saisie semi-automatique.Allow the character to be written to the buffer, and then trigger or filter completion. (Les caractères imprimables cette opération).(Printing characters do this.)

    • Valider l’achèvement, mais n’autorisent pas le caractère à écrire dans la mémoire tampon.Commit the completion, but do not allow the character to be written to the buffer. (Un espace blanc, Tab et entrée cette opération lorsqu’une session de saisie semi-automatique est affichée).(Whitespace, Tab, and Enter do this when a completion session is displayed.)

    • Autoriser la commande pour être transmises au gestionnaire suivant.Allow the command to be passed on to the next handler. (Toutes les autres commandes.)(All other commands.)

      Étant donné que cette méthode peut afficher l’interface utilisateur, appelez IsInAutomationFunction pour vous assurer qu’elle n’est pas appelée dans un contexte d’automation :Because this method may display UI, call IsInAutomationFunction to make sure that it is not called in an automation context:

      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;
      }
      
      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
      
  6. Ce code est une méthode privée qui déclenche la session de saisie semi-automatique :This code is a private method that triggers the completion session:

    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;
    }
    
    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
    
  7. L’exemple suivant est une méthode privée qui annule l’abonnement à partir de la Dismissed événement :The next example is a private method that unsubscribes from the Dismissed event:

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

Création et test du codeBuilding and Testing the Code

Pour tester ce code, générez la solution CompletionTest et l’exécuter dans l’instance expérimentale.To test this code, build the CompletionTest solution and run it in the experimental instance.

Pour générer et tester la solution CompletionTestTo build and test the CompletionTest solution

  1. Générez la solution.Build the solution.

  2. Lorsque vous exécutez ce projet dans le débogueur, une deuxième instance de Visual Studio est instanciée.When you run this project in the debugger, a second instance of Visual Studio is instantiated.

  3. Créez un fichier texte et tapez du texte qui inclut le mot « ajouter ».Create a text file and type some text that includes the word "add".

  4. Lorsque vous tapez tout d’abord « a » et ensuite « d », une liste qui contient « addition » et « adaptation » doit être affichée.As you type first "a" and then "d", a list that contains "addition" and "adaptation" should be displayed. Notez que l’addition est sélectionnée.Notice that addition is selected. Lorsque vous tapez un autre « d », la liste doit contenir uniquement « Ajout », qui est maintenant sélectionnée.When you type another "d", the list should contain only "addition", which is now selected. Vous pouvez valider « addition » en appuyant sur la touche espace, tabulation ou entrée, ou fermer la liste en tapant ÉCHAP ou une autre clé.You can commit "addition" by pressing the Spacebar, Tab, or Enter key, or dismiss the list by typing Esc or any other key.

Voir aussiSee Also

Procédure pas à pas : Liaison d’un type de contenu à une extension de nom de fichierWalkthrough: Linking a Content Type to a File Name Extension