共用方式為


逐步解說: 實作程式碼片段

 

發行︰ 2016年7月

如需 Visual Studio 2017 的最新文件請參閱 Visual Studio 2017 文件

您可以建立程式碼片段,並將它們包含在編輯器延伸模組,以便擴充功能的使用者可以將它們加入自己的程式碼。

程式碼片段是程式碼或其他可以合併檔案中的文字片段。 若要檢視所有已註冊為特定的程式設計語言,在程式碼片段工具] 功能表上,按一下 [程式碼片段管理員。 若要插入程式碼片段在檔案中,以滑鼠右鍵按一下您想要的程式碼片段中,按一下插入程式碼片段環繞,找出您想,程式碼的片段,然後按兩下它。 按 TAB 或 SHIFT + TAB,修改相關部分的程式碼片段,然後按下 ENTER 或 esc 鍵,以接受它。 如需詳細資訊,請參閱 Code Snippets

程式碼片段會包含在具有.snippet 副檔名的 XML 檔案。 程式碼片段可包含程式碼片段插入,讓使用者可以尋找並加以變更後會反白顯示的欄位。 程式碼片段檔案也會提供資訊程式碼片段管理員,讓它可以顯示程式碼片段名稱正確類別中。 如需程式碼片段結構描述資訊,請參閱程式碼片段結構描述參考

這個逐步解說示範如何完成這些工作︰

  1. 建立並註冊特定語言的程式碼片段。

  2. 新增插入程式碼片段命令至快速鍵功能表。

  3. 實作程式碼片段擴充。

本逐步解說根據逐步解說︰ 顯示陳述式完成

必要條件

啟動 Visual Studio 2015 中,您未安裝 Visual Studio SDK 從 「 下載中心 」。 它是 Visual Studio 安裝程式的選用功能。 您也可以在稍後安裝 VS SDK。 如需詳細資訊,請參閱安裝 Visual Studio SDK

建立和註冊程式碼片段

一般來說,程式碼片段是與已註冊的語言服務相關聯。 然而,您不需要實作LanguageService註冊程式碼片段。 相反地,只在程式碼片段的索引檔案中指定的 GUID,然後使用相同的 GUID 在ProvideLanguageCodeExpansionAttribute您加入至您的專案。

下列步驟示範如何建立程式碼片段,並將它們關聯的特定 GUID。

  1. 建立下列目錄結構︰

    %InstallDir%\TestSnippets\Snippets\1033\

    其中*%installdir%*是 Visual Studio 安裝資料夾。 (雖然這個路徑通常用來安裝程式碼片段中,您可以指定任何路徑)。

  2. 在 \1033\ 資料夾中,建立一個.xml 檔案,並將它TestSnippets.xml。 (雖然這個名稱通常用於程式碼片段的索引檔案,您可以指定任何名稱,只要它具有.xml 副檔名。)加入下列文字,然後刪除版面配置區 GUID,並加入您自己。

    <?xml version="1.0" encoding="utf-8" ?>  
    <SnippetCollection>  
        <Language Lang="TestSnippets" Guid="{00000000-0000-0000-0000-000000000000}">  
            <SnippetDir>  
                <OnOff>On</OnOff>  
                <Installed>true</Installed>  
                <Locale>1033</Locale>  
                <DirPath>%InstallRoot%\TestSnippets\Snippets\%LCID%\</DirPath>  
                <LocalizedName>Snippets</LocalizedName>  
            </SnippetDir>  
        </Language>  
    </SnippetCollection>  
    
  3. 程式碼片段資料夾中建立的檔案、 將它命名測試.snippet,然後加入下列文字︰

    <?xml version="1.0" encoding="utf-8" ?>  
    <CodeSnippets  xmlns="https://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">  
        <CodeSnippet Format="1.0.0">  
            <Header>  
                <Title>Test replacement fields</Title>  
                <Shortcut>test</Shortcut>  
                <Description>Code snippet for testing replacement fields</Description>  
                <Author>MSIT</Author>  
                <SnippetTypes>  
                    <SnippetType>Expansion</SnippetType>  
                </SnippetTypes>  
            </Header>  
            <Snippet>  
                <Declarations>  
                    <Literal>  
                      <ID>param1</ID>  
                        <ToolTip>First field</ToolTip>  
                        <Default>first</Default>  
                    </Literal>  
                    <Literal>  
                        <ID>param2</ID>  
                        <ToolTip>Second field</ToolTip>  
                        <Default>second</Default>  
                    </Literal>  
                </Declarations>  
                <References>  
                   <Reference>  
                       <Assembly>System.Windows.Forms.dll</Assembly>  
                   </Reference>  
                </References>  
                <Code Language="TestSnippets">  
                    <![CDATA[MessageBox.Show("$param1$");  
         MessageBox.Show("$param2$");]]>  
                </Code>    
            </Snippet>  
        </CodeSnippet>  
    </CodeSnippets>  
    

下列步驟顯示如何註冊的程式碼片段。

特定 GUID 的註冊程式碼片段

  1. 開啟CompletionTest專案。 如需有關如何建立此專案的資訊,請參閱逐步解說︰ 顯示陳述式完成

  2. 在專案中,加入下列組件的參考︰

    • Microsoft.VisualStudio.TextManager.Interop

    • Microsoft.VisualStudio.TextManager.Interop.8.0

    • microsoft.msxml

  3. 在專案中,開啟 source.extension.vsixmanifest 檔案。

  4. 請確定資產] 索引標籤包含VsPackage內容型別,專案設為專案的名稱。

  5. 選取 CompletionTest 專案,然後在 [屬性] 視窗中設定產生 Pkgdef 檔true。 儲存專案。

  6. 新增靜態SnippetUtilities類別至專案。

    static class SnippetUtilities
    
    Module SnippetUtilities
    
  7. 在 SnippetUtilities 類別中,定義 GUID,並提供您使用 SnippetsIndex.xml 檔案中的值。

        internal const string LanguageServiceGuidStr = "00000000-0000-0000-0000-00000000";
    
        Friend Const LanguageServiceGuidStr As String = "00000000-0000-0000-0000-00000000"
    
  8. 新增ProvideLanguageCodeExpansionAttributeTestCompletionHandler類別。 這個屬性可以加入至專案中任何公用或內部 (非靜態) 類別中。 (您可能要加入usingMicrosoft.VisualStudio.Shell 命名空間陳述式。)

        [ProvideLanguageCodeExpansion(
        SnippetUtilities.LanguageServiceGuidStr,
        "TestSnippets", //the language name
        0,              //the resource id of the language
        "TestSnippets", //the language ID used in the .snippet files
        @"%InstallRoot%\TestSnippets\Snippets\%LCID%\TestSnippets.xml",
            //the path of the index file
        SearchPaths = @"%InstallRoot%\TestSnippets\Snippets\%LCID%\",
        ForceCreateDirs = @"%InstallRoot%\TestSnippets\Snippets\%LCID%\")]
        internal class TestCompletionCommandHandler : IOleCommandTarget
    
        <ProvideLanguageCodeExpansion(
        SnippetUtilities.LanguageServiceGuidStr,
        "TestSnippets",
        0,
        "TestSnippets",
        "%InstallRoot%\TestSnippets\Snippets\%LCID%\SnippetsIndex.xml",
        SearchPaths:="%InstallRoot%\TestSnippets\Snippets\%LCID%\",
        ForceCreateDirs:="%InstallRoot%\TestSnippets\Snippets\%LCID%\")>
        Friend Class TestCompletionCommandHandler
            Implements IOleCommandTarget
    
  9. 建置並執行專案。 在 Visual Studio 啟動時執行專案時執行的實驗執行個體,您剛登錄的程式碼片段應該會顯示在程式碼片段管理員TestSnippets語言。

加入快顯功能表插入片段命令

插入程式碼片段命令未包含在文字檔案的捷徑功能表。 因此,您必須啟用命令。

若要新增的快顯功能表插入片段] 命令

  1. 開啟TestCompletionCommandHandler類別檔案。

    因為這個類別會實作IOleCommandTarget,您可以啟用插入程式碼片段命令QueryStatus方法。 啟用此命令之前,請檢查,呼叫這個方法不是被自動化函式內因為時插入程式碼片段命令被按下,便會顯示程式碼片段選擇器使用者介面 (UI)。

            public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
            {
                if (!VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider))
                {
                    if (pguidCmdGroup == VSConstants.VSStd2K && cCmds > 0)
                    {
                        // make the Insert Snippet command appear on the context menu 
                        if ((uint)prgCmds[0].cmdID == (uint)VSConstants.VSStd2KCmdID.INSERTSNIPPET)
                        {
                            prgCmds[0].cmdf = (int)Constants.MSOCMDF_ENABLED | (int)Constants.MSOCMDF_SUPPORTED;
                            return VSConstants.S_OK;
                        }
                    }
                }
    
                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
                If Not VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider) Then
                    If pguidCmdGroup = VSConstants.VSStd2K AndAlso cCmds > 0 Then
                        ' make the Insert Snippet command appear on the context menu 
                        If CUInt(prgCmds(0).cmdID) = CUInt(VSConstants.VSStd2KCmdID.INSERTSNIPPET) Then
                            prgCmds(0).cmdf = CInt(Constants.MSOCMDF_ENABLED) Or CInt(Constants.MSOCMDF_SUPPORTED)
                            Return VSConstants.S_OK
                        End If
                    End If
                End If
    
                Return m_nextCommandHandler.QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText)
            End Function
    
  2. 建置並執行專案。 在實驗性的執行個體,開啟.zzz 副檔名的檔案,然後以滑鼠右鍵按一下任何位置中。 插入程式碼片段命令應該會出現快顯功能表。

