VS 2010 IDE 宏学习总结

281 篇文章 6 订阅

自动添加注释—VS2010宏的使用



    在敲代码的过程中类和函数都需要进行注释,但总是一遍一遍的复制粘贴觉得很是麻烦,终于找到

了一个不错的解决方法:使用宏。


    所谓宏,就是一些命令组织在一起,作为一个单独命令完成一个特定任务。在日常的办公环境中,
不论是Office还是Foxmail以及我们所使用的VS甚至输入法都具有宏的功能。VS2010中的宏,不仅可以录
制模块、还可以录制类和代码文件。通过设置编辑宏,然后为设置好的宏添加特定的快捷键,就可以在
VS2010代码编辑器中任何位置非常方便的添加设定的注释块。实现过程如下:
    
    1、打开“工具”→“宏”→“宏IDE”,进入以下界面,右击“MyMacros”,添加模块
    命名模块:
 
    2、添加代码并保存
    双击所添加的模块,进入编辑状态,添加如下代码:
[vb] view plain copy
Imports System  
Imports EnvDTE  
Imports EnvDTE80  
Imports EnvDTE90  
Imports EnvDTE90a  
Imports EnvDTE100  
Imports System.Diagnostics  
  
Public Module MyNote  
  
    Sub DocumentFileHeader()  
  
        Dim DocSel As EnvDTE.TextSelection  
        DocSel = DTE.ActiveDocument.Selection  
        DocSel.NewLine()  
        DocSel.Text = "'************************************************"  
        DocSel.NewLine()  
        DocSel.Text = "'◇作者:吴利昌"  
        DocSel.NewLine()  
        DocSel.Text = "'◇小组:无"  
        DocSel.NewLine()  
        DocSel.Text = "'◇说明:"  
        DocSel.NewLine()  
        DocSel.Text = "'◇版本号:V1.0"  
        DocSel.NewLine()  
        DocSel.Text = "'◇创建日期:" + System.DateTime.Now.ToLongDateString  
        DocSel.NewLine()  
        DocSel.Text = "'*************************************************"  
  
    End Sub  
  
End Module  


    3、设置快捷键
    打开“工具”→“选项”,选择“键盘”,进行如下设置 
    
    4、效果
[vb] view plain copy
'************************************************  
'◇作者:吴利昌  
'◇小组:无  
'◇说明:  
'◇版本号:V1.0  
'◇创建日期:2013年6月25日 星期二  
'*************************************************  


========

为VS2010编写IDE宏


网上有不少好书,可惜其中有很多是扫描版的,摘抄加注起来很麻烦。为方便自己,也为造福大众,我

会将自己喜爱的整理一遍,转换成文本版。

网上有现成的工具,可以将图片版的pdf转换成文本,保存到ms word中。如果源图片足够清晰的话,文

本的识别率还是很高的。

不过对于代码,其格式则往往比较混乱。手工在word中进行修正,麻烦不说,还容易出错。想起曾经有

过几次在VS2010中整理代码,进行的操作基本上都是查找替换和格式化等等;并且,从vs中拷贝的代码

,在word中还可以保留语法高亮(关键字蓝色,字符串暗红色,注释绿色)。(不足的是,从VS2010中

拷贝的中文,在word中显示为乱码;而从VS2008中拷贝,则完全正常,并且语法高亮也仍然有效)

查找替换和格式化都是些重复性的劳动,因此想着法子让电脑去做。

一开始打算使用dos批处理,但这样一来如果仍要使用语法高亮,就要手工拷贝到VS2010,在拷贝到word

,多了一个步骤,麻烦。于是就想能不能直接在VS2010中完成。没想到还真行。通过网络和MSDN,知道

VS提供了一个叫做IDE宏的东西。

IDE宏原理上和VBA差不多,或者说就是应用于VS的VBA,只不过使用的VB变成.Net版的了(我不懂VB,如

果说错了勿怪)。

下面说说编写IDE宏的具体步骤(VS2010):

按ALT+F11或者点击菜单:工具-》宏-》宏IDE,出现一个和VS类似的IDE窗口:


在MyMacros上右键添加模块,模块名称随便起(我的如上图所示,叫TieWen,是本人的网名)。


双击模块名称,打开编辑窗口,默认的内容如下:

Imports System  
Imports EnvDTE  
Imports EnvDTE80  
Imports EnvDTE90  
Imports EnvDTE90a  
Imports EnvDTE100  
Imports System.Diagnostics  
  
Public Module aaa  
  
End Module  


我们所要作的,就是在Module TieWen和End Module之间写入合适的Sub(过程,无返回值)(能否写成

Function(有返回值)本人并未深入研究)。

我最近正在整理的书籍中源码是基于Java的,因此给Sub取名为Macro_FormatJava,完整的代码如下(有

点问题,多多包涵):


[vb] view plain copy 在CODE上查看代码片派生到我的代码片
Imports System  
Imports System.Collections.Generic  
Imports EnvDTE  
Imports EnvDTE80  
Imports EnvDTE90  
Imports EnvDTE90a  
Imports EnvDTE100  
Imports System.Diagnostics  
  
Public Module TieWen  
  
    Sub MergeAll(ByRef Content As String, ByVal From As String, ByVal sTo As String)  
        While (Content.Contains(From))  
            Content = Content.Replace(From, sTo)  
        End While  
    End Sub  
  
    Sub PrefixLf(ByRef Content As String, ByVal Who As String)  
        Content = Content.Replace(Who, vbLf + Who)  
    End Sub  
  
    Sub PostfixLf(ByRef Content As String, ByVal Who As String)  
        Content = Content.Replace(Who, Who + vbLf)  
    End Sub  
  
    Sub DTEReplaceAll(ByVal Target As EnvDTE.vsFindTarget, ByVal From As String, ByVal sTo 


As String, Optional ByVal UseRegEx As Boolean = False, Optional ByVal bLoop As Boolean = 


True)  
  
        DTE.Find.FindWhat = From  
        DTE.Find.ReplaceWith = sTo  
        DTE.Find.Target = Target  
        DTE.Find.MatchCase = True  
        DTE.Find.MatchWholeWord = False  
        DTE.Find.MatchInHiddenText = False  
        If (UseRegEx) Then  
            DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxRegExpr  
        Else  
            DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral  
        End If  
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone  
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll  
        While ((DTE.Find.Execute() <> vsFindResult.vsFindResultNotFound) And bLoop)  
  
        End While  
  
    End Sub  
    ' 以上几个是辅助Sub,而不是宏  
  
  
    Sub Macro_FormatJava()  
        DTE.ActiveDocument.Selection.SelectAll()  
        Dim Content As String  
        Content = DTE.ActiveDocument.Selection.Text  
  
  
        '处理开始  
        Dim operators_NeedPrefixAndPostfixSpace(), 


operators_IfIsAssignmentNeedPrefixAndPostfixSpace(), operators_NeedPrefixSpace(), 


operators_NeedPostfixSpace(), operators_NeedNoSpace(), 


operators_IfMatchedThenNeedPrefixAndPostfixSpace()  
        '此处无法使用VB的Array函数  
        operators_NeedPrefixAndPostfixSpace = "public,class,interface,implements,return,:,


