实现Visual Studio 2010一个很简单的很酷的扩展

简介:

基本介绍篇

    在实现这个扩展之前,让我们先弄清楚这个扩展实现什么功能。这个扩展实际上是在你的VS窗口的右上角创建了一个信息框代码。该信息框显示您的源代码的统计信息。这些信息包括:

    1、文件的代码行数
    2、文件的字符数
    3、命名空间的个数
    4、字段个数
    5、接口个数
    6、类的个数
    7、函数个数
    8、属性个数
    9、注释的数量
   10、统计文件的大小(Bytes, KB, MB等)。

    当您键入您的代码,你会看到信息窗口中的数据会即时更新。

    这个信息窗口,是利用可扩展面板。你可以把它看成两个部分,每一个部分都可以根据您的需要展开和折叠。这样,当你不需要它时,你将它可以折叠起来,需要的时候,将它展开。下面演示如何展开/折叠这个控件。

 

    这个控件有三个特殊的状态。第一个状态是一个很小的扩展按钮。如上图的第一部分。只需点击它,就会打开控件右侧的面板,这个面板显示文件的基本数据,如上图的第二部分。这个控件还有一个可扩展面板,如果点击扩展,就会看到下面的面板,其中显示其他的统计数据,如上图的第三部分。

实现篇:

    需要软件:

    1、 Microsoft Visual Studio 2010
    2、 Visual Studio 2010 SDK

    你安装 Visual Studio SDK之后,你的Visual Studio 2010中会多出下面这些模板:

    这篇文章中,我们使用模板Editor ViewPort Adornment实现这个扩展,此模板将为你的代码编辑器的带来一个装饰品。 

    其实这个扩展包一个WPF用户控件,我把它放进VS的视窗中就成了信息框。它还含有两个类,一个类用来解析代码,获取代码的相关信息;另一个类用来处理自定义编辑器的事件和当页以及加载的时候将WPF控件添加到页面中。

第一步:创建一个Viewport Adornment项目

    我们从Extensibility中选择Viewport Adornment模板创建一个项目。这将生成一个SourceManifest文件和两个类文件。一个是Adornment类本身,另外一个是AdornmentFactory类。

第二步:添加一个WPF用户控件

    右键单击项目,选择添加一个新的WPF用户控件。为了简单起见,我使用了一个用户控件。这个用户控件实际上包含一个Expander控件,设置它的ExpandDirection = Left,它里面又包含了一些TextBlock控件和另外一个Expander ,设置里面的这个Expander的ExpandDirection = Down。看下面的代码(我删除不必要的元素,使其更简单):

复制代码
 1     < Expander  ExpandDirection ="Left"  Style =" {DynamicResource ExpanderStyle1} "  
 2             x:Name ="expMain"   >
 3     < StackPanel >
 4                   < TextBlock  x:Name ="txtNoLines"  
 5                             Text ="No of Lines : {0}"  
 6                             Margin ="25 25 25 0"  
 7                             FontSize ="12"  
 8                             FontFamily ="Verdana"  
 9                             FontWeight ="Bold"  
10                             Foreground ="Yellow" ></ TextBlock >
11                   < TextBlock  x:Name ="txtNoCharacters"  
12                             Text ="No of Characters : {0}"  
13                             Margin ="25 5 25 15"  
14                             FontSize ="12"  
15                             FontFamily ="Verdana"  
16                             FontWeight ="Bold"  
17                             Foreground ="Yellow" ></ TextBlock >
18                   < Expander  x:Name ="expCodeInfo"  ExpandDirection ="Down"  
19                                       Header ="Code Information" >
20                       < StackPanel >
21                           < TextBlock  x:Name ="txtClassInfo"  
22                                     Margin ="25 25 25 0"  
23                                     FontSize ="12"  
24                                     FontFamily ="Verdana"  
25                                     FontWeight ="Bold"  
26                                     Foreground ="LightYellow" />
27                           < Line
28                                 Margin ="0,4"
29                                SnapsToDevicePixels ="True"
30                                Stroke ="Gold"
31                                Stretch ="Fill"
32                                X1 ="0"  X2 ="1"  
33                                 />
34                           < TextBlock  x:Name ="txtFileSize"
35                                     Margin ="25 5 25 15"  
36                                     FontSize ="12"  
37                                     FontFamily ="Verdana"  
38                                     FontWeight ="Bold"  
39                                     Foreground ="AliceBlue" />
40                       </ StackPanel >
41                   </ Expander >
42               </ StackPanel >
43            </ Expander >
复制代码

    你可以看到,代码很简单,两个Expanders,一个用来显示基本的统计信息和另外一个显示扩展的统计信息。我还使用StackPanel来固定TextBlocks布局。

    现在,如果你看一下后台代码,发现它也一样简单。其实我已经创建了一个CodeInfoTracker类,用它来为我们分析源代码文件。我只是为我们的用户控件添加了一个构造函数,使用户控件更具扩展性而已。

