Visual Studio 宏的高級用法

 

由於自 Visual Studio 2012 開始,微軟已經取消了對宏的支持,因此本篇文章所述內容只適用於 Visual Studio 2010 或更早期版本的 VS。html

  在上一篇中,我已經介紹瞭如何編寫一個最簡單的宏,本文將進一步介紹如何用宏來實現對代碼編輯窗口控制。在本文結束的時候,你應該能本身實現以下兩個功能,第一個用於對方法體進行 phase0 標記;第二個能夠將當前窗口中的代碼進行歸類,將全部方法、屬性、變量經過region進行分塊。編程

動畫演示:phase0 編輯器

 

動畫演示:設置 region
工具

 

爲何使用宏

  在計算機行業內,宏的出現由來已久,由於它能替代人們執行一些重複發生的簡單但煩瑣的事情,因此廣受人們歡迎。在 Visual Studio 中也提供了進行宏編程的方法,從而方便開發人員錄製一些宏腳原本擴展Visual Studio,以提升開發效率。post

 

  要想在 Visual Studio 中操做宏來操控代碼編輯窗口,就必需要了解以下幾個東東:EnvDTEDTETextSelectionEditPoint。宏可實現地遠不止是操控代碼編輯窗口,關於其它能力請見參考資源[1]動畫

 

  本文中的內容在閱讀過程當中最好能結合實踐進行練習,這樣印象會更深入。 ui

EnvDTE

  EnvDTE 是最核心的程序集,全部後續要講到的東西都歸於它名下。spa

 

  MSDN上對它的介紹:3d

EnvDTE 是包含 Visual Studio 內核自動化的對象和成員的用程序集包裝的 COM 庫。 在 EnvDTE80、EnvDTE90、 EnvDTE90a 和 EnvDTE100 命名空間中包含更改和新功能。code

  EnvDTE80、90、100按照數字,越大的表示越新,由於Visual Stuido有好多版本,不一樣的版本會提供新的功能,而這幾個版本的 EnvDTE 正是對應了這些更新,不一樣的版本只是在功能上作了補充,並無誰能替代誰的關係,好比editPoint2 比 editPoint 可能多了某些新特性,當你要使用這些新特性的時候,就應該使用editPoint2,不然仍是使用 editPoint。

 

  在編寫本身的擴展前,能夠把EnvDTE、EnvDTE80 等所有引用進來。

Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100

 

DTE對象

  在 Visual Studio 中, DTE 對象是自動化模型中的頂級對象,經過操做DTE對象能夠獲取對 Visual Studio 的控制,好比你能夠獲得當前活動的文檔、活動的窗口、活動的項目、查找與替換、向解決方案中添加文件、執行預約義命令、錄製宏等。

 

  DTE包含的屬性(局部)

上面只是截取了一部分,完整的請查看 MSDN 

 

  DTE包含的方法

 

  經過操控這些屬性和方法就能夠實現強大的功能,下面的例子中經過操縱DTE對象的TextSelecion子對象和Find子對象來調用 Visual Studio 的查找功能。

 1 Dim selection As TextSelection = DTE.ActiveDocument.Selection
 2  
 3 DTE.Find.MatchWholeWord = False
 4 DTE.Find.Action = vsFindAction.vsFindActionFind
 5 DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
 6 DTE.Find.MatchCase = False
 7 DTE.Find.Backwards = False
 8 DTE.Find.MatchInHiddenText = True
 9 DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
10  
11 '跳出輸入框,接收你的輸入
12 what = InputBox(prompt)
13 If (what <> "") Then
14      DTE.Find.FindWhat = what
15       
16      '至關於在當前文檔向下搜索一次
17      Dim result = DTE.Find.Execute()
18      If (result = vsFindResult.vsFindResultFound) Then
19           
20          ’若是找到,就把那一行選中
21          selection.SelectLine()
22      End If
23 End If

 

   上面的代碼並不複雜,就是簡單地對 Find 的調用和賦值。若是你正好看到這裏,不仿也試着寫一下吧~ Find 相關內容請查看參考資源[2]

