因为自 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. CLR 这些年有啥变化吗?

    引言 首先想给初学者推荐下<CLR via C#>这本好书,做.Net开发的开发者应该都读一下.为避免广告之嫌,所以这里只提供豆瓣书评的链接. CLR 作为.Net 程序跨平台运行的载体, ...

  2. hadoop 2.7.3本地环境运行官方wordcount-基于HDFS

    接上篇<hadoop 2.7.3本地环境运行官方wordcount>.继续在本地模式下测试,本次使用hdfs. 2 本地模式使用fs计数wodcount 上面是直接使用的是linux的文件 ...

  3. HTML中上传与读取图片或文件(input file)----在路上(25)

    input file相关知识简例 在此介绍的input file相关知识为: 上传照片及文件,其中包括单次上传.批量上传.删除照片.增加照片.读取图片.对上传的图片或文件的判断,比如限制图片的张数.限 ...

  4. C#中如何创建PDF网格并插入图片

    这篇文章我将向大家演示如何以编程的方式在PDF文档中创建一个网格,并将图片插入特定的网格中. 网上有一些类似的解决方法,在这里我选择了一个免费版的PDF组件.安装控件后,创建新项目,添加安装目录下的d ...

  5. node中的Stream-Readable和Writeable解读

    在node中,只要涉及到文件IO的场景一般都会涉及到一个类-Stream.Stream是对IO设备的抽象表示,其在JAVA中也有涉及,主要体现在四个类-InputStream.Reader.Outpu ...

  6. 在Windows上编译和调试CoreCLR

    生成CoreCLR - Windows篇 本文的唯一目的就是让你运行Hello World 运行环境 Window 7+ Visual studio 2015 确保C++ 工具已经被安装,默认是不安装 ...

  7. RIFF和WAVE音频文件格式

    RIFF file format RIFF全称为资源互换文件格式(Resources Interchange File Format),是Windows下大部分多媒体文件遵循的一种文件结构.RIFF文 ...

  8. CSS知识总结(八)

    CSS常用样式 8.变形样式 改变元素的大小,透明,旋转角度,扭曲度等. transform : none | <transform-function> <transform-fun ...

  9. swift 中关于open ,public ,fileprivate,private ,internal,修饰的说明

    关于 swift 中的open ,public ,fileprivate,private, internal的区别 以下按照修饰关键字的访问约束范围 从约束的限定范围大到小的排序进行说明 open,p ...

  10. Atitit 软件工程概览attilax总结

    Atitit 软件工程概览attilax总结 1.1. .2 软件工程的发展 进一步地,结合人类发展史和计算机世界演化史来考察软件工程的发展史. 表2 软件工程过程模型 表2将软件工程的主要过程模型做 ...