因为自 Visual Studio 2012 开始,微软已经取消了对宏的支持,所以本篇文章所述内容只适用于 Visual Studio 2010 或更早期版本的 VS。

  在上一篇中,我已经介绍了如何编写一个最简单的宏,本文将进一步介绍如何用宏来实现对代码编辑窗口控制。在本文结束的时候,你应该能自己实现如下两个功能,第一个用于对方法体进行 phase0 标记;第二个可以将当前窗口中的代码进行归类,将所有方法、属性、变量通过region进行分块。

动画演示:phase0

动画演示:设置 region

为什么使用宏

  在计算机行业内,宏的出现由来已久,因为它能替代人们执行一些重复发生的简单但烦琐的事情,所以广受人们欢迎。在 Visual Studio 中也提供了进行宏编程的方法,从而方便开发人员录制一些宏脚本来扩展Visual Studio,以提高开发效率。

  要想在 Visual Studio 中操作宏来操控代码编辑窗口,就必须要了解如下几个东东:EnvDTEDTETextSelectionEditPoint。宏可实现地远不止是操控代码编辑窗口,关于其它能力请见参考资源[1]

  本文中的内容在阅读过程中最好能结合实践进行练习,这样印象会更深刻。

EnvDTE

  EnvDTE 是最核心的程序集,所有后续要讲到的东西都归于它名下。

  MSDN上对它的介绍:

EnvDTE 是包含 Visual Studio 内核自动化的对象和成员的用程序集包装的 COM 库。 在 EnvDTE80、EnvDTE90、 EnvDTE90a 和 EnvDTE100 命名空间中包含更改和新功能。

  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 的查找功能。

 Dim selection As TextSelection = DTE.ActiveDocument.Selection

 DTE.Find.MatchWholeWord = False
DTE.Find.Action = vsFindAction.vsFindActionFind
DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
DTE.Find.MatchCase = False
DTE.Find.Backwards = False
DTE.Find.MatchInHiddenText = True
DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral '跳出输入框,接收你的输入
what = InputBox(prompt)
If (what <> "") Then
DTE.Find.FindWhat = what '相当于在当前文档向下搜索一次
Dim result = DTE.Find.Execute()
If (result = vsFindResult.vsFindResultFound) Then ’如果找到,就把那一行选中
selection.SelectLine()
End If
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]

 Sub DemoFunctionInfo()
Dim selection As TextSelection = DTE.ActiveDocument.Selection
Dim func As CodeFunction = selection.ActivePoint.CodeElement(vsCMElement.vsCMElementFunction)
If Not func Is Nothing Then
MsgBox(func.Name)
End If
End Sub


动画演示:显示方法名

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

     Sub DemoRegion()

         '获取 TextSelection 实例
Dim selection As TextSelection = DTE.ActiveDocument.Selection '移动到当前光标所在行的最前面
selection.StartOfLine()
'在该位置插入一个新行,相当于按了下回车
selection.NewLine()
'将光标移回到新行
selection.LineUp()
'在当前光标所在的位置开始输入文字
selection.Text = "#region start" '将光标移动到下一行
selection.LineDown()
'将光标移动到行末
selection.EndOfLine()
'回车
selection.NewLine()
selection.Text = "#endregion" '格式化
selection.SmartFormat() End Sub

动画演示:在特定行的上下添加region

  再来看一个示例,用户输入起始和结束文字,然后自动选中位于这两个起始结束标记之间的一段文本。

     Sub DemoSelectTextRange()

         '获取 TextSelection