+,-,*,/,%,&,|,^,<<,>>,=,==,!=,<,<=,>,>=,&&,||".Split(",")  
        operators_IfIsAssignmentNeedPrefixAndPostfixSpace = "+,-,*,/,%,&,|,^,<<,>>".Split


(",")  
        operators_NeedPrefixSpace = "{,!,~".Split(",")  
        operators_NeedPostfixSpace = ",|;".Split("|")  
        operators_NeedNoSpace = "},->,::,.".Split(",") '不考虑case标签或其它符号后紧跟::的


情形  
        operators_IfMatchedThenNeedPrefixAndPostfixSpace = "new,delete".Split(",")  
        '尚未处理的符号:++、--(前后缀形式的区分比较麻烦)、()、[]、?:  
        '一元操作符+、-、*、&被当作二元操作符处理了;  
        For Each i In operators_NeedPrefixAndPostfixSpace  
            Content = Content.Replace(i, " " + i + " ")  
        Next  
  
        For Each i In operators_NeedPrefixSpace  
            Content = Content.Replace(i, " " + i)  
        Next  
  
        For Each i In operators_NeedPostfixSpace  
            Content = Content.Replace(i, i + " ")  
        Next  
  
        Content = Content.Replace(vbTab, " ")  
        '去除多余的空格  
        MergeAll(Content, "  ", " ")  
  
        '合并被分开的//、/*、*/、**,必须在去除多余的空格之后调用  
        MergeAll(Content, "/ /", "//")  
        MergeAll(Content, "/ *", "/*")  
        MergeAll(Content, "* /", "*/")  
        MergeAll(Content, "* *", "**")  
  
        '必须在去除多余的空格之后调用  
        For Each i In operators_IfIsAssignmentNeedPrefixAndPostfixSpace  
            Content = Content.Replace(i + " =", i + "=")  
        Next  
  
        '必须在去除多余的空格之后调用  
        For Each i In operators_NeedPrefixSpace  
            Content = Content.Replace(i + " ", i)  
        Next  
        For Each i In operators_NeedPostfixSpace  
            Content = Content.Replace(" " + i, i)  
        Next  
  
        '必须在去除多余的空格之后调用  
        For Each i In operators_NeedNoSpace  
            Content = Content.Replace(" " + i, i)  
            Content = Content.Replace(i + " ", i)  
        Next  
  
        'operators_IfMatchedThenNeedPrefixAndPostfixSpace无需处理  
  
        Dim operators_NeedPrefixLf(), operators_NeedPostfixLf()  
        '此处无法使用VB的Array函数  
        operators_NeedPrefixLf = "},if(,if( ,for(, for (,return".Split(",")  
        operators_NeedPostfixLf = "{".Split(",")  
  
        For Each i In operators_NeedPrefixLf  
            PrefixLf(Content, i)  
        Next  
        For Each i In operators_NeedPostfixLf  
            PostfixLf(Content, i)  
        Next  
  
        Content = Content.Replace(vbCrLf, vbLf)  
        Content = Content.Replace(vbCr, vbLf)  
        MergeAll(Content, " " + vbLf, vbLf)  
        MergeAll(Content, vbLf + vbLf, vbLf)  
  
        '调用ALT+F8格式化代码(在我的机器上会自动在行尾增加空格,因此上面的替换仅为处理{}使

用,具体的去除行尾空格,已使用查找替换实现)  
        DTE.ActiveDocument.Selection.Text = Content  
        DTE.ActiveDocument.Selection.SelectAll()  
        DTE.ExecuteCommand("Edit.FormatSelection")  
  
        DTE.ActiveDocument.Selection.SelectAll()  
  
        '将Tab替换成四个空格  
        '由于DTE.ActiveDocument.Selection.Text = Content会自动进行格式化,  
        '所以不能用代码进行替换再赋值,否会会导致多余的空格。  
        '通过查找替换功能实现  
        DTEReplaceAll(vsFindTarget.vsFindTargetCurrentDocumentSelection, vbTab, "    ")  
        '结束处理  
    End Sub  
End Module  
 


 Sub写好之后,就是将之应用到VS。


点击VS的菜单:工具-》选项,切换到环境-》键盘:

在显示命令包含下的输入框中输入先前的模块名或Sub的名称,等上1-2秒钟,会将过滤后的结果刷新在


输入框下发的列表中:

选中对应的宏(刚刚我们所编写的Sub),然后将光标放在“按快捷键P”下方的输入框中,按一个快捷

键,如果该快捷键已经被其它命令占用,会在“快捷键的当前使用对象U”下方的下拉框中显示出来:

此时按Backspace,删除快捷键,重新选择一个(注意,一定要按Backspace删除,不要直接继续按),

直到该快捷键未被占用(我选到的时候ALT+T),然后点击“分配”按钮,点击确定关闭选项窗口。

然后,打开一个源码文档,按下快捷键(我的是ALT+T)试试效果吧。

如果觉得不好,就修改Sub,直到自己满意为止。
 
补充:

如果发现有些IDE已经实现的功能而自己不会写,可以使用VS的宏记录功能:

按Ctrl+Shift+R或者点击菜单项“工具-〉宏-〉记录TemporaryMacro”,然后执行VS动作(比如执行查

找替换),完毕后停止宏记录,然后打开宏编辑器,打开RecordingModule,代码全在这里头。
========

VS2010编写自定义宏


这里所说的宏可不是指#define PI 3.14159之类的,而是按下Alt + 1,Alt + 2之类的键盘组合之后可以

方便地插入一大串自定义的内容,如:

/******************************************************************* 
* 函数名称: 
* 功    能: 
* 参    数: 
* 返 回 值:void 
* 创 建 人:Ajioy 
* 博    客:blog.csdn.net/ajioy 
* 电子邮箱:ajioy1206@gmail.com 
* 日    期:2013.1.8 21:18 
*******************************************************************/  

这在团队开发中显得尤为重要,当然,在网络上发布源代码时也起到一个简单地版权声明作用,而不需

要人为地花时间编写及排版,减少了许多繁琐而不必要的工作。

简单地了解一下,这里谈的宏(Macro)是开发工具VS2010(或VS的其它版本)自带的,一种方便开发人

员进行注释、版权声明或者执行其他若干琐碎工作的“小机器人”。重复、不辞劳苦地为我们做一些不

可缺少的小事。总之,有它的存在,生活更美好。

怎样自己写一个宏?

1.打开VS2010(或VS的其它版本),“Tools” -->  "Macros"--->"Macros IDE...(Alt + F11)" 打开

宏IDE

2.在宏IDE的工具栏中"Project"->"Add Module"(或Add New Item)->Name:AjioyMacros--->"Add"


3.将初始内容替换成以下代码

Imports System  
Imports EnvDTE  
Imports EnvDTE80  
Imports EnvDTE90  
Imports EnvDTE90a  
Imports EnvDTE100  
Imports System.Diagnostics  
Imports System.Text  
Imports System.Text.RegularExpressions  
Imports System.IO  
Imports System.Collections.Specialized  
  