TextSelection

  用於表明當前選定的區域,一個文檔有且只有一個實例,即便你在代碼中建立了多個實例,這些實例其實都是指向同一個選定區域。對 TextSelection 的操控會直接體如今界面上。經過控制該對象能夠剪切、複製、刪除選中的文本,插入刪除空白行,大小寫轉換,定位到某個位置、格式化等。

 

  TextSelection 的屬性

 

  TextSelection 的方法(局部)

完整的請查看 MSDN 

 

  一句話獲取 TextSelection 實例,由於 TextSelection 是針對文檔的,因此在獲取 Selection 以前,必須先獲取文檔。若是當前文檔中並無選中任何文本,則 TextSelection 表示的是當前光標所在的位置。

Dim selection As TextSelection = DTE.ActiveDocument.Selection

 

  下面演示幾個例子,來講明 TextSelection 的能力。 

  第一個例子將演示如何獲取當前光標所在的方法的名稱,主要經過獲取當前光標所在位置的 CodeElement 元素來獲得具體的方法信息,經過傳入 CodeElement 的參數不一致能夠獲取不一樣塊的信息,包括方法、枚舉、屬性、類、名稱空間等。關於 vsCMElement 的枚舉請見參考資源[4]

1 Sub DemoFunctionInfo()
2         Dim selection As TextSelection = DTE.ActiveDocument.Selection
3         Dim func As CodeFunction = selection.ActivePoint.CodeElement(vsCMElement.vsCMElementFunction)
4         If Not func Is Nothing Then
5             MsgBox(func.Name)
6         End If
7 End Sub

 


動畫演示:顯示方法名

 

  第二個示例,演示如何在光標位置所在的行上下加上Region。

 1     Sub DemoRegion()
 2  
 3         '獲取 TextSelection 實例
 4         Dim selection As TextSelection = DTE.ActiveDocument.Selection
 5  
 6         '移動到當前光標所在行的最前面
 7         selection.StartOfLine()
 8         '在該位置插入一個新行,至關於按了下回車
 9         selection.NewLine()
10         '將光標移回到新行
11         selection.LineUp()
12         '在當前光標所在的位置開始輸入文字
13         selection.Text = "#region start"
14  
15         '將光標移動到下一行
16         selection.LineDown()
17         '將光標移動到行末
18         selection.EndOfLine()
19         '回車
20         selection.NewLine()
21         selection.Text = "#endregion"
22  
23         '格式化
24         selection.SmartFormat()
25  
26     End Sub

動畫演示:在特定行的上下添加region

 

  再來看一個示例,用戶輸入起始和結束文字,而後自動選中位於這兩個起始結束標記之間的一段文本。

 1     Sub DemoSelectTextRange()
 2          
 3         '獲取 TextSelection
 4         Dim selection As TextSelection = DTE.ActiveDocument.Selection
 5         Dim startLine As Integer
 6         Dim startLineOffset As Integer
 7         Dim startPoint As TextPoint
 8         Dim endLine As Integer
 9         Dim endLineOffset As Integer