Dim selection As TextSelection = DTE.ActiveDocument.Selection
Dim startLine As Integer
Dim startLineOffset As Integer
Dim startPoint As TextPoint
Dim endLine As Integer
Dim endLineOffset As Integer DTE.Find.Action = vsFindAction.vsFindActionFind
DTE.Find.MatchCase = False '-------------- 找到起始的文字 ----------------------
Dim input = InputBox("Enter a word to find as the start tag")
If input = "" Then
Exit Sub
End If DTE.Find.FindWhat = input
Dim result As vsFindResult = DTE.Find.Execute()
If result <> vsFindResult.vsFindResultFound Then
Exit Sub
End If startLineOffset = selection.BottomPoint.LineCharOffset
startLine = selection.BottomPoint.Line
'----------------------------------------------------- '--------------- 找到结束的文字 ----------------------
input = InputBox("Enter a word to find as the end tag")
If input = "" Then
Exit Sub
End If DTE.Find.FindWhat = input
result = DTE.Find.Execute()
If result <> vsFindResult.vsFindResultFound Then
Exit Sub
End If endLine = selection.TopPoint.Line
endLineOffset = selection.TopPoint.LineCharOffset
'----------------------------------------------------- '------------- 遍历,记录经过的字符数用于选中 --------
Dim index As Integer
Dim len As Integer = selection.GotoLine(startLine)
len += selection.ActivePoint.LineLength - startLineOffset
For index = startLine + To endLine -
selection.GotoLine(index)
len += selection.ActivePoint.LineLength
Next
selection.GotoLine(endLine)
len += endLineOffset
'----------------------------------------------------- '设置起始位置
selection.MoveToLineAndOffset(startLine, startLineOffset)
'True 表示鼠标跟随移动,len 表示要移动的字符数
selection.CharRight(True, len) End Sub


动画演示:选中一段文本

EditPoint

  Visual Studio 除了在代码编辑窗口中会保留代码,还有一个叫代码缓冲区的地方(用户是看不到的)也会保留代码,但这个缓冲区中的代码不受自动换行和虚拟空格的影响。前面我们说过 TextSelection 只能有一个,那如果开发人员事先选中了一行代码,而我们又在宏中不小心改变了这个 TextSelection,那就会导致用户的选中被丢失。另外,EditPoint提供了一些TextSelection所不具备的操作能力。比如剪切一段文本,使用 EditPoint 的 Cut 方法只要设置起始位置然后直接传入结束的位置给 Cut 方法就可以完成,但是如果使用 TextSelection ,因为它的 Cut 不带参数,所以就必须先选中这段文本才能使用 Cut 方法。

  这里补充一个小知识点,什么是虚拟空格?这个东东默认是关闭的,在 Visual Studio 开发的时候也很少用。一般我们在写代码的时候,如果在一行的结尾处使用小键盘向右继续移动的话,光标很快就会自动跳转到下一行。如果开启之后,则永远不会自动跳转到下一行,你可以在任意一个位置进行编辑。开启的方式:工具 / 选项 / 文本编辑器 / 所有语言 -> 启用虚拟空格。

  所以如果你在项目中会存在自动换行或开启了虚拟空格,那么想要精准的控制编辑器,还是使用 EditPoint 吧。

  下面一样举个例子来讲解。该示例将把一个方法的位置进行移动,思路就是先剪切,然后粘贴。

    Sub DemoCut()
Dim selection As TextSelection = DTE.ActiveDocument.Selection
'获取editPointer
Dim edit = selection.ActivePoint.CreateEditPoint
'获取 方法
Dim func As CodeFunction = selection.ActivePoint.CodeElement(vsCMElement.vsCMElementFunction)
If Not func Is Nothing Then
edit.MoveToPoint(func.StartPoint)
edit.Cut(func.EndPoint) edit.MoveToLineAndOffset(, )
edit.Paste()
End If
End Sub


动画演示:如何剪贴一个方法

Have a try

  辛苦了,看到这里实在不容易。既然已经看到这了,何不来尝试着自己写一个呢?回到开头的两个示例,看看能不能写出来了。答案请凶猛的点击这里

参考资源

  [1] 自动化与扩展性参考

  [2] Find 接口

  [3] 如何:控制代码编辑器 (Visual Basic)

  [4] vsCMElement 枚举

  本文来源于 《Visual Studio 宏的高级用法》