Public Module AjioyMacros'这里要与保存的Module名保持一致,不然无法调用宏  
    Sub AddMessageBox()  
        'DESCRIPTION 增加对话框  
        ActiveDocument.Selection.Text = "MessageBox("""",""提示"");" + vbNewLine + "system


(""pause"");"  
    End Sub  
    Sub AddStartComment()  
        'DESCRIPTION 注释开始  
        ActiveDocument.Selection.Text = "system(""pause"");"  
    End Sub  
    Public Sub FileSign()  
        'DESCRIPTION 文件签名  
        Dim Description As New StringBuilder  
        Dim BlankLine As String  
        BlankLine = "//" + vbNewLine  
        With Description  
            .AppendFormat("//Copyright (c) 2013 Ajioy All Rights Reserved{0}",vbNewLine)  
            .AppendFormat


("/****************************************************************************************


*****{0}", vbNewLine)  
            .AppendFormat("*文件名:{0}{1}{2}", vbTab, DTE.ActiveDocument.Name, vbNewLine)  
            .AppendFormat("*说明:{0}{1}{2}", vbTab, "", vbNewLine)  
            .AppendFormat("*创建日期:{0}{1}{2}", vbTab, Date.Today.ToString("yyyy-MM-dd"), 


vbNewLine)  
            .AppendFormat("*作者:{0}{1}{2}", vbTab, "Ajioy", vbNewLine)  
            .AppendFormat("*版本:{0}{1}{2}", vbTab, "1.0", vbNewLine)  
            .AppendFormat


("*----------------------------------------------------------------------------------------


------{0}", vbNewLine)  
            .AppendFormat("*修改记录:{0}", vbNewLine)  
            .AppendFormat("*日期{0}版本{1}修改人{2}修改内容{3}", New String(vbTab, 3), 


vbTab, vbTab, vbNewLine)  
            .AppendFormat("*{0}{1}", Date.Today.ToString("yyyy-MM-dd"), vbNewLine)  
            .AppendFormat


("*****************************************************************************************


***/{0}", vbNewLine)  
            .Append(vbNewLine)  
        End With  
        '插入cs文件头部  
        Dim objSel As TextSelection  
        objSel = CType(DTE.ActiveDocument.Selection, TextSelection)  
        DTE.UndoContext.Open("FileSign")  
        objSel.StartOfDocument(False)  
        objSel.Insert(Description.ToString())  
        DTE.UndoContext.Close()  
    End Sub  
    Sub FunctionSign()  
        'DESCRIPTION 文件签名  
        Dim obj  
        obj = Now()  
        Dim DocSel As EnvDTE.TextSelection  
        DocSel = DTE.ActiveDocument.Selection  
        DocSel.NewLine()  
        DocSel.Text = 


"/*******************************************************************"  
        DocSel.NewLine()  
        DocSel.Text = "* 函数名称:"  
        DocSel.NewLine()  
        DocSel.Text = "* 功    能:"  
        DocSel.NewLine()  
        DocSel.Text = "* 参    数:"  
        DocSel.NewLine()  
        DocSel.Text = "* 返 回 值:"  
        DocSel.NewLine()  
        DocSel.Text = "* 创 建 人:Ajioy"  
        DocSel.NewLine()  
        DocSel.Text = "* 博    客:blog.csdn.net/ajioy"  
        DocSel.NewLine()  
        DocSel.Text = "* 电子邮箱:ajioy1206@gmail.com"  
        DocSel.NewLine()  
        DocSel.Text = "* 日    期:" + CStr(Year(obj)) + "." + CStr(Month(obj)) + "." + 

CStr(Day(obj)) + " " + CStr(Hour(obj)) + ":" + CStr(Minute(obj)) 

'System.DateTime.Now.ToLongDateString()  
        DocSel.NewLine()  
        DocSel.Text = 


"*******************************************************************/"  
    End Sub  
    Sub AddModify()  
        'DESCRIPTION 增添修改  
        Dim obj  
        obj = Now()  
        ActiveDocument.Selection.Text = "//Ajioy" + CStr(Year(obj)) + "." + CStr(Month


(obj)) + "." + CStr(Day(obj))  +" " + CStr(Hour(obj)) + ":" + CStr(Minute(obj)) + " 修改"  
    End Sub  
    Sub AddStartSymbol()  
        'DESCRIPTION 开始注释  
        ActiveDocument.Selection.Text = "/*"  
    End Sub  
    Sub AddEndSymbol()  
        'DESCRIPTION 结束注释  
        ActiveDocument.Selection.Text = "*/"  
    End Sub  
End Module  
保存后关闭宏IDE


4.回到VS2010主界面,"Tools"--->"Options"--->"Environment"--->"Keyboard"--->在Show commands 


containing:下的编辑框中输入FunctionSign(所有带括号的那些名称,如AddStartSymbol()...),会


看到有"Macros.Macros(或Samples).AjioyMacros.FunctionSign"的项,选中它,在Press shortcut 

keys:下自定义快捷键,建议用Alt +  数字0-9和-+键组合,以免与编译环境快捷键发生冲突,之

后"Assign",最后确定。

接下来我们可以随便验证一下,打开一个.cpp文件,按下Alt + 数字,看看会发生什么。


========

让vs2010自动完成双引号



   广大码奴们,敲码时遇到需要输入双引号,方括号,圆括号是不是很烦躁,

如果有一种只需要输入一个左边括号,就可以自动补齐另一边括号,并且可以自

动将光标定位到括号中间,输入完毕后又可以方便的跳出括号的工具,那效率会


不会高很多。

    百度了很久,都没有什么好的解决方案,不是装VA就是resharper插件,

但是也只是可以自动补齐和定位而已,想要跳出仍然需要利用键盘上的右方向

键,手部移动幅度很大有木有,完全打乱了敲码的节奏,破坏了忧郁的气质,好

吧,我之前一直都用鼠标来的。。。

 找不到现成的方法,只能自己动手丰衣足食了。突然发现 virtual studio是支持宏操作的,于是楼主

灵光一闪,想到了利用宏来自动实现上述功能的方法,不多说,直接上图。


 1.工具-宏-记录TemporaryMacro

 
2. 接下来就不用我多说了,和office中的一样,录制宏,比如你可以在文本编辑窗口输入“ ( ”,“ 

) ”,“ <— ”(方向键),然后停止录制宏。这样我们就有了可以自动完成双引号并定位到中间位

置的快捷操作,依次可以得到自动完成圆括号,方括号等等的宏。这是我自己录制的7个宏。
 

3. 接下来我们还要把这些宏和具体的快捷键绑定起来,这样我们只要在键盘上敲打快捷键就可以自动完


  

在“显示命令包含”中输入“宏”,会自动显示你刚刚录制的所有宏,选择一个,设置快捷键,注意设

置完要点“分配”
 
 
这样一个宏就设置完了,接下来把你录制的所有宏都设置一个你认为方便你操作的快捷键即可。


4.接下来和大家分享一下我的设计方案。我选取了H,J,K,L,N,M,Alt,空格这8个元素,她们在键盘上的位


置都在右手可以控制的范围内,非常灵活便捷,不想录制的朋友也可以直接粘贴我设置好的宏代码。


Alt+H : 删除,即backspace
Sub 删除()
        DTE.ActiveDocument.Selection.DeleteLeft()
End Sub

Alt+J:输入双引号并定位到中间
 Sub 打出双引号()
        DTE.ActiveDocument.Selection.Text = """"""
        DTE.ActiveDocument.Selection.CharLeft()
 End Sub

Alt+K:输入圆括号并定位到中间
 Sub 打出括号()
        DTE.ActiveDocument.Selection.Text = "()"
        DTE.ActiveDocument.Selection.CharLeft()
 End Sub

Alt+L:输入方括号并定位到中间
Sub 打出方括号()
        DTE.ActiveDocument.Selection.Text = "[]"
        DTE.ActiveDocument.Selection.CharLeft()
End Sub

Alt+N:撤销
 Sub 撤销()
        DTE.ExecuteCommand("Edit.Undo")
 End Sub

Alt+M:反撤销
 Sub 反撤销()
        DTE.ExecuteCommand("Edit.Redo")
 End Sub

Alt+空格:自动跳出括号
Sub 跳出()
        DTE.ActiveDocument.Selection.CharRight()
End Sub


Ps:
1. 
所有的vs编辑器都支持宏,所以这个方法可以用在vs各个版本上,你也可以依此在office上操作
2.事实上由于升级的微软补丁冲突,很多vs的宏功能已经被破坏,是无法运行任何宏的。基本都是在安

装KB2898869、KB2901126、KB2898857等更新后宏停止运行。查看了一下提供的解决方案,修改宏配置文

件,VS2010的配置文件路径为:C:\Program Files (x86)\Common Files\microsoft shared\VSA


\9.0\VsaEnv目录下的vsmsvr10.exe.config,在RunTime配置节添加配置项:
<AllowDComReflection enabled="1"/>即可
 
32bit和64bit的windows,以及vs不同版本的路径和配置文件如下
 
在之前7个宏的基础上再新加8个宏,一共15个,基本涵盖了所有常用的操作。


alt+e:光标向上
alt+d:光标向下
alt+s:光标向左
alt+f:激活文件窗口,有时由于鼠标操作或别的问题代码页面会失去焦点,这个快捷键可以让光标重新


出现在代码文件上
alt+i:复制代码段,指定行号,当前光标位置和指定行之间代码全部选定
alt+g:指定行号,光标自动跳到改行
alt+r:将选定代码段注释
alt+t:将注释代码段解开

15个快捷键全部由alt带动, s,e,d,f,r,t,g,h,j,k,l,n,m,i,空格     充分考虑手指的摆动幅度,几乎

可以保证最大限度的连续操作。

并不想将vs真的改造成vim,简单,甚好。

另外vs的宏模块全部可以导出,快捷键的绑定配置文件也可以导出,这样,把这两个文件上传到你的微

云或百度云盘,就可以保证你的随时随地使用了。
  
15Macros.vb( 宏模块文件,可导入)
-------------------------------------------------------------------------------------------


-------------------------------------------------------------------------------------
Option Strict Off
Option Explicit Off
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics
Public Module RecordingModule


    Sub 打出括号()
        DTE.ActiveDocument.Selection.Text = "()"
        DTE.ActiveDocument.Selection.CharLeft()
    End Sub


 Sub 向右()
        DTE.ActiveDocument.Selection.CharRight()
 End Sub


    Sub 打出方括号()
        DTE.ActiveDocument.Selection.Text = "[]"
        DTE.ActiveDocument.Selection.CharLeft()
    End Sub


    Sub 打出双引号()
        DTE.ActiveDocument.Selection.Text = """"""
        DTE.ActiveDocument.Selection.CharLeft()
    End Sub


    Sub 删除()
        DTE.ActiveDocument.Selection.DeleteLeft()
    End Sub


    Sub 撤销()
        DTE.ExecuteCommand("Edit.Undo")
    End Sub


    Sub 反撤销()
        DTE.ExecuteCommand("Edit.Redo")
    End Sub


    Sub 向左()
        DTE.ActiveDocument.Selection.CharLeft()
    End Sub


    Sub 向上()
        DTE.ActiveDocument.Selection.LineUp()
    End Sub


    Sub 向下()
        DTE.ActiveDocument.Selection.LineDown()
    End Sub


    Sub 激活()
        ActiveDocument.Activate()
    End Sub


    Sub 转行()
        Dim command As Integer
        command = InputBox("Enter a number: ")
        DTE.ActiveDocument.Selection.GotoLine(command)
    End Sub


    Sub 复制()
        Dim textSelection As EnvDTE.TextSelection
        Dim textSelectionPointSaved As TextPoint
        Dim command As Integer
        textSelection = DTE.ActiveWindow.Selection
        textSelectionPointSaved = textSelection.ActivePoint.CreateEditPoint()
        command = InputBox("Enter a number: ")
        selection = ActiveDocument.Selection
        d = selection.TopPoint.Line
        If ((d - command) > 0) Then
            For arrIdx = 1 To (d - command)
                selection.LineUp(True)
            Next
            textSelection.StartOfLine()
        ElseIf ((d - command) < 0) Then
            For arrIdx = 1 To (command - d)
                selection.LineDown(True)
            Next
            textSelection.EndOfLine()
        Else
            textSelection.StartOfLine()
            textSelectionPointSaved = textSelection.ActivePoint.CreateEditPoint()
            textSelection.EndOfLine()
        End If
        textSelection.MoveToPoint(textSelectionPointSaved, True)
    End Sub
 
    Sub 注释()
        DTE.ExecuteCommand("Edit.CommentSelection")
    End Sub


    Sub 解开注释()
        DTE.ExecuteCommand("Edit.UncommentSelection")
    End Sub




End Module


========

VS2010编写自定义宏,定义解决方案项目折叠、展开快捷键


怎样自己写一个宏?

1.打开VS2010(或VS的其它版本),“Tools” -->  "Macros"--->"Macros IDE...(Alt + F11)" 打开

宏IDE

2.在宏IDE的工具栏中"MyMacros"->"Add Module"->CollapseExpandAllProject

3. 将初始内容替换成以下代码

Option Strict Off
Option Explicit Off
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports System.Diagnostics

Public Module CollapseExpandAllProject   ‘(特别注意:这里要与保存的Module名保持一致,不然

无法调用宏 )

    '----------------------------------------------- 
    'Collapse All projects  折叠
    'Author:ZhangRongHua
    'Date:2010-05-12
    '-----------------------------------------------
    Public Sub CollapseAllProject()
        lastSlashIndex = DTE.Solution.FullName.LastIndexOf("\") + 1  'Get the last slash 


index .
        solutionNameWithExtension = DTE.Solution.FullName.Substring(lastSlashIndex)  ' Get 


solution name with extension. 
        solutionName = solutionNameWithExtension.ToString().Substring(0, 


solutionNameWithExtension.ToString().Length - 4) ' Get the solution name without extension 


.
        count = 0
        For Each curProject As EnvDTE.Project In DTE.Solution.Projects
            Try
                DTE.ActiveWindow.Object.GetItem(solutionName + "\" + 


curProject.Name).UIHierarchyItems.Expanded = False
                count = count + 1
            Catch ex As ArgumentException
                Continue For
            End Try
        Next curProject




    End Sub


    '----------------------------------------------- 
    'Expand All projects  展开
    'Author:ZhangRongHua
    'Date:2010-05-12
    '-----------------------------------------------
    Public Sub ExpandAllProject()
        lastSlashIndex = DTE.Solution.FullName.LastIndexOf("\") + 1  'Get the last slash 


index .
        solutionNameWithExtension = DTE.Solution.FullName.Substring(lastSlashIndex)  ' Get 


solution name with extension. 
        solutionName = solutionNameWithExtension.ToString().Substring(0, 


solutionNameWithExtension.ToString().Length - 4) ' Get the solution name without extension 


.
        count = 0


        For Each curProject As EnvDTE.Project In DTE.Solution.Projects
            Try
                DTE.ActiveWindow.Object.GetItem(solutionName + "\" + 


curProject.Name).UIHierarchyItems.Expanded = True
                count = count + 1
            Catch ex As ArgumentException
                Continue For
            End Try
        Next curProject
    End Sub


End Module
保存后关闭宏IDE


4、回到VS2010主界面(注意是在VS2010主界面,不是打开了某一个解决方案的主界面),"Tools"---


>"Options"--->"Environment"--->"Keyboard"--->在Show commands containing:下的编辑框中输入


macro(所有含macro的那些名称),会看到


有"MyMacros.CollapseExpandAllProject.CollapseAllProject"的项,选中它,在Press shortcut 


keys:下自定义快捷键,建议用Alt +  数字0-9和-+键组合,以免与编译环境快捷键发生冲突,之


后"Assign",最后确定。




5、接下来我们可以验证一下,打开一个解决方案,按下Alt + 数字,会执行对应操作。


注意,按下快捷键时,鼠标要定位到解决方案资源管理器上面,不然会报错




参见:


http://www.cnblogs.com/zhangronghua/archive/2010/05/12/Colloapse_Expand_Macro.html
========

VS2010自定义宏注释模板



通过宏IDE进行宏编辑从而达到在编码时实现自动添加注释的作用。
操作有两个步骤:
1、编辑宏注释
2、为宏添加快捷键方便操作。
下面详说以上两步:
1、VS2010->工具->宏(Macros)->宏IDE。
接着就是在宏编辑的IDE环境中,添加新项->新建名称->宏编辑(参照模板)->保存->返回VS2010。
2、VS2010->工具->选项(Options)->环境下的键盘->在显示命令包含:的方框中输入第一步新建的宏注


释的名字->选择该宏注释->定义快捷键(按个人喜欢,不要有冲突)->快捷键用于全局->分配->确定。
以上就已经做好了你的宏注释模板了,在以后的个人编程和团队工作时就可以采用这样的方式进行统一


化注释规则。
宏注释模板:
Sub AddFunComment()
        Dim DocSel As EnvDTE.TextSelection
        DocSel = DTE.ActiveDocument.Selection
        DocSel.NewLine()
        DocSel.Text = ""
    End Sub
以上学习于http://blog.chinaunix.net/uid-21375345-id-3085290.html。
========
使用宏来完成一些烦琐的代码


  在 Visual Studio 2012 之前的版本,当有些效果我们经常会使用但又无法单纯的用一个快捷命令


来实现时,就可以通过宏来创建自己的快捷命令。但是 Microsoft 再考虑到自定义宏的维护成本过高而


且只支持VB,因此抛弃了对它的支持。




  下面的演示只限于 Visual Studio 2012 之前的版本。


  通过录制宏来实现一个最简单的功能


  1. 打开 工具 / 宏 / 录制宏

  2. 在代码编辑器中输入


Console.WriteLine("Hi");
 
  3. 点击停止录制宏


  打开 工具 / 宏 / 宏资源管理器,找到 RecordingModule 并展开,双击 TemporaryMacro。这个时


候会发现编辑器光标所在的位置已经自动插入了一条 “Console.WriteLine("Hi")” 代码。

动画演示:如何创建一个最简单的宏

  本节只演示宏的基本功能,更多关于宏的高级用法,请见《Visual Studio 宏的高级用法》。
 


  注:2014年2月之后,Windows的一次更新将导致 Visual Studio 无法运行 macro,按照该文章的方


法修改三个配置文件即可以修复。


 
========

Visual Studio 宏的高级用法


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

Visual Studio 2010 或更早期版本的 VS。

  在上一篇中,我已经介绍了如何编写一个最简单的宏,本文将进一步介绍如何用宏来实现对代码编

辑窗口控制。在本文结束的时候,你应该能自己实现如下两个功能,第一个用于对方法体进行 phase0 

标记;第二个可以将当前窗口中的代码进行归类,将所有方法、属性、变量通过region进行分块。



动画演示:phase0 




动画演示:设置 region


为什么使用宏


  在计算机行业内,宏的出现由来已久,因为它能替代人们执行一些重复发生的简单但烦琐的事情,


所以广受人们欢迎。在 Visual Studio 中也提供了进行宏编程的方法,从而方便开发人员录制一些宏脚


本来扩展Visual Studio,以提高开发效率。


  要想在 Visual Studio 中操作宏来操控代码编辑窗口,就必须要了解如下几个东东:EnvDTE、DTE


、TextSelection、EditPoint。宏可实现地远不止是操控代码编辑窗口,关于其它能力请见参考资源[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]。


复制代码
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 宏的高级用法》


========

使用Visual Studio 2005 IDE的宏,自动为c#变量生成属性



在编写c#代码过程中,我们经常需要做一些重复枯燥的工作。例如,编写DTO(数据访问对象),通常就


是为一个类定义一系列的变量和属性。


有一些第三方的IDE辅助工具,可以为我们生成一些代码,减少工作量。例如,Assist X就是一款很值得


推荐的工具,使用其提供的Encapsulate Field功能,可以很方便地将一个类地编写封装为属性。


我今天需要介绍的如何使用Visual Studio 2005 IDE中自带的宏实现类似的功能。


打开Visual Studio 2005 IDE,选择“工具” > "宏" > “宏 IDE”,选择“添加模块”。例如,我是


在MyMacros项目中新增了一个EditorHelper模块,代码如下:


Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Public Module EditorHelper
    '为一个参数封装一般属性访问器
    Public Sub EncapsulateField()
        Dim projectItem As ProjectItem = DTE.ActiveDocument.ProjectItem
        Dim fileCodeModel As FileCodeModel = projectItem.FileCodeModel


        '得到当前选定的内容
        Dim selectText As TextSelection = DTE.ActiveDocument.Selection
        '获取到当前光标的位置
        Dim point As TextPoint = selectText.ActivePoint


        Try
            Dim codeElement As CodeElement = fileCodeModel.CodeElementFromPoint(point, 


vsCMElement.vsCMElementVariable)


            If (codeElement Is Nothing) Then
                Return
            End If


            Debug.Assert(codeElement.Kind = vsCMElement.vsCMElementVariable)


            Dim codeVar As CodeVariable = CType(codeElement, CodeVariable)
            Dim fieldName As String = codeVar.Name
            Dim codeClass As CodeClass = CType(codeVar.Parent, CodeClass)


            AddPropertyToClass(codeClass, fieldName, codeVar.Type)
        Catch ex As Exception
            '吃掉异常,不做处理或者提示
        End Try


    End Sub


    Public Sub EncapsulateAllFields()
        Dim projectItem As ProjectItem = DTE.ActiveDocument.ProjectItem
        Dim fileCodeModel As FileCodeModel = projectItem.FileCodeModel


        Try
            '得到当前选定的内容
            Dim selectText As TextSelection = DTE.ActiveDocument.Selection
            '获取到当前光标的位置
            Dim point As TextPoint = selectText.ActivePoint


            Dim codeElement As CodeElement = fileCodeModel.CodeElementFromPoint(point, 


vsCMElement.vsCMElementClass)
            Dim codeClass As CodeClass = CType(codeElement, CodeClass)


            Dim i As Integer
            For i = 1 To codeClass.Members.Count
                '如果属性已经定义,会抛出异常
                '在这里处理异常,即使新增的属性已经定义,也可以继续处理下面的代码
                Try
                    Dim element As CodeElement = codeClass.Members.Item(i)
                    If (element.Kind = vsCMElement.vsCMElementVariable) Then
                        Dim codeVariable As CodeVariable = CType(element, CodeVariable)
                        If (Not codeVariable.IsShared) Then     '静态变量不需要增加属性
                            AddPropertyToClass(codeClass, codeVariable.Name, 


codeVariable.Type)
                        End If
                    End If
                Catch ex As Exception
                    '吃掉异常
                End Try
            Next
        Catch ex As Exception
            '可能并没有选择有效的类定义,这时会抛出异常,忽略
        End Try
    End Sub


    '根据成员的名称的类型,在类对象中插入属性
    Private Sub AddPropertyToClass(ByVal codeClass As CodeClass, ByVal fieldName As String, 


ByVal fieldType As Object)
        '生成属性的名称,规则是首先字母大写。如果变量的开头为“_”,移除
        Dim propertyName As String = fieldName
        If (propertyName.StartsWith("_")) Then
            propertyName = propertyName.TrimStart("_"c)
        End If
        propertyName = propertyName.Substring(0, 1).ToUpper() & propertyName.Substring(1)


        '创建属性对象
        '-1表示代码插入到类的最下方
        'vsCMAccess.vsCMAccessPublic表示为public
        Dim codeProperty As CodeProperty = codeClass.AddProperty(propertyName, 


propertyName, fieldType, -1, vsCMAccess.vsCMAccessPublic)
        'Getter
        Dim getter As CodeFunction = codeProperty.Getter
        Dim getterPoint As TextPoint = getter.GetStartPoint(vsCMPart.vsCMPartBody)
        Dim getterEditPoint As EditPoint = getterPoint.CreateEditPoint()
        getterEditPoint.Delete(getter.GetEndPoint(vsCMPart.vsCMPartBody))
        getterEditPoint.Insert(vbCrLf)      '插入回车符
        getterEditPoint.LineUp()
        getterEditPoint.Indent(, 4)         '缩进4个位置
        getterEditPoint.Insert("return " & fieldName & ";")
        'Setter
        Dim setter As CodeFunction = codeProperty.Setter
        Dim setterPoint As TextPoint = setter.GetStartPoint(vsCMPart.vsCMPartBody)
        Dim setterEditPoint As EditPoint = setterPoint.CreateEditPoint()
        setterEditPoint.Insert(vbCrLf)     '插入回车符
        setterEditPoint.LineUp()
        setterEditPoint.Indent(, 4)         '缩进4个位置
        setterEditPoint.Insert(fieldName & " = value;")
    End Sub
End Module


我定义了两个Public方法:EncapsulateField和EncapsulateAllFields,分别用于为类的一个变量封装


属性,或者为类中所有的变量(非静态)封装属性。


使用上面的宏的方法很简单,选择“工具”>“宏”>“宏资源管理器”就可以看到我们已经创建的宏方


法,如下图所示:




假如你已经编写了这样一段代码:


using System;
using System.Collections.Generic;
using System.Text;
namespace Demo
{
    public class Person
    {
        private int _id;
        private string _name;
        private DateTime _birthDay;
    }
}


将光标移到“_name”变量上,然后双击“EncapsulateField”宏,就运行了该宏。运行后,你可以得到


这样的代码:


using System;
using System.Collections.Generic;
using System.Text;
namespace Demo
{
    public class Person
    {
        private int _id;
        private string _name;
        private DateTime _birthDay;


        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }
    }
}


可以看到“EncapsulateField”宏已经为private string _name;创建了相应的属性。
EncapsulateAllFields宏只需要将光标放在Person类的代码区域中,就可以正常执行。例如针对上面的


代码,EncapsulateAllFields后可以为Person类中的每一个变量都生成相应的属性。(注:上面的代码


中Name属性已经有定义,所有试图再添加Name属性时会抛出异常,在EncapsulateAllFields宏定义中,


已经将该异常吃掉,所以,可以正确地为所有变量生成属性)。运行后的代码如下:


using System;
using System.Collections.Generic;
using System.Text;
namespace Demo
{
    public class Person
    {
        private int _id;
        private string _name;
        private DateTime _birthDay;


        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }


        public int Id
        {
            get
            {
                return _id;
            }
            set
            {
                _id = value;
            }
        }


        public System.DateTime BirthDay
        {
            get
            {
                return _birthDay;
            }
            set
            {
                _birthDay = value;
            }
        }
    }
}


在确认上面的宏可以正确运行的情况下,我们还可以为其定义快捷键,进一步提高我们的工作效率。
在Visual Studio 2005 IDE中选择“工具” > “选项”


在“选项”对话框中选择“环境”>“键盘”。
在【显示命令包含】中输入Encap...,可以帮你快速定位到相应的宏命令;
【新快捷键用于】选项中选择“文本编辑器”;
激活【按快捷键】输入框,选择你所希望的快捷键,例如我这里为EncapsulateField定义的快捷键


为“Ctrl + `”,为EncapsulateAllFields定义的快捷键为“Ctrl + Shift + `”
点击分配按钮


你就可以在文本编辑器中尽情享用宏给你带来的方便。


补充在Visual Studio 2003中使用的宏:
Visual Studio 2003 IDE与Visual Studio 2005 IDE在处理上稍微有些不一致的地方,需要做如下的调


整:


Imports System
Imports EnvDTE
Imports System.Diagnostics
Public Module EditorHelper
    '为一个参数封装一般属性访问器
    Public Sub EncapsulateField()
        Dim projectItem As ProjectItem = DTE.ActiveDocument.ProjectItem
        Dim fileCodeModel As FileCodeModel = projectItem.FileCodeModel


        '得到当前选定的内容
        Dim selectText As TextSelection = DTE.ActiveDocument.Selection
        '获取到当前光标的位置
        Dim point As TextPoint = selectText.ActivePoint


        Try
            Dim codeElement As CodeElement = fileCodeModel.CodeElementFromPoint(point, 


vsCMElement.vsCMElementVariable)


            If (codeElement Is Nothing) Then
                Return
            End If


            Debug.Assert(codeElement.Kind = vsCMElement.vsCMElementVariable)


            Dim codeVar As CodeVariable = CType(codeElement, CodeVariable)
            Dim fieldName As String = codeVar.Name
            Dim codeClass As CodeClass = CType(codeVar.Parent, CodeClass)


            AddPropertyToClass(codeClass, fieldName, codeVar.Type)
        Catch ex As Exception
            '吃掉异常,不做处理或者提示
            MsgBox(ex.Message)
        End Try


    End Sub


    Public Sub EncapsulateAllFields()
        Dim projectItem As ProjectItem = DTE.ActiveDocument.ProjectItem
        Dim fileCodeModel As FileCodeModel = projectItem.FileCodeModel


        Try
            '得到当前选定的内容
            Dim selectText As TextSelection = DTE.ActiveDocument.Selection
            '获取到当前光标的位置
            Dim point As TextPoint = selectText.ActivePoint


            Dim codeElement As CodeElement = fileCodeModel.CodeElementFromPoint(point, 


vsCMElement.vsCMElementClass)
            Dim codeClass As CodeClass = CType(codeElement, CodeClass)


            Dim i As Integer
            For i = 1 To codeClass.Members.Count
                '如果属性已经定义,会抛出异常
                '在这里处理异常,即使新增的属性已经定义,也可以继续处理下面的代码
                Try
                    Dim element As CodeElement = codeClass.Members.Item(i)
                    If (element.Kind = vsCMElement.vsCMElementVariable) Then
                        Dim codeVariable As CodeVariable = CType(element, CodeVariable)
                        If (Not codeVariable.IsShared) Then     '静态变量不需要增加属性
                            AddPropertyToClass(codeClass, codeVariable.Name, 


codeVariable.Type)
                        End If
                    End If
                Catch ex As Exception
                    '吃掉异常
                End Try
            Next
        Catch ex As Exception
            '可能并没有选择有效的类定义,这时会抛出异常,忽略
            MsgBox(ex.Message)
        End Try
    End Sub


    '根据成员的名称的类型,在类对象中插入属性
    Private Sub AddPropertyToClass(ByVal codeClass As CodeClass, ByVal fieldName As String, 


ByVal fieldType As Object)
        '生成属性的名称,规则是首先字母大写。如果变量的开头为“_”,移除
        Dim propertyName As String = fieldName
        If (propertyName.StartsWith("_")) Then
            propertyName = propertyName.TrimStart("_"c)
        End If
        propertyName = propertyName.Substring(0, 1).ToUpper() & propertyName.Substring(1)


        '创建属性对象
        '-1表示代码插入到类的最下方
        'vsCMAccess.vsCMAccessPublic表示为public
        Dim codeProperty As CodeProperty = codeClass.AddProperty(propertyName, 


propertyName, fieldType, -1, vsCMAccess.vsCMAccessPublic)
        'Getter
        Dim getter As CodeFunction = codeProperty.Getter
        Dim getterPoint As TextPoint = getter.GetStartPoint(vsCMPart.vsCMPartBody)
        Dim getterEditPoint As EditPoint = getterPoint.CreateEditPoint()
        getterEditPoint.Delete(getter.GetEndPoint(vsCMPart.vsCMPartBody))
        getterEditPoint.Insert("get{ return " & fieldName & "; }")
        'Setter
        Dim setter As CodeFunction = codeProperty.Setter
        Dim setterPoint As TextPoint = setter.GetStartPoint(vsCMPart.vsCMPartBody)
        Dim setterEditPoint As EditPoint = setterPoint.CreateEditPoint()
        setterEditPoint.Delete(setter.GetEndPoint(vsCMPart.vsCMPartBody))
        setterEditPoint.Insert("set{ " & fieldName & " = value; }")
    End Sub
End Module


另外,在2003中使用EncapsulateAllFields的宏时,也需要注意一点:在使用时,光标的应该停留在类


定义的空白位置,否则使用Dim codeClass As CodeClass = CType(codeElement, CodeClass)方法不能


正确获取到类对象(例如,如果光标在构造函数里,获取到的是构造函数对象,这点与2005还是有所区


别的)。
========

使用宏(Macro)扩展Visual Studio IDE



虽然有很多工具可以开发.NET程序,但我相信大多数的开发人员都是用Visual Studio(简称VS)。VS是


微软所提供的一款集成开发工具,其最新版本为VS 2008。


VS使用起来还不错,不是吗?而且它还可以被我们进行扩展,按照我们自己的需求。这的确是挺诱人的


,对吧?


认真说起来,扩展VS的IDE有很多方法,例如你可以通过创建一个所谓的"Visual Studio外接程序",这


个外接程序其实就是一个实现了IDTExtensibility2接口的程序集。


t4


关于外接程序的具体细节,不是我们这次讨论的内容。你可以通过下面地址了解


http://msdn2.microsoft.com/zh-cn/library/ms165620(VS.80).aspx
 


外接程序的好处是可以比较集中地封装大量复杂的扩展,同时也易于分发。但相对来说,所需要的能力


也较高。相对比而言,另外一个扩展方法——宏扩展——则比较适合轻量级的扩展。它的实现方式相对


较为容易。我们下面就以一个例子来说明如何创建宏,如何运行宏,实现某些有意思的事情。


我们今天要解决的问题是这样的:


大家知道,每个解决方案或项目都有一个相对应的文件目录。我们经常需要定位到这些目录。以前的做


法是(以项目为例):


1)先选中该项目


2)在它属性中,复制它的"项目文件夹"这个属性值


3)打开"开始"=>"运行"命令,粘贴那个路径,然后回车


这些操作没有什么技术含量,地球人都知道怎么做。但经常这么做,显然不符合和谐社会的要求。试想


,如果能在解决方案或者项目的快捷菜单中,就有一个命令,可以一次性做这样的事情,那该多好啊


很多事情并不难,尤其是当我们以认真的态度正视它的时候。为了实现上述要求,我们只需要写一个简


单的宏。的确如此简单!


1)通过ALT+F8 打开宏资源管理器


2)在宏资源管理器中,定位到MyMacros,右键中选择"新建模块",给新的模块命名为


ProjectContextMenu或者其他你喜欢的名字。


3)双击刚才新建的模块,把以下的代码复制到接下来打开的一个设计器中,并保存。


Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Imports System.IO


'这个模块主要是用来为项目添加一些特殊的上下文菜单操作
Public Module ProjectContextMenu
    '这个方法是定位到当前项目的目录
    Public Sub NavigateToProjectPath()
        Dim proj As EnvDTE.Project
        proj = DTE.ActiveSolutionProjects(0) '定位到当前的项目
        Dim path As String
        path = System.IO.Path.GetDirectoryName(proj.FullName) '取得当前项目所在的目录


        Dim process As New System.Diagnostics.Process
        process.Start("Explorer.exe", path) '打开资源管理器
    End Sub


    '这个方法是定位到解决方案的目录
    Public Sub NavigateToSolutionPath()
        Dim sln As EnvDTE.Solution
        sln = DTE.Solution '取得当前解决方案
        Dim path As String
        path = System.IO.Path.GetDirectoryName(sln.FullName) '取得当前解决方案的目录
        Dim process As New System.Diagnostics.Process
        process.Start("Explorer.exe", path) '打开资源管理器
    End Sub
End Module


这样我们的宏就做好了,你可以直接执行那两个方法。看,是不是很神奇呢。它打开了当前项目的文件


夹。


t3


当然,我们还差最后一步没有完成。那就是把这两个方法关联到内置菜单里面去。


1)你需要通过以下路径打开自定义工具栏的对话框。"视图"=〉"工具栏"==〉"自定义"


2)在"自定义"对话框中,选中"上下文菜单",你会发现所有内置的快捷菜单都显示在顶部了


t7


3)把两个宏方法拖拽到相应的快捷菜单里面去


t6 


下面是配置好之后的效果:多出了两个菜单,分别都指向了上面写好的两个方法。单击这个菜单,就可


以很方便地定位到项目或者解决方案的根目录,免去了复制,然后粘贴到运行窗口的劳动。


t1 t


 
附加资源:


Visual Studio自动化对象模型。如果确实有兴趣的朋友可以认真看一下(要想写出高质量的VS IDE扩展


程序或插件,必须对该模型有较深入的认识)


Vs自动化模型图


如果你的机器上装好了MSDN,那么也可以通过下面的导航,了解到更加详细的信息


ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_extcore/html/4173a963-7ac7-


4966-9bb7-e28a9d9f6792.htm
 


最后,你还可以下载VS Sdk进行更加深入的了解


http://download.microsoft.com/download/9/a/1/9a1b39c4-cf38-4e40-b0b8-


aac1b34fc70a/VsSDKFebruary2007.exe


分类: 其他,Microsoft .NET
========

Visual Studio 宏

https://msdn.microsoft.com/zh-cn/library/b4c73967(v=vs.100).aspx
Visual Studio 2010 其他版本 
宏是组合到一起形成一个命令以自动完成某项任务的一系列命令和指令。 宏允许自动重复操作。 


Visual Studio 包括宏集成开发环境 (IDE),该开发环境专门用于创建、操作、编辑和运行宏。 宏 IDE 


与 Visual Studio IDE 相互独立。
本节内容
如何:录制宏
描述如何创建和录制宏。
如何:运行宏
讨论各种运行宏和传递参数的方法。
宏的录制和运行问题
提供录制和运行宏时的常见问题的解决方案。
如何:管理宏
描述如何编辑现有宏或手动创建新宏。
调试宏
讨论在宏中出现错误时的解决方法。
如何:管理宏
描述宏资源管理器及其上下文菜单。
保存和导出宏文件
描述如何在宏 IDE 中保存和导出宏文件。
宏 IDE 与 Visual Studio IDE 之间的功能差异
描述 Visual Studio 宏和 Visual Studio 之间在扩展性模型、Document 对象、属性、项操作、Find 


方法、项目以及工具选项方面的差异。
如何:在宏中引用 COM 和 .NET Framework 组件
描述如何使用 Tlbimp 实用工具使 Visual Studio 宏能够引用 COM 组件。
如何:在宏中处理环境事件
讨论 EnvironmentEvents 模板、OnMacrosRuntimeReset 事件和 OnStartupComplete 事件。
宏安全性和共享问题
讨论与宏有关的主要安全问题:知识产权保护和病毒的预防与保护。
宏示例
列出并描述 Visual Studio 中所包括的宏示例。
相关章节
使用宏自动执行重复性操作
提供对如何使用宏以使过程或重复的击键序列自动化的概述。
宏开发环境
描述宏 IDE 中的所有对话框。
Macros
提供有关 Macros 对象的详细信息,该对象表示 Visual Studio 宏记录器。
Visual Studio Macros Error Messages
列出与 Visual Studio 宏关联的所有错误消息。
如何:使用外接程序控制宏
描述如何使用 Visual Studio 自动化模型的 Macros 对象来控制在 IDE 中记录的宏,包括暂停和重新


激活记录器、向所记录的宏中写入代码以及确定记录器当前是否正在运行。
========

让Visual Studio 也支持JS代码折叠

      Visual Studio的代码折叠功能非常好用,#region #endregion 这个词连搜狗的词库里面都出现


了(不含'#'号),可见使用频率很高,但是他不支持js的代码折叠 : ( 最近Ext用得比较多,一写就是上


百行JS代码,非常不方便,想着自己写个扩展或插件什么的,意外搜到了下面的文章,已经用宏来实现


了,本文可以理解为该文的简单译本,注意宏代码部分我有所改动 : )
 


文章


      1.      Using #region Directive With JavaScript Files in Visual Studio
 


环境


      Microsoft Visual Studio 2008
 


正文


      1.      打开宏资源管理器:视图 -> 其他窗口 -> 宏资源管理器


      2.      创建一个新模块
  


  3.  编辑宏:  选中模块 -> 右键编辑

Option Strict Off
Option Explicit Off

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Imports System.Collections

Public Module JsMacros

    Sub OutlineRegions()
        Dim selection As EnvDTE.TextSelection = DTE.ActiveDocument.Selection

        Const REGION_START As String = "//#region"
        Const REGION_END As String = "//#endregion"

        selection.SelectAll()
        '农民伯伯 --- 自动为"//#endregion"结束的代码添加最后一行,不然出错
        If selection.Text.EndsWith(REGION_END) Then
            selection.EndOfLine()
            selection.NewLine()
            selection.SelectAll()
        End If

        Dim text As String = selection.Text
        selection.StartOfDocument(True)

        Dim startIndex As Integer
        Dim endIndex As Integer
        Dim lastIndex As Integer = 0
        Dim startRegions As Stack = New Stack()

        Do
            startIndex = text.IndexOf(REGION_START, lastIndex)
            endIndex = text.IndexOf(REGION_END, lastIndex)

            If startIndex = -1 AndAlso endIndex = -1 Then
                Exit Do
            End If

            If startIndex <> -1 AndAlso startIndex < endIndex Then
                startRegions.Push(startIndex)
                lastIndex = startIndex + 1
            Else
                ' Outline region 
                selection.MoveToLineAndOffset(CalcLineNumber(text, CInt(startRegions.Pop())), 1)
                selection.MoveToLineAndOffset(CalcLineNumber(text, endIndex) + 1, 1, True)
                selection.OutlineSection()

                lastIndex = endIndex + 1
            End If
        Loop

        selection.StartOfDocument()
    End Sub

    Private Function CalcLineNumber(ByVal text As String, ByVal index As Integer)
        Dim lineNumber As Integer = 1
        Dim i As Integer = 0

        While i < index
            If text.Chars(i) = vbCr Then
                lineNumber += 1
                i += 1
            End If

            i += 1
        End While

        Return lineNumber
    End Function

End Module

    保存即可。这里可以省去新建宏的步骤,他会根据代码自动给你生成一个宏的。

    注意我加的代码段,如果不加,并且你的JS最后一行为#endregion,宏将报错,显示“值不在

预期的范围内”。 
 

  4.  设置快捷键

    4.1  工具 -> 选项 - > 环境 -> 键盘

    4.2  在显示命令包含下面的文本框中输入宏名outli,不用输全,下面能显示你新建的宏

    4.3  点一下 按快捷键 下面的文本框, 然后自定义快捷键组合,我定义的是Ctrl+M,Ctrl+J

,点分配(别忘了!),点确定。
 
  5.效果

    5.1  输入代码:


//aasdsadsad

//#region
//#endregion
    5.2  快捷键Ctrl+M,Ctrl+J启动宏,能看到系统的右下角显示可爱的小方块在转动,js编辑

框显示效果如下:
   

    5.3  之后就可以用快捷键Ctrl+M,Ctrl+L来[展开/折叠]代码了,注意关闭之后重新打开需要


再启动一次宏,展开效果如下:

========

msdn相关链接

https://msdn.microsoft.com/zh-cn/library/aa291605(v=vs.71).aspx

debugger对象


https://msdn.microsoft.com/zh-cn/library/aa291105(v=vs.71).aspx

公共环境对象模型


https://msdn.microsoft.com/zh-cn/library/68shb4dw(VS.80).aspx

https://msdn.microsoft.com/zh-cn/library/aa301306(v=vs.71).aspx

https://msdn.microsoft.com/zh-cn/library/aa300755

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值