在程式碼片段選擇器 UI 中實作程式碼片段擴充

本節說明如何實作程式碼片段擴充,使程式碼片段選擇器 UI 時顯示插入程式碼片段快顯功能表上按一下。 使用者類型的程式碼片段捷徑,然後按下 TAB 時,則也會延伸程式碼片段。

若要顯示的程式碼片段選擇器 UI,並啟用瀏覽及後續插入程式碼片段接受,請使用M:Microsoft.VisualStudio.OLE.Interop.IOleCommandTarget.Exec(System.Guid,System.UInt32,System.UInt32,System.IntPtr,System.IntPtr)方法。 插入本身由OnItemChosen方法。

程式碼片段展開的實作會使用舊版Microsoft.VisualStudio.TextManager.Interop介面。 當您從目前的編輯器類別轉譯為舊版程式碼時,請記得舊版的介面使用行號和欄數字的組合,在文字緩衝區中,指定位置,但目前的類別會使用一個索引。 因此,如果緩衝區有每個都有 10 個字元的三行 (加上 1 個字元都算是一個新行)、 第三列第四個字元位於位置 27 在目前的實作,但它是第 2 行,在舊的實作中的位置 3。

若要實作程式碼片段擴充

  1. 包含檔案TestCompletionCommandHandler類別中,新增下列using陳述式。

    using Microsoft.VisualStudio.Text.Operations;
    using MSXML;
    using System.ComponentModel.Composition;
    
    Imports Microsoft.VisualStudio.Text.Operations
    Imports MSXML
    
  2. TestCompletionCommandHandler類別實作IVsExpansionClient介面。

        internal class TestCompletionCommandHandler : IOleCommandTarget, IVsExpansionClient
    
        <ProvideLanguageCodeExpansion(
        SnippetUtilities.LanguageServiceGuidStr,
        "TestSnippets",
        0,
        "TestSnippets",
        "%InstallRoot%\TestSnippets\Snippets\%LCID%\SnippetsIndex.xml",
        SearchPaths:="%InstallRoot%\TestSnippets\Snippets\%LCID%\",
        ForceCreateDirs:="%InstallRoot%\TestSnippets\Snippets\%LCID%\")>
        Friend Class TestCompletionCommandHandler
            Implements IOleCommandTarget
            Implements IVsExpansionClient
    
  3. TestCompletionCommandHandlerProvider類別中,匯入ITextStructureNavigatorSelectorService

        [Import]
        internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
    
        <Import()>
        Friend Property NavigatorService As ITextStructureNavigatorSelectorService
    
  4. 加入一些程式碼擴充介面的私用欄位和IVsTextView

            IVsTextView m_vsTextView;
            IVsExpansionManager m_exManager;
            IVsExpansionSession m_exSession;
    
            Dim m_vsTextView As IVsTextView
            Dim m_exManager As IVsExpansionManager
            Dim m_exSession As IVsExpansionSession
    
  5. 建構函式中TestCompletionCommandHandler類別中,設定下列欄位。

            internal TestCompletionCommandHandler(IVsTextView textViewAdapter, ITextView textView, TestCompletionHandlerProvider provider)
            {
                this.m_textView = textView;
                m_vsTextView = textViewAdapter;
                m_provider = provider;
                //get the text manager from the service provider
                IVsTextManager2 textManager = (IVsTextManager2)m_provider.ServiceProvider.GetService(typeof(SVsTextManager));
                textManager.GetExpansionManager(out m_exManager);
                m_exSession = null;
    
                //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
                Me.m_vsTextView = textViewAdapter
    
                Dim textManager As IVsTextManager2 = DirectCast(m_provider.ServiceProvider.GetService(GetType(SVsTextManager)), IVsTextManager2)
                textManager.GetExpansionManager(m_exManager)
                m_exSession = Nothing
    
                'add the command to the command chain
                textViewAdapter.AddCommandFilter(Me, m_nextCommandHandler)
            End Sub
    
  6. 若要顯示程式碼片段選擇器,當使用者按一下插入程式碼片段命令中,加入下列程式碼以Exec方法。 (若要使這項說明更容易閱讀,不顯示用來完成陳述式的 exec () 程式碼; 相反地,程式碼區塊加入至現有的方法)。檢查字元的程式碼後面加入下列程式碼區塊。

                //code previously written for Exec
                if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR)
                {
                    typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn);
                }
                //the snippet picker code starts here
                if (nCmdID == (uint)VSConstants.VSStd2KCmdID.INSERTSNIPPET)
                {
                    IVsTextManager2 textManager = (IVsTextManager2)m_provider.ServiceProvider.GetService(typeof(SVsTextManager));
    
                    textManager.GetExpansionManager(out m_exManager);
    
                    m_exManager.InvokeInsertionUI(
                        m_vsTextView,
                        this,      //the expansion client
                        new Guid(SnippetUtilities.LanguageServiceGuidStr),
                        null,       //use all snippet types
                        0,          //number of types (0 for all)
                        0,          //ignored if iCountTypes == 0
                        null,       //use all snippet kinds
                        0,          //use all snippet kinds
                        0,          //ignored if iCountTypes == 0
                        "TestSnippets", //the text to show in the prompt
                        string.Empty);  //only the ENTER key causes insert 
    
                    return VSConstants.S_OK;
                }
    
                'code previously written for Exec
                If pguidCmdGroup = VSConstants.VSStd2K AndAlso nCmdID = CUInt(VSConstants.VSStd2KCmdID.TYPECHAR) Then
                    typedChar = ChrW(CUShort(Marshal.GetObjectForNativeVariant(pvaIn)))
                End If
                'the snippet picker code starts here
                If nCmdID = CUInt(VSConstants.VSStd2KCmdID.INSERTSNIPPET) Then
                    Dim textManager As IVsTextManager2 = DirectCast(m_provider.ServiceProvider.GetService(GetType(SVsTextManager)), IVsTextManager2)
    
                    textManager.GetExpansionManager(m_exManager)
                    m_exManager.InvokeInsertionUI(
                        m_vsTextView,
                        Me,
                        New Guid(SnippetUtilities.LanguageServiceGuidStr),
                        Nothing,
                        0,
                        0,
                        Nothing,
                        0,
                        0,
                        "TestSnippets",
                        String.Empty)
                    Return VSConstants.S_OK
                End If
    
  7. 直到明確地接受擴充; 如果程式碼片段會有可巡覽的欄位,擴充工作階段會保持開啟如果程式碼片段會不有任何欄位,在工作階段已關閉,而且會當做傳回nullInvokeInsertionUI方法。 在Exec方法中,程式碼片段選擇器 UI 程式碼,您在上一個步驟中,加入之後新增下列程式碼來處理片段巡覽 (當使用者程式碼片段插入後,按 TAB 或 SHIFT + TAB)。

                //the expansion insertion is handled in OnItemChosen
                //if the expansion session is still active, handle tab/backtab/return/cancel
                if (m_exSession != null)
                {
                    if (nCmdID == (uint)VSConstants.VSStd2KCmdID.BACKTAB)
                    {
                        m_exSession.GoToPreviousExpansionField();
                        return VSConstants.S_OK;
                    }
                    else if (nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB)
                    {
    
                        m_exSession.GoToNextExpansionField(0); //false to support cycling through all the fields
                        return VSConstants.S_OK;
                    }
                    else if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN || nCmdID == (uint)VSConstants.VSStd2KCmdID.CANCEL)
                    {
                        if (m_exSession.EndCurrentExpansion(0) == VSConstants.S_OK)
                        {
                            m_exSession = null;
                            return VSConstants.S_OK;
                        }
                    }
                }
    
                'the expansion insertion is handled in OnItemChosen
                'if the expansion session is still active, handle tab/backtab/return/cancel
                If m_exSession IsNot Nothing Then
                    If nCmdID = CUInt(VSConstants.VSStd2KCmdID.BACKTAB) Then
                        m_exSession.GoToPreviousExpansionField()
                        Return VSConstants.S_OK
                    ElseIf nCmdID = CUInt(VSConstants.VSStd2KCmdID.TAB) Then
                        m_exSession.GoToNextExpansionField(0)
                        'false to support cycling through all the fields
                        Return VSConstants.S_OK
                    ElseIf nCmdID = CUInt(VSConstants.VSStd2KCmdID.[RETURN]) OrElse nCmdID = CUInt(VSConstants.VSStd2KCmdID.CANCEL) Then
                        If m_exSession.EndCurrentExpansion(0) = VSConstants.S_OK Then
                            m_exSession = Nothing
                            Return VSConstants.S_OK
                        End If
                    End If
                End If
    
  8. 若要插入的程式碼片段,使用者型別對應的捷徑,然後按下 TAB 時,將程式碼加入Exec方法。 私用方法插入程式碼片段會顯示在稍後的步驟。 您在上一個步驟中加入導覽程式碼後面加入下列程式碼。

                //neither an expansion session nor a completion session is open, but we got a tab, so check whether the last word typed is a snippet shortcut 
                if (m_session == null && m_exSession == null && nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB)
                {
                    //get the word that was just added 
                    CaretPosition pos = m_textView.Caret.Position;
                    TextExtent word = m_provider.NavigatorService.GetTextStructureNavigator(m_textView.TextBuffer).GetExtentOfWord(pos.BufferPosition - 1); //use the position 1 space back
                    string textString = word.Span.GetText(); //the word that was just added
                    //if it is a code snippet, insert it, otherwise carry on
                    if (InsertAnyExpansion(textString, null, null))
                        return VSConstants.S_OK;
                }
    
                'neither an expansion session nor a completion session is open, but we got a tab, so check whether the last word typed is a snippet shortcut 
                If m_session Is Nothing AndAlso m_exSession Is Nothing AndAlso nCmdID = CUInt(VSConstants.VSStd2KCmdID.TAB) Then
                    'get the word that was just added 
                    Dim pos As CaretPosition = m_textView.Caret.Position
                    Dim word As TextExtent = m_provider.NavigatorService.GetTextStructureNavigator(m_textView.TextBuffer).GetExtentOfWord(pos.BufferPosition - 1)
                    Dim textString As String = word.Span.GetText()
                    'if it is a code snippet, insert it, otherwise carry on
                    If InsertAnyExpansion(textString, Nothing, Nothing) Then
                        Return VSConstants.S_OK
                    End If
                End If
    
  9. 實作的方法IVsExpansionClient介面。 在此實作中,只有感興趣的方法都是EndExpansionOnItemChosen。 其他方法應該只會傳回S_OK

            public int EndExpansion()
            {
                m_exSession = null;
                return VSConstants.S_OK;
            }
    
            public int FormatSpan(IVsTextLines pBuffer, TextSpan[] ts)
            {
                return VSConstants.S_OK;
            }
    
            public int GetExpansionFunction(IXMLDOMNode xmlFunctionNode, string bstrFieldName, out IVsExpansionFunction pFunc)
            {
                pFunc = null;
                return VSConstants.S_OK;
            }
    
            public int IsValidKind(IVsTextLines pBuffer, TextSpan[] ts, string bstrKind, out int pfIsValidKind)
            {
                pfIsValidKind = 1;
                return VSConstants.S_OK;
            }
    
            public int IsValidType(IVsTextLines pBuffer, TextSpan[] ts, string[] rgTypes, int iCountTypes, out int pfIsValidType)
            {
                pfIsValidType = 1;
                return VSConstants.S_OK;
            }
    
            public int OnAfterInsertion(IVsExpansionSession pSession)
            {
                return VSConstants.S_OK;
            }
    
            public int OnBeforeInsertion(IVsExpansionSession pSession)
            {
                return VSConstants.S_OK;
            }
    
            public int PositionCaretForEditing(IVsTextLines pBuffer, TextSpan[] ts)
            {
                return VSConstants.S_OK;
            }
    
            Public Function EndExpansion() As Integer Implements IVsExpansionClient.EndExpansion
                m_exSession = Nothing
                Return VSConstants.S_OK
            End Function
    
            Public Function FormatSpan(ByVal pBuffer As IVsTextLines, ByVal ts As TextSpan()) As Integer Implements IVsExpansionClient.FormatSpan
                Return VSConstants.S_OK
            End Function
    
            Public Function GetExpansionFunction(ByVal xmlFunctionNode As IXMLDOMNode, ByVal bstrFieldName As String, ByRef pFunc As IVsExpansionFunction) As Integer Implements IVsExpansionClient.GetExpansionFunction
                pFunc = Nothing
                Return VSConstants.S_OK
            End Function
    
            Public Function IsValidKind(ByVal pBuffer As IVsTextLines, ByVal ts As TextSpan(), ByVal bstrKind As String, ByRef pfIsValidKind As Integer) As Integer Implements IVsExpansionClient.IsValidKind
                pfIsValidKind = 1
                Return VSConstants.S_OK
            End Function
    
            Public Function IsValidType(ByVal pBuffer As IVsTextLines, ByVal ts() As TextSpan, ByVal rgTypes() As String, ByVal iCountTypes As Integer, ByRef pfIsValidType As Integer) As Integer Implements IVsExpansionClient.IsValidType
                pfIsValidType = 1
                Return VSConstants.S_OK
            End Function
    
            Public Function OnAfterInsertion(ByVal pSession As IVsExpansionSession) As Integer Implements IVsExpansionClient.OnAfterInsertion
                Return VSConstants.S_OK
            End Function
    
            Public Function OnBeforeInsertion(ByVal pSession As IVsExpansionSession) As Integer Implements IVsExpansionClient.OnBeforeInsertion
                Return VSConstants.S_OK
            End Function
    
            Public Function PositionCaretForEditing(ByVal pBuffer As IVsTextLines, ByVal ts As TextSpan()) As Integer Implements IVsExpansionClient.PositionCaretForEditing
                Return VSConstants.S_OK
            End Function
    
  10. 實作OnItemChosen方法。 在稍後的步驟將說明實際插入擴充功能的 helper 方法。 TextSpan提供列和資料行資訊,您可以從取得IVsTextView

            public int OnItemChosen(string pszTitle, string pszPath)
            {
                InsertAnyExpansion(null, pszTitle, pszPath);
                return VSConstants.S_OK;
            }
    
            Public Function OnItemChosen(ByVal pszTitle As String, ByVal pszPath As String) As Integer Implements IVsExpansionClient.OnItemChosen
                InsertAnyExpansion(Nothing, pszTitle, pszPath)
                Return VSConstants.S_OK
            End Function
    
  11. 下列的私用方法插入程式碼片段,根據捷徑或標題和路徑。 然後它會呼叫InsertNamedExpansion方法,使用程式碼片段。

            private bool InsertAnyExpansion(string shortcut, string title, string path)
            {
                //first get the location of the caret, and set up a TextSpan
                int endColumn, startLine;
                //get the column number from  the IVsTextView, not the ITextView
                m_vsTextView.GetCaretPos(out startLine, out endColumn);
    
                TextSpan addSpan = new TextSpan();
                addSpan.iStartIndex = endColumn;
                addSpan.iEndIndex = endColumn;
                addSpan.iStartLine = startLine;
                addSpan.iEndLine = startLine;
    
                if (shortcut != null) //get the expansion from the shortcut
                {
                    //reset the TextSpan to the width of the shortcut, 
                    //because we're going to replace the shortcut with the expansion
                    addSpan.iStartIndex = addSpan.iEndIndex - shortcut.Length;
    
                    m_exManager.GetExpansionByShortcut(
                        this,
                        new Guid(SnippetUtilities.LanguageServiceGuidStr),
                        shortcut,
                        m_vsTextView,
                        new TextSpan[] { addSpan },
                        0,
                        out path,
                        out title);
    
                }
                if (title != null && path != null)
                {
                    IVsTextLines textLines;
                    m_vsTextView.GetBuffer(out textLines);
                    IVsExpansion bufferExpansion = (IVsExpansion)textLines;
    
                    if (bufferExpansion != null)
                    {
                        int hr = bufferExpansion.InsertNamedExpansion(
                            title,
                            path,
                            addSpan,
                            this,
                            new Guid(SnippetUtilities.LanguageServiceGuidStr),
                            0,
                           out m_exSession);
                        if (VSConstants.S_OK == hr)
                        {
                            return true;
                        }
                    }
                }
                return false;
            }
    
            Private Function InsertAnyExpansion(ByVal shortcut As String, ByVal title As String, ByVal path As String) As Boolean
                Dim endColumn As Integer, startLine As Integer
                'get the column number from  the IVsTextView, not the ITextView
                m_vsTextView.GetCaretPos(startLine, endColumn)
    
                Dim addSpan As New TextSpan()
                addSpan.iStartIndex = endColumn
                addSpan.iEndIndex = endColumn
                addSpan.iStartLine = startLine
                addSpan.iEndLine = startLine
    
                'get the expansion from the shortcut
                If shortcut IsNot Nothing Then
                    'reset the TextSpan to the width of the shortcut, because we're going to replace the shortcut with the expansion
                    addSpan.iStartIndex = addSpan.iEndIndex - shortcut.Length
    
                    m_exManager.GetExpansionByShortcut(
                        Me,
                        New Guid(SnippetUtilities.LanguageServiceGuidStr),
                        shortcut,
                        m_vsTextView,
                        New TextSpan() {addSpan},
                        0,
                        path,
                        title)
                End If
                If title IsNot Nothing AndAlso path IsNot Nothing Then
                    Dim textLines As IVsTextLines = Nothing
                    m_vsTextView.GetBuffer(textLines)
                    Dim bufferExpansion As IVsExpansion = DirectCast(textLines, IVsExpansion)
    
                    If bufferExpansion IsNot Nothing Then
                        Dim hr As Integer = bufferExpansion.InsertNamedExpansion(
                            title,
                            path,
                            addSpan,
                            Me,
                            New Guid(SnippetUtilities.LanguageServiceGuidStr),
                            0,
                            m_exSession)
                        If VSConstants.S_OK = hr Then
                            Return True
                        End If
                    End If
                End If
                Return False
            End Function
    

建置和測試程式碼片段擴充

您可以測試是否擴充程式碼片段適用於您的專案。

  1. 建置方案。 當您在偵錯工具中執行這個專案時,會具現化第二個 Visual Studio 執行個體。

  2. 開啟文字檔案,並輸入一些文字。

  3. 在文字中的某處按一下滑鼠右鍵,然後按一下插入程式碼片段

  4. UI 應會顯示快顯視窗顯示的程式碼片段選擇器測試取代欄位。 按兩下快顯視窗。

    應插入下列程式碼片段。

    MessageBox.Show("first");  
    MessageBox.Show("second");  
    

    不要按 ENTER 或 esc 鍵。

  5. 按下 TAB,SHIFT + TAB 切換之間"first"和"第二個 」。

  6. 按下 ENTER 或 esc 鍵,以接受插入。

  7. 在文字的不同部分中,輸入 「 測試 」,然後按 TAB 鍵。 因為 「 測試 」 程式碼片段捷徑,應該再次插入程式碼片段。

後續步驟