Visual Studio 宏的高级用法的更多相关文章

  1. 解决Visual Studio 2017隐藏“高级保存选项”命令

    Visual Studio提供高级保存选项功能,它能指定特定代码文件的编码规范和行尾所使用的换行符.在Visual Studio 2017中,该命令没有默认显示在“文件”菜单中.用户需要手工设置,才能 ...

  2. Visual Studio宏

    MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)MSVC++ 12.0 _MSC_VER == 1800 (Visual Studio 2013)MS ...

  3. Visual Studio宏注释模板

    前言 有时写代码需要写注释的时候 甚是苦恼 写吧 怕麻烦 不写吧 似乎这代码估计自己都看不懂 权衡之下 似乎找一个自动写注释的方法最靠谱 一直在VS下开发 偶尔听人说过有一个宏工具可以帮助开发者快速注 ...

  4. visual studio 中GIT的用法

    http://msdn.microsoft.com/zh-cn/library/vstudio/hh850445    Git 使用最新版:Git-1.8.4-preview20130916http: ...

  5. 如何扩展 Visual Studio 编辑器

    在 Visual Studio 2010 的时代,扩展 Visual Studio 的途径有很多,开发者可以选择宏.Add-in.MEF 和 VSPackages 进行自定义的扩展.但是宏在 Visu ...

  6. 如何利用 Visual Studio 自带工具提高开发效率

    Visual Stuido 是一款强大的Windows 平台集成开发工具,你是否好好地利用了它呢? 显示行号 有些时候(比如错误定位)的时候,显示行号将有利于我们进行快速定位. 如何显示 1. 工具 ...

  7. Visual Studio 编辑器

    如何扩展 Visual Studio 编辑器 在 Visual Studio 2010 的时代,扩展 Visual Studio 的途径有很多,开发者可以选择宏.Add-in.MEF 和 VSPack ...

  8. Microsoft Visual Studio 2012注册密钥

    Microsoft Visual Studio Ultimate 2012 旗舰版 有效注册密钥:YKCW6-BPFPF-BT8C9-7DCTH-QXGWCMicrosoft Visual Studi ...

  9. Visual Studio 各种版本的快捷键总结

    下列快捷组合键可在工具和文档窗口中用于进行移动.关闭或导航. 命令名 快捷键 说明 视图.全屏 SHIFT + ALT + ENTER 在打开和关闭之间切换“全屏”模式. 视图.向后定位 CTRL + ...

随机推荐

  1. 【趣事】用 JavaScript 对抗 DDOS 攻击

    继续趣事分享. 上回聊到了大学里用一根网线发起攻击,今天接着往后讲. 不过这次讲的正好相反 -- 不是攻击,而是防御.一个奇葩防火墙的开发经历. 第二学期大家都带了电脑,于是可以用更高端的方法断网了. ...

  2. Key/Value之王Memcached初探:二、Memcached在.Net中的基本操作

    一.Memcached ClientLib For .Net 首先,不得不说,许多语言都实现了连接Memcached的客户端,其中以Perl.PHP为主. 仅仅memcached网站上列出的语言就有: ...

  3. kafka学习笔记:知识点整理

    一.为什么需要消息系统 1.解耦: 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余: 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险. ...

  4. 【开源】.Net Api开放接口文档网站

    开源地址:http://git.oschina.net/chejiangyi/ApiView 开源QQ群: .net 开源基础服务  238543768 ApiView .net api的接口文档查看 ...

  5. Python(九)Tornado web 框架

    一.简介 Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本.这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过 ...

  6. 来自于微信小程序的一封简讯

    9月21晚间,微信向部分公众号发出公众平台-微信应用号(小程序)的内测邀请,向来较为低调的微信在这一晚没人再忽视它了. 来自个人博客:Damonare的个人博客 一夜之间火了的微信应用号你真的知道吗? ...

  7. 关于CSS inline-block、BFC以及外边距合并的几个小问题

    CSS inline-block和BCF对于初学者来说,总是弄不太明白,下面记录下我在学习这块知识的过程中遇到的几个问题,供大家参考,有不足的地方,欢迎大家批评指正. 一.在什么场景下会出现外边距合并 ...

  8. Android中通过ActionBar为标题栏添加搜索以及分享视窗

    在Android3.0之后,Google对UI导航设计上进行了一系列的改革,其中有一个非常好用的新功能就是引入的ActionBar,他用于取代3.0之前的标题栏,并提供更为丰富的导航效果.Action ...

  9. Oracle Standard Error 列表

    今天,我特意从网上找了一些,以及自己平时总结的,关于错误编号和说明,平时我们在写项目的时候,往往是可能会出现下面这些错误,例如:违反唯一约束,无效的会话ID,等等.希望对大家有点帮助!可以看看,如果有 ...

  10. php+websocket搭建简易聊天室实践

    1.前言 公司游戏里面有个简单的聊天室,了解了之后才知道是node+websocket做的,想想php也来做个简单的聊天室.于是搜集各种资料看文档.找实例自己也写了个简单的聊天室. http连接分为短 ...