逐步解說: 實作程式碼片段
發行︰ 2016年7月
如需 Visual Studio 2017 的最新文件請參閱 Visual Studio 2017 文件。
您可以建立程式碼片段,並將它們包含在編輯器延伸模組,以便擴充功能的使用者可以將它們加入自己的程式碼。
程式碼片段是程式碼或其他可以合併檔案中的文字片段。 若要檢視所有已註冊為特定的程式設計語言,在程式碼片段工具] 功能表上,按一下 [程式碼片段管理員。 若要插入程式碼片段在檔案中,以滑鼠右鍵按一下您想要的程式碼片段中,按一下插入程式碼片段或環繞,找出您想,程式碼的片段,然後按兩下它。 按 TAB 或 SHIFT + TAB,修改相關部分的程式碼片段,然後按下 ENTER 或 esc 鍵,以接受它。 如需詳細資訊,請參閱 Code Snippets。
程式碼片段會包含在具有.snippet 副檔名的 XML 檔案。 程式碼片段可包含程式碼片段插入,讓使用者可以尋找並加以變更後會反白顯示的欄位。 程式碼片段檔案也會提供資訊程式碼片段管理員,讓它可以顯示程式碼片段名稱正確類別中。 如需程式碼片段結構描述資訊,請參閱程式碼片段結構描述參考。
這個逐步解說示範如何完成這些工作︰
建立並註冊特定語言的程式碼片段。
新增插入程式碼片段命令至快速鍵功能表。
實作程式碼片段擴充。
本逐步解說根據逐步解說︰ 顯示陳述式完成。
必要條件
啟動 Visual Studio 2015 中,您未安裝 Visual Studio SDK 從 「 下載中心 」。 它是 Visual Studio 安裝程式的選用功能。 您也可以在稍後安裝 VS SDK。 如需詳細資訊,請參閱安裝 Visual Studio SDK。
建立和註冊程式碼片段
一般來說,程式碼片段是與已註冊的語言服務相關聯。 然而,您不需要實作LanguageService註冊程式碼片段。 相反地,只在程式碼片段的索引檔案中指定的 GUID,然後使用相同的 GUID 在ProvideLanguageCodeExpansionAttribute您加入至您的專案。
下列步驟示範如何建立程式碼片段,並將它們關聯的特定 GUID。
建立下列目錄結構︰
%InstallDir%\TestSnippets\Snippets\1033\
其中*%installdir%*是 Visual Studio 安裝資料夾。 (雖然這個路徑通常用來安裝程式碼片段中,您可以指定任何路徑)。
在 \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>
程式碼片段資料夾中建立的檔案、 將它命名測試
.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 的註冊程式碼片段
開啟CompletionTest專案。 如需有關如何建立此專案的資訊,請參閱逐步解說︰ 顯示陳述式完成。
在專案中,加入下列組件的參考︰
Microsoft.VisualStudio.TextManager.Interop
Microsoft.VisualStudio.TextManager.Interop.8.0
microsoft.msxml
在專案中,開啟 source.extension.vsixmanifest 檔案。
請確定資產] 索引標籤包含VsPackage內容型別,專案設為專案的名稱。
選取 CompletionTest 專案,然後在 [屬性] 視窗中設定產生 Pkgdef 檔至true。 儲存專案。
新增靜態
SnippetUtilities
類別至專案。static class SnippetUtilities
Module SnippetUtilities
在 SnippetUtilities 類別中,定義 GUID,並提供您使用 SnippetsIndex.xml 檔案中的值。
internal const string LanguageServiceGuidStr = "00000000-0000-0000-0000-00000000";
Friend Const LanguageServiceGuidStr As String = "00000000-0000-0000-0000-00000000"
新增ProvideLanguageCodeExpansionAttribute至
TestCompletionHandler
類別。 這個屬性可以加入至專案中任何公用或內部 (非靜態) 類別中。 (您可能要加入using
Microsoft.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
建置並執行專案。 在 Visual Studio 啟動時執行專案時執行的實驗執行個體,您剛登錄的程式碼片段應該會顯示在程式碼片段管理員下TestSnippets語言。
加入快顯功能表插入片段命令
插入程式碼片段命令未包含在文字檔案的捷徑功能表。 因此,您必須啟用命令。
若要新增的快顯功能表插入片段] 命令
開啟
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
建置並執行專案。 在實驗性的執行個體,開啟.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。
若要實作程式碼片段擴充
包含檔案
TestCompletionCommandHandler
類別中,新增下列using
陳述式。using Microsoft.VisualStudio.Text.Operations; using MSXML; using System.ComponentModel.Composition;
Imports Microsoft.VisualStudio.Text.Operations Imports MSXML
請
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
在
TestCompletionCommandHandlerProvider
類別中,匯入ITextStructureNavigatorSelectorService。[Import] internal ITextStructureNavigatorSelectorService NavigatorService { get; set; }
<Import()> Friend Property NavigatorService As ITextStructureNavigatorSelectorService
加入一些程式碼擴充介面的私用欄位和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
建構函式中
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
若要顯示程式碼片段選擇器,當使用者按一下插入程式碼片段命令中,加入下列程式碼以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
直到明確地接受擴充; 如果程式碼片段會有可巡覽的欄位,擴充工作階段會保持開啟如果程式碼片段會不有任何欄位,在工作階段已關閉,而且會當做傳回
null
由InvokeInsertionUI方法。 在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
若要插入的程式碼片段,使用者型別對應的捷徑,然後按下 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
實作的方法IVsExpansionClient介面。 在此實作中,只有感興趣的方法都是EndExpansion和OnItemChosen。 其他方法應該只會傳回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
實作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
下列的私用方法插入程式碼片段,根據捷徑或標題和路徑。 然後它會呼叫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
建置和測試程式碼片段擴充
您可以測試是否擴充程式碼片段適用於您的專案。
建置方案。 當您在偵錯工具中執行這個專案時,會具現化第二個 Visual Studio 執行個體。
開啟文字檔案,並輸入一些文字。
在文字中的某處按一下滑鼠右鍵,然後按一下插入程式碼片段。
UI 應會顯示快顯視窗顯示的程式碼片段選擇器測試取代欄位。 按兩下快顯視窗。
應插入下列程式碼片段。
MessageBox.Show("first"); MessageBox.Show("second");
不要按 ENTER 或 esc 鍵。
按下 TAB,SHIFT + TAB 切換之間"first"和"第二個 」。
按下 ENTER 或 esc 鍵,以接受插入。
在文字的不同部分中,輸入 「 測試 」,然後按 TAB 鍵。 因為 「 測試 」 程式碼片段捷徑,應該再次插入程式碼片段。