复制代码
 1  private  CodeInfoTracker _cinfo;
 2  private  CodeInfoTracker.Calculators _calculator;
 3  public  ucInfoBox(CodeInfoTracker cinfo)
 4              :  this ()
 5  {
 6           this ._cinfo  =  cinfo;
 7  }
 8    public   void  UpdateInfo(CodeInfoTracker info)
 9   {
10              _calculator  =  info.PerFormCalculate();
11               this .txtNoLines.Text  =   string .Format( " No of Lines : {0} "
12                                      _calculator.no_of_lines);
13               this .txtNoCharacters.Text  =   string .Format( " No of Characters : {0} "
14                                                         _calculator.no_of_characters);
15               this .txtFileSize.Text  =   string .Format( " Total File Size : {0} "
16                                                         _calculator.totalfilesize);
17 
18              StringBuilder builder  =   new  StringBuilder();
19               if  ( this ._calculator.interfaces  !=   0 )
20                  builder.AppendFormat( " Interfaces : {0}\n\r "
21                                             this ._calculator.interfaces);
22               if  ( this ._calculator.namespaces  !=   0 )
23                  builder.AppendFormat( " NameSpaces : {0}\n\r "
24                                               this ._calculator.namespaces);
25               if  ( this ._calculator.classes  !=   0 )
26                  builder.AppendFormat( " Classes : {0}\n\r "
27                                               this ._calculator.classes);
28               if  ( this ._calculator.methods  !=   0 )
29                  builder.AppendFormat( " Methods : {0}\n\r " this ._calculator.methods);
30               if  ( this ._calculator.properties  !=   0 )
31                  builder.AppendFormat( " Properties : {0}\n\r "
32                                                  this ._calculator.properties);
33               if  ( this ._calculator.fields  !=   0 )
34                  builder.AppendFormat( " Fields : {0}\n\r " this ._calculator.fields);
35               if  ( this ._calculator.comments  !=   0 )
36                  builder.AppendFormat( " Comments : {0}\n\r " this ._calculator.comments);
37 
38               if  (builder.Length  >   0 )
39              {
40                   this .txtClassInfo.Visibility  =  System.Windows.Visibility.Visible;
41                   this .txtClassInfo.Text  =  builder.ToString();
42              }
43               else
44              {
45                   this .txtClassInfo.Text  =   "" ;
46                   this .txtClassInfo.Visibility  =  System.Windows.Visibility.Hidden;
47         }
48    }
复制代码

    使用了一个结构体Calculators ,这个结构体放置在我们的自定义类中,它有几个int属性用来保存分析源文件获取的所有信息。 info.PerFormCalculate(); 给出分析的结果。这里使用的所有获取的信息来更新了UIElements。

第三步:创建获取源文件信息的类

    虽然代码存在一些复杂性,但是这个类其实很简单。我很感谢CS Parser [^],它帮助我自动地解析源代码。   

    这个类需要一个IWpfTextView对象,它代表着Visual Studio文本编辑器。实际上WpfTextView实现了IWpfTextView。在执行期间这个类接受这个对象。我可以从WPFTextView.TextSnapshot.GetText()获得到了源代码。
    在我调用的这个分析的时候,我只需要检测的代码是什么语言写的。开始我想自己来实现,但是感谢上帝,我在WPFTextView中发现已经存在这个对象了。

复制代码
 1  public   enum  Language
 2  {
 3          CSharp, VisualBasic, Indeterminate
 4  }
 5  internal  Language DetectLanguage
 6  {
 7               get
 8              {
 9                   string  langtype  =  
10           this ._view.FormattedLineSource.TextAndAdornmentSequencer.
11          SourceBuffer.ContentType.DisplayName;
12                   if (langtype.Equals( " CSHARP "
13              StringComparison.InvariantCultureIgnoreCase))
14                       return  Language.CSharp;
15                   else   if (langtype.Equals( " BASIC "
16                                StringComparison.InvariantCultureIgnoreCase))
17                       return  Language.VisualBasic;
18                   else
19                       return  Language.Indeterminate;
20              }
21  }
复制代码

     DetectLanguage妥善地利用WPFTextView对象的FormattedLineSource.TextAndAdornmentSequencer.
SourceBuffer.ContentType.DisplayName,这个属性
告诉我是使用了哪种语言。之后我创建了一个新的方法PerFormCalculate,用它来解析源代码,它返回一个Calculation结构对象。

第四步:创建 Adornment Factory 类

    回到这个扩展,我创建一个Adornment(InfoBoxAdornmentFactory)的Factory类。这个类继承IWpfTextViewCreationListener,用来监听WPF的编辑和创建事件。

复制代码
 1  [Export( typeof (IWpfTextViewCreationListener))]
 2  [ContentType( " text " )]
 3  [TextViewRole(PredefinedTextViewRoles.Document)] 
 4  internal   sealed   class  InfoBoxAdornmentFactory : IWpfTextViewCreationListener
 5  {
 6          [Export( typeof (AdornmentLayerDefinition))]
 7          [Name( " AlwaysVisibleInfoBox " )]
 8          [Order(After  =  PredefinedAdornmentLayers.Selection)]
 9          [TextViewRole(PredefinedTextViewRoles.Interactive)]
10           public  AdornmentLayerDefinition editorAdornmentLayer  =   null ;
11           public   void  TextViewCreated(IWpfTextView textView)
12          {
13               new  AlwaysVisibleInfoBox(textView);
14          }
15   } 
复制代码

    这里,你可以看到我在这个类上使用了很多Attributes,像ContentType,它定义了我们只处理文本格式的编辑器;还有TextViewRole,它定义了将被这个类处理的textview的类型

    在这个类中,我创建了一个AdornmentLayerDefination对象。可能你想知道我们没有使用它,无什么还需要定义它呢,它只是用来配置属性的。Order属性指定,当,InfoBox在层被选之后监听,Name是编辑扩展的名字。

第五步:创建Adornment 类

    Adornment类实际创建了一个WPF用户控件对象,并设置它的视图画布。在内部构造函数中,我处理IWpfTextView.LayoutChanged事件,当代码修改或者布局改变的时候,就触发这个事件。因此,通过这一事件,当我们编辑的文档时,我们可以很容易地得到回调。当浏览器编辑器的大小改变时,我还通过处理WPFTextView.ViewportHeightChanged,WPFTextView.ViewportWidthChanged得到回调,使我们可以重新定位相应的UserControl。

复制代码
 1  public  AlwaysVisibleInfoBox(IWpfTextView view)
 2  {
 3            _view.LayoutChanged  +=   this .OnLayoutChanged;
 4             this .GetLayer();
 5  }
 6  private   void  GetLayer()
 7   {
 8              _adornmentLayer  =   this ._view.GetAdornmentLayer( " AlwaysVisibleInfoBox " );
 9              _view.ViewportHeightChanged  +=   delegate  {  this .onSizeChange(); };
10              _view.ViewportWidthChanged  +=   delegate  {  this .onSizeChange(); };
11  }
12    private   void  OnLayoutChanged( object  sender, TextViewLayoutChangedEventArgs e)
13  {
14               this ._info  =   new  CodeInfoTracker(_view);
15               this .infobox.UpdateInfo( this ._info);
16   }
17    public   void  onSizeChange()
18   {
19       
20              _adornmentLayer.RemoveAllAdornments();
21              Canvas.SetLeft(infobox, _view.ViewportRight  -   255 );
22              Canvas.SetTop(infobox, _view.ViewportTop  +   10 );
23              
24            _adornmentLayer.AddAdornment(AdornmentPositioningBehavior.ViewportRelative, 
25             null null
26            infobox,  null );
27  }
复制代码

   因此,构造函数只是调用GetLayer来获取的Layer对象,发生在ViewportHeightChanged和ViewportWidthChanged ViewPortSizeChage事件。当一个布局改变时,我就能更新这个用户的控件。

    至此,我们成功地建立我们的扩展。你可以使用F5运行它,它会打开一个Visual Studio的Experimental实例。

安装和卸载这个扩展:
    安装和卸载这个扩展是非常容易的。当您编译项目后,它会产生一个VSIX文件。您可以只需双击这个文件,它会自动安装到Visual Studio。
   

    要卸载的文件,您打开Visual Studio,转到 Tools - > Extension Manager,然后选择卸载该扩展。

发布您的扩展:

    发布你的扩展到Visual Studio库的方式也非常的酷。只要你需要上传VSIX文件到http://www.visualstudiogallery.com/。我已经上载我的这个扩展。

总结:这篇文章,从头到尾一步一步教你实现一个很简单很酷的VS2010的扩展





本文转自麒麟博客园博客,原文链接:http://www.cnblogs.com/zhuqil/archive/2010/04/15/Visual-Studio-Extension.html,如需转载请自行联系原作者

相关文章
Visual Studio 2022扩展安装MFC(在VS已安装完成的情况下)
Visual Studio 2022扩展安装MFC(在VS已安装完成的情况下)
3616 0
Visual Studio 2022扩展安装MFC(在VS已安装完成的情况下)
|
人工智能 前端开发 JavaScript
提高Java开发效率:5个常用的Visual Studio代码扩展工具
对于软件工程师来说,能够更好地管理时间是一项宝贵的技能。因此,这里有5个Visual Studio代码扩展工具,可以帮助前端开发人员(以及更多的人!)将生产力至少提高10%到20%,下面和小编一起来看看吧!
231 0
提高Java开发效率:5个常用的Visual Studio代码扩展工具
|
开发工具 git
【Visual Studio 2019】上传代码到 GitHub ( 16.9.2 版本 | 安装 GitHub 扩展插件 | 创建 Git 仓库 | 推送到远程仓库 )(二)
【Visual Studio 2019】上传代码到 GitHub ( 16.9.2 版本 | 安装 GitHub 扩展插件 | 创建 Git 仓库 | 推送到远程仓库 )(二)
209 0
【Visual Studio 2019】上传代码到 GitHub ( 16.9.2 版本 | 安装 GitHub 扩展插件 | 创建 Git 仓库 | 推送到远程仓库 )(二)
|
存储 开发工具 git
【Visual Studio 2019】上传代码到 GitHub ( 16.9.2 版本 | 安装 GitHub 扩展插件 | 创建 Git 仓库 | 推送到远程仓库 )(一)
【Visual Studio 2019】上传代码到 GitHub ( 16.9.2 版本 | 安装 GitHub 扩展插件 | 创建 Git 仓库 | 推送到远程仓库 )(一)
265 0
【Visual Studio 2019】上传代码到 GitHub ( 16.9.2 版本 | 安装 GitHub 扩展插件 | 创建 Git 仓库 | 推送到远程仓库 )(一)
|
数据安全/隐私保护
【OpenGL】二、Visual Studio 2019 配置 GitHub ( 下载并安装 GitHub 扩展 | 配置 GitHub )(二)
【OpenGL】二、Visual Studio 2019 配置 GitHub ( 下载并安装 GitHub 扩展 | 配置 GitHub )(二)
155 0
【OpenGL】二、Visual Studio 2019 配置 GitHub ( 下载并安装 GitHub 扩展 | 配置 GitHub )(二)
【OpenGL】二、Visual Studio 2019 配置 GitHub ( 下载并安装 GitHub 扩展 | 配置 GitHub )(一)
【OpenGL】二、Visual Studio 2019 配置 GitHub ( 下载并安装 GitHub 扩展 | 配置 GitHub )(一)
290 0
【OpenGL】二、Visual Studio 2019 配置 GitHub ( 下载并安装 GitHub 扩展 | 配置 GitHub )(一)
|
IDE 开发工具 C#
Visual Studio 2022 Preview 2 发布:扩展跨平台功能,支持实时预览,debug 更高效
Visual Studio 2022 Preview 2 发布:扩展跨平台功能,支持实时预览,debug 更高效
Visual Studio 2022 Preview 2 发布:扩展跨平台功能,支持实时预览,debug 更高效
|
IDE Java 编译器
Android++:为Android App开发而生的Visual Studio的原生扩展
2014年1月27日,随着Android++扩展的出现,Windows平台的开发者所期待的一件事情:通过Visual Studio开发Android App,可以如愿以偿了。
350 0
Android++:为Android App开发而生的Visual Studio的原生扩展
|
Web App开发 Go
一起谈.NET技术,分享一些非常好用的Visual Studio扩展
扩展管理器 Visual Studio 2010新增“扩展管理器”的功能,可用于添加、移除、启用和禁用Visual Studio扩展。我们可以从Visual Studio Gallery(Visual Studio库)网站上安装扩展,这些扩展一般是VSIX包格式,包括项目模板、项模板、工具箱项、托管扩展框架(MEF)组件和VSPackage。
1414 0
一起谈.NET技术,用NuGet掌管你的Visual Studio扩展
  如果你使用Visual Studio 2010,那么 NuGet 可以使你的生活更加美好。当你项目里要引用到的一些库时候,比如JQuery 库或者 NHibernate, NUnit, log4net 你就可以考虑使用NuGet。
836 0