10  
11         DTE.Find.Action = vsFindAction.vsFindActionFind
12         DTE.Find.MatchCase = False
13  
14         '-------------- 找到起始的文字 ----------------------
15         Dim input = InputBox("Enter a word to find as the start tag")
16         If input = "" Then
17             Exit Sub
18         End If
19  
20         DTE.Find.FindWhat = input
21         Dim result As vsFindResult = DTE.Find.Execute()
22         If result <> vsFindResult.vsFindResultFound Then
23             Exit Sub
24         End If
25  
26         startLineOffset = selection.BottomPoint.LineCharOffset
27         startLine = selection.BottomPoint.Line
28         '-----------------------------------------------------
29  
30         '--------------- 找到結束的文字 ----------------------
31         input = InputBox("Enter a word to find as the end tag")
32         If input = "" Then
33             Exit Sub
34         End If
35  
36         DTE.Find.FindWhat = input
37         result = DTE.Find.Execute()
38         If result <> vsFindResult.vsFindResultFound Then
39             Exit Sub
40         End If
41  
42         endLine = selection.TopPoint.Line
43         endLineOffset = selection.TopPoint.LineCharOffset
44         '-----------------------------------------------------
45  
46         '------------- 遍歷,記錄通過的字符數用於選中 --------
47         Dim index As Integer
48         Dim len As Integer = 0
49  
50         selection.GotoLine(startLine)
51         len += selection.ActivePoint.LineLength - startLineOffset
52         For index = startLine + 1 To endLine - 1
53             selection.GotoLine(index)
54             len += selection.ActivePoint.LineLength
55         Next
56         selection.GotoLine(endLine)
57         len += endLineOffset
58         '-----------------------------------------------------
59  
60         '設置起始位置
61         selection.MoveToLineAndOffset(startLine, startLineOffset)
62         'True 表示鼠標跟隨移動,len 表示要移動的字符數
63         selection.CharRight(True, len)
64  
65     End Sub

 


動畫演示:選中一段文本

 

EditPoint

  Visual Studio 除了在代碼編輯窗口中會保留代碼,還有一個叫代碼緩衝區的地方(用戶是看不到的)也會保留代碼,但這個緩衝區中的代碼不受自動換行和虛擬空格的影響。前面咱們說過 TextSelection 只能有一個,那若是開發人員事先選中了一行代碼,而咱們又在宏中不當心改變了這個 TextSelection,那就會致使用戶的選中被丟失。另外,EditPoint提供了一些TextSelection所不具有的操做能力。好比剪切一段文本,使用 EditPoint 的 Cut 方法只要設置起始位置而後直接傳入結束的位置給 Cut 方法就能夠完成,可是若是使用 TextSelection ,由於它的 Cut 不帶參數,因此就必須先選中這段文本才能使用 Cut 方法。

 

  這裏補充一個小知識點,什麼是虛擬空格?這個東東默認是關閉的,在 Visual Studio 開發的時候也不多用。通常咱們在寫代碼的時候,若是在一行的結尾處使用小鍵盤向右繼續移動的話,光標很快就會自動跳轉到下一行。若是開啓以後,則永遠不會自動跳轉到下一行,你能夠在任意一個位置進行編輯。開啓的方式:工具 / 選項 / 文本編輯器 / 全部語言 -> 啓用虛擬空格。

 

  因此若是你在項目中會存在自動換行或開啓了虛擬空格,那麼想要精準的控制編輯器,仍是使用 EditPoint 吧。

 

  下面同樣舉個例子來說解。該示例將把一個方法的位置進行移動,思路就是先剪切,而後粘貼。

 1    Sub DemoCut()
 2         Dim selection As TextSelection = DTE.ActiveDocument.Selection
 3         '獲取editPointer
 4         Dim edit = selection.ActivePoint.CreateEditPoint
 5         '獲取 方法
 6         Dim func As CodeFunction = selection.ActivePoint.CodeElement(vsCMElement.vsCMElementFunction)
 7         If Not func Is Nothing Then
 8             edit.MoveToPoint(func.StartPoint)
 9             edit.Cut(func.EndPoint)
10  
11             edit.MoveToLineAndOffset(20, 1)
12             edit.Paste()
13         End If
14     End Sub

 


動畫演示:如何剪貼一個方法

 

Have a try

  辛苦了,看到這裏實在不容易。既然已經看到這了,何不來嘗試着本身寫一個呢?回到開頭的兩個示例,看看能不能寫出來了。答案請兇猛的點擊這裏

 

參考資源

  [1] 自動化與擴展性參考

  [2] Find 接口

  [3] 如何:控制代碼編輯器 (Visual Basic)

  [4] vsCMElement 枚舉

 

  本文來源於 《Visual Studio 宏的高級用法》

相關文章
相關標籤/搜索