VS插件开发 - 个性化VS IDE编辑器
废话不多说,先show几张示例图吧。
之前的默认的VS界面:
主题也只有默认的两三个,而且不能自定义添加:
这距离我们的目标,自定义主题、背景、透明等等,感觉貌似相差甚远:
其实,整体步骤非常简单,大家想一下:我们不能直接去设置更改VS的东西,但是VS不是有一个插件的功能么?
那我们能不能自己写一个插件,来设置VS的相关功能,最后实现这个效果呢?答案是:那是必须的。呵呵。
大概步骤如下:
1.创建VS插件项目,在启动时读取指定图片资源,填充VS的IDE编辑器
2.使用现有插件设置相应模块的透明色
具体步骤如下:
【一、准备工作】
VS提供了一个“Visual Studio Package”项目的模板,我们可以根据这个模板,创建一个VS的插件项目,以此开发相应的插件。
但是这个项目模板有的Visual Studio安装包中并没有默认附带,需要另行下载。
我使用的是VS2012,自带默认就有,VS2013自测没有,VS2010貌似也有 以前用的记不清了,如果没有这个模板需要另行下载,其他版本大家自己看看。
“新建项目 - 模板 - 其他项目类型 - Visual Studio Package”:
如果你发现你的VS新建项目中,在模板列表中找不到“Visual Studio Package”,大家可以去搜索或直接微软官网软件下载找“Visual Studio SDK ****”,****表示你的VS版本,不同版本的VS,SDK不同。
下载后,是在线安装程序,大概也就十几M,在线安装的SDK大小也就一百多M,非常快。(安装注意最好关闭VS哦。)
安装成功后,你打开VS,新建项目,就可以看到这个项目模板了。
【二、新建项目】
打开VS - “新建项目 - 其他项目类型 - Visual Studio Package”,项目名称随意,比如我的“Guying.Package.IDEBackground”:
然后确定:
下一步,开发语言选择你的,在这里我当然选择“Visual C#”啦,哈哈,下面的默认就O了:
下一步,输入公司名称、插件名称、版本号、指定Icon图标、插件说明信息:
下一步,什么都别选:
下一步,不要测试项目:
最后点击Finish完成,项目就创建完成了:
【三、编写插件代码】
找到项目中插件的.cs文件“****Package.cs”:
这个文件就好比“控制台项目”中的“Program.cs”,对,插件运行时,会启动这个代码文件。
我们只需要在这个文件中,插入修改Visual Studio IDE的代码即可。
起初的“***Package.cs”文件中,去掉注释后,只有如下代码:
using System; using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; using System.ComponentModel.Design; using Microsoft.Win32; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.OLE.Interop; using Microsoft.VisualStudio.Shell; namespace LonelyShadow.Guying_Package_IDEBackground { [PackageRegistration(UseManagedResourcesOnly = true)] [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] [Guid(GuidList.guidGuying_Package_IDEBackgroundPkgString)] public sealed class Guying_Package_IDEBackgroundPackage : Package { public Guying_Package_IDEBackgroundPackage() { Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString())); } protected override void Initialize() { Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString())); base.Initialize(); } } }
我们可以发现,包含两个函数:一个无参构造和“Initialize()”方法,这个就不用我介绍了吧,大家都懂的。呵呵。
在这里,我需要说的是,可能大家细心的已经发现了,你在这个项目中新建窗体,显示的是WPF的应用程序。
是的,不仅仅是Vista系统,Visual Studio也是用WPF来开发UI的。
那我们是不是也可以在这个WPF插件项目中来控制VS呢?哈哈。。
①添加需要的WPF等DLL组件引用:
Microsoft.VisualStudio.CoreUtility.dll
Microsoft.VisualStudio.Text.UI.dll
Microsoft.VisualStudio.Text.UI.Wpf.dll
PresentationCore.dll
PresentationFramework.dll
System.ComponentModel.Composition.dll
System.Xaml.dll
WindowsBase.dll
②然后,我们回到“****Package.cs”文件中,找到“Initialize()”初始化的方法中,为当前启动程序(也就是咱们运行的Visual Studio的实例)的主窗口添加Loaded事件:
1 protected override void Initialize() 2 { 3 Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString())); 4 base.Initialize(); 5 6 // 为当前启动程序(Visual Studio)的主窗口添加Loaded事件“MainWindow_Loaded” 7 Application.Current.MainWindow.Loaded += MainWindow_Loaded; 8 } 9 10 为当前启动程序(Visual Studio)的主窗口添加Loaded事件“MainWindow_Loaded”
③然后,当然,编写上面添加的这个“MainWindow_Loaded”的方法,读取指定的图片资源,填充到Visual Studio IDE编辑器中:
1 void MainWindow_Loaded(object sender, RoutedEventArgs e) 2 { 3 var rWindow = (Window)sender; 4 5 //加载图片 6 var rImageSource = BitmapFrame.Create(new Uri(@"E:\\孤影\\照片\\桌面\\shut.jpg"/*图片路径*/), BitmapCreateOptions.None, BitmapCacheOption.OnLoad); 7 rImageSource.Freeze(); 8 9 var rImageControl = new Image() 10 { 11 Source = rImageSource, 12 Stretch = Stretch.UniformToFill, //按比例填充 13 HorizontalAlignment = HorizontalAlignment.Center, //水平方向中心对齐 14 VerticalAlignment = VerticalAlignment.Center, //垂直方向中心对齐 15 }; 16 17 Grid.SetRowSpan(rImageControl, 4); 18 var rRootGrid = (Grid)rWindow.Template.FindName("RootGrid", rWindow); 19 rRootGrid.Children.Insert(0, rImageControl); 20 } 21 22 读取指定的图片资源,填充到Visual Studio IDE编辑器中
在这一步,你可以自我发挥,比如用上IO流,读取一个配置文件,获取配置数据,动态显示等等。是吧。。。。哈哈。
④为了方便调试,请在“****Package.cs”文件的类声明上加上如下属性定义:
1 [ProvideAutoLoad(UIContextGuids.NoSolution)] 2 [ProvideAutoLoad(UIContextGuids.SolutionExists)]
⑤紧接着,新建一个类文件“EditorBackground.cs”,参考代码如下,亲们复制的时候,注意我的命名空间和你的是不是一样的哦:
1 using Microsoft.VisualStudio.Text.Classification; 2 using Microsoft.VisualStudio.Text.Editor; 3 using Microsoft.VisualStudio.Utilities; 4 using System; 5 using System.ComponentModel.Composition; 6 using System.Windows; 7 using System.Windows.Controls; 8 using System.Windows.Media; 9 using System.Windows.Threading; 10 11 namespace LonelyShadow.Guying_Package_IDEBackground 12 { 13 [Export(typeof(IWpfTextViewCreationListener))] 14 [ContentType("Text")] 15 [ContentType("BuildOutput")] 16 [TextViewRole(PredefinedTextViewRoles.Document)] 17 class Listener : IWpfTextViewCreationListener 18 { 19 [Import] 20 IEditorFormatMapService EditorFormatMapService = null; 21 22 public void TextViewCreated(IWpfTextView rpTextView) 23 { 24 new EditorBackground(rpTextView); 25 26 //去掉断点边栏的背景 27 var rProperties = EditorFormatMapService.GetEditorFormatMap(rpTextView).GetProperties("Indicator Margin"); 28 rProperties["BackgroundColor"] = Colors.Transparent; 29 rProperties["Background"] = Brushes.Transparent; 30 } 31 } 32 33 class EditorBackground 34 { 35 IWpfTextView r_TextView; 36 ContentControl r_Control; 37 Grid r_ParentGrid; 38 Canvas r_ViewStack; 39 40 public EditorBackground(IWpfTextView rpTextView) 41 { 42 r_TextView = rpTextView; 43 r_Control = (ContentControl)r_TextView; 44 r_TextView.Background = Brushes.Transparent; 45 r_TextView.BackgroundBrushChanged += TextView_BackgroundBrushChanged; 46 r_TextView.Closed += TextView_Closed; 47 r_Control.Loaded += TextView_Loaded; 48 } 49 void MakeBackgroundTransparent() 50 { 51 r_TextView.Background = Brushes.Transparent; 52 r_ViewStack.Background = Brushes.Transparent; 53 r_ParentGrid.ClearValue(Grid.BackgroundProperty); 54 } 55 void TextView_Loaded(object sender, RoutedEventArgs e) 56 { 57 if (r_ParentGrid == null) 58 r_ParentGrid = (Grid)r_Control.Parent; 59 if (r_ViewStack == null) 60 r_ViewStack = (Canvas)r_Control.Content; 61 MakeBackgroundTransparent(); 62 } 63 void TextView_BackgroundBrushChanged(object sender, BackgroundBrushChangedEventArgs e) 64 { 65 r_Control.Dispatcher.BeginInvoke(new Action(() => 66 { 67 while (r_ParentGrid.Background != null) 68 MakeBackgroundTransparent(); 69 }), DispatcherPriority.Render); 70 } 71 void TextView_Closed(object sender, EventArgs e) 72 { 73 //清除委托,以防内存泄露 74 r_TextView.Closed -= TextView_Closed; 75 r_TextView.BackgroundBrushChanged -= TextView_BackgroundBrushChanged; 76 } 77 } 78 } 79 80 EditorBackground.cs
⑥最后,大家找到项目中的“source.extension.vsixmanifest”文件并打开,找到上面的“Assets”,点击右边的“New”:
Type选择“Microsoft.VisualStudio.MefComponent”
Source选择一个现有的项目
Project就选择当前这个插件项目即可
(例如下图:)
⑦然后OK、大家生成项目,进入项目的“bin\debug”文件夹,找到生成的插件,关掉VS,双击安装即可:
最后打开VS,瞅瞅,如果VS启动异常报错,闪退等,如果指定的图片资源存在,则表示你的插件有问题了,请运行“devenv.exe /safemode”卸载掉刚刚这个插件就行了。
【四、设置模块透明】
打开VS如果没问题的话,你会发现是这个样子:
没错,你可能已经看到了,VS的背景已经发生变化了,被我们指定的图片填充背景了。
但是,VS的模块还没有,这怎么办?
当然,还是通过插件设置他们的颜色啊。
但是VS默认主题颜色是不能随便更改的,怎么办?难道还要再写一个主题换肤的插件?!
当然不用,这个插件已经开发出来了,大家可以打开VS直接在线安装。
打开VS - “工具 - 扩展和更新 - 联机”,右上角搜索“Theme”,找到类似这个名字的点击下载安装即可:“Visual Studio 2012 Color Theme Editor”:
安装后提示重启VS,重启后你会发现“工具”里可以设置主题配色了:
在这里我们可以选择提供的几套配色主题,当然我们也可以自己点击“Customize Colors”新建自己的主题:
左边选择基于哪种现有配色创建新主题,然后下面输入主题名称,点击Create即可:
然后你会很鸡冻的发现,VS每个部分的颜色都可以修改了,而且可以修改透明度:
大家自己按照自己喜欢的修改吧。
点击下面的“Import Theme”导入我发过去的主题即可:
最后效果如下: