博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
VS2010 Extension实践(1)
阅读量:445 次
发布时间:2019-03-06

本文共 7213 字,大约阅读时间需要 24 分钟。

最近VS2010 Extension在Visual Studio Blog()上提得很频繁,于是也想翻来文档研究研究,结果居然找了半天,居然没有一丁点完整介绍这一块的,于是,只好自己找着VS IDE上的模板提供的内容和Visual Studio Blog上的讲解,一边Reflector参演,一边涂鸦一些代码,准备实弹演练一下,但是觉得这个模板建出来的Extension也太简单了,刚好看到AxTool()有一个代码编辑器扩展,也是VS Extension的,于是就照着这个,自己一步一步做一下。

首先,要想建立VS Extension工程,你需要安装VS2010 SDK,目前是Beta2版本,你可以到这里可以下载:),这里我是通过Editor Text Adornment模板创建的工程,嗯,我就不详细写如何通过模板创建自己Extension工程了,如果你不熟悉这里,可以参考Quan To的这篇帖子——。

建好工程以后,会自动生成TextViewCreationListener,这里实现了IWpfTextViewCreationListener接口,并通过MEF导出IWpfTextViewCreationListener对象:

 

 

[TextViewRole("DOCUMENT")][Export(typeof(IWpfTextViewCreationListener))][ContentType("text")]internal sealed class PETextViewCreationListener : IWpfTextViewCreationListener    {        void IWpfTextViewCreationListener.TextViewCreated(IWpfTextView textView)        {            //...        }}

 

这样VS就会在合适的时候调用IWpfTextViewCreationListener.TextViewCreated方法来通知文字编辑的状态改变。

为了实现浮动一个自己的工具栏,这里还需要导出一个AdornmentLayerDefinition,并通过Order Attribute来定制这个Adornment层的显示位置和次序:

 

[Name("QuickToolbarAdornmentLayer")]        [Order(After = "Text")]        [Export(typeof(AdornmentLayerDefinition))]        public AdornmentLayerDefinition QuickToolbarLayerDefinition        {            get;            set;        }

 

这里的Name Attribute很重要,以后的代码中要获取我们的AdornmentLayer就得靠它了:

 

this._adornmentLayer = this._textView.GetAdornmentLayer("QuickToolbarAdornmentLayer");

 

扯得远了,回到IWpfTextViewCreationListener.TextViewCreated,通过这里,可以得到一个IWpfTextView,

这是所有操作的目标和展现,另外,还需要挂他的Closed、LayoutChanged、MouseHovered、SelectionChanged等事件,以响应用户行为。

由于我们要通过工具栏操作代码,所以需要通过MEF导入IEditorOperationsFactoryService:

 

[Import]        internal IEditorOperationsFactoryService EditorOperationsFactoryService        {            get;            set;        }

 

这样就可以在IWpfTextViewCreationListener.TextViewCreated中通过IEditorOperationsFactoryService.GetEditorOperations(ITextView)来获得IEditorOperations,有了它,就可以方便快捷的编辑代码了。

接下来要实现工具栏的界面,这个就不多说了,建一个UserControl,里面放上ToolBar就搞定了。那么何时何地显示这个ToolBar呢?这就要依赖IWpfTextView的SelectionChanged事件了,上面提到会挂这个事件就是为这里用的。

 

1                 private void MayBeAdornmentShowCondition() 2                 { 3                     if (!this._textView.Selection.IsEmpty) 4                     { 5                         SnapshotPoint startPos = this._textView.Selection.Start.Position; 6                         SnapshotPoint endPos = this._textView.Selection.End.Position; 7                         IWpfTextViewLine textViewLineContainingBufferPosition = this._textView.GetTextViewLineContainingBufferPosition(startPos); 8                         TextBounds characterBounds = textViewLineContainingBufferPosition.GetCharacterBounds(startPos); 9                         TextBounds bounds2 = this._textView.GetTextViewLineContainingBufferPosition(endPos).GetCharacterBounds(endPos);10                         if (this._fromMouseHover)11                         {12                             this._mustHaveAdornmentDisplayed = true;13                         }14                         else15                         {16                             PELeftButtonMouseProcessor property = null;17                             try18                             {19                                 property = this._textView.Properties.GetProperty
(typeof(PELeftButtonMouseProcessor));20 }21 catch22 {23 }24 this._mustHaveAdornmentDisplayed = (property != null)25 && (property.IsLeftButtonDown26 || ((DateTime.Now - property.LastLeftButtonDownTime).TotalMilliseconds < 400.0));27 }28 if (this._mustHaveAdornmentDisplayed)29 {30 TextBounds selectionBounds = !this._textView.Selection.IsReversed ? bounds2 : characterBounds;31 int offset = 7;32 double top = selectionBounds.Top + (!this._textView.Selection.IsReversed ? (offset + textViewLineContainingBufferPosition.Height) : (-offset - this._adornmentUI.ActualHeight));33 if (top < 0.0)34 {35 top = 0.0;36 }37 double left = characterBounds.Left + ((bounds2.Left - characterBounds.Left) / 2.0);38 if ((left + this._adornmentUI.ActualWidth) > this._textView.ViewportWidth)39 {40 left = this._textView.ViewportWidth - this._adornmentUI.ActualWidth;41 }42 Canvas.SetTop(this._adornmentUI, top);43 Canvas.SetLeft(this._adornmentUI, left);44 long chars = 0L;45 try46 {47 chars = this._textView.Selection.SelectedSpans[0].Span.Length;48 }49 catch50 {51 }52 this._adornmentUI.SetStatus(chars);53 this.RenderSelectionPopup();54 }55 }56 else57 {58 this._mustHaveAdornmentDisplayed = false;59 this._adornmentLayer.RemoveAdornmentsByTag(this._adornmentTag);60 }61 }62 63 private void RenderSelectionPopup()64 {65 if (this._mustHaveAdornmentDisplayed)66 {67 IAdornmentLayerElement element = null;68 try69 {70 element = this._adornmentLayer.Elements.First
(71 (IAdornmentLayerElement ile) => ile.Tag.ToString() == this._adornmentTag);72 }73 catch (InvalidOperationException)74 {75 }76 if (element == null)77 {78 this._adornmentLayer.AddAdornment(this._textView.Selection.SelectedSpans[0], this._adornmentTag, this._adornmentUI);79 }80 this._timer.Stop();81 this._timer.Start();82 }83 }84 85 private void selection_SelectionChanged(object sender, EventArgs e)86 {87 this._fromMouseHover = false;88 this.MayBeAdornmentShowCondition();89 }

 

 

然后要注意的是IWpfTextView的Closed事件处理要记得取消所有挂这个事件等等收尾工作。

接下来编译工程,打包VSIX就完成了,目前实现的主要Feature:

1、当在代码编辑器中选择一段文字,并将鼠标移到文字区域时,QuickToolbar会以半透明的方式“浮”文字的旁边。

2、当鼠标移到QuickToolbar区域,QuickToolbar会变成不透明,其上的按钮会响应鼠标动作。
3、目前支持的操作有:

  • 剪切(Cut)
  • 复制(Copy)
  • 粘贴(Paste)
  • 删除(Delete)
  • 减小缩进(Decrease Indent)
  • 增加缩进(Increase Indent)
  • 注释代码(Comment)
  • 取消注释(Uncomment)
  • 等等

VSIX和源代码下载以及安装方法在GCDN论坛: ()

转载地址:http://hmufz.baihongyu.com/

你可能感兴趣的文章