本文分2部分 第一为自定义多项目模板 第二为vs add-in开发


效果图

1.自定义模板

2. 工具菜单

3.窗口

4.工程

5.文件

...


一. 多项目模板

单项目模板做起来很简单 选中一个项目在文件一栏中选中导出模板

然后选择项目模板

在最后一项向导会给出你的输出路径,一般都是系统的用户文档路径+\Visual Studio 2010\My Exported Templates

在对应目录下会生成你对应的项目模板压缩包

我们生成2个项目的模板文件 然后做一个多项目模板

我们解压2个模板文件并且放进一个新建的名称为MaoyaTemplates的文件夹 剪切到Visual Studio 2010\Templates\ProjectTemplates路径下

新建模板文件MyTemplate.vstemplate

根据要定义的模板内容 修改文件

然后将整个文件夹压缩成zip文件即可 在TemplateData可以定义一些自己需要的信息 例如icon定义你的模板图标 把图标文件放在相对路径即可

然后重新打开vs 即可看到刚才作成的模板

打开以后就是定义的2个demo工程 相当简单

这样就不用每次来新项目都去copy代码了


二 vs插件

概念性的东西可以参考 http://msdn.microsoft.com/zh-cn/library/bb384200.aspx

vs插件可以帮助或者优化你在vs开发过程的大部分窗口 它可以针对文件 针对项目 针对窗口 甚至针对不同的后缀做不同的处理

下面图文+代码介绍开发步骤(vs2010)

选择插件项目 进入向导根据自己的场景选择即可

中间向导过程略过 最后一步

完成向导后 默认工程框架如下

最关键的就是connect.cs文件

Connect 继承了2个类 IDTExtensibility2, IDTCommandTarget

IDTExtensibility2 包含在实现接口时用作事件的方法。 每当发生影响某个外接程序的事件时(如加载或卸载该外接程序时)以及对该外接程序进行任何更改时,Visual Studio 都会调用这些方法。

IDTCommandTarget 接口使开发者得以在环境中实现命名命令。 并且以定义命令状态或执行命令。

每个方法的描述

中文版可以参考msdn

http://msdn.microsoft.com/zh-cn/library/extensibility.idtextensibility2.aspx

http://msdn.microsoft.com/zh-cn/library/envdte.idtcommandtarget.aspx

其中我们作为入门开发 需要关注得的是

OnConnection 为IDTExtensibility2的 main 方法,这是因为每次加载外接程序时都会调用该方法。 该方法为外接程序在加载时的入口点,因此可以将要在外接程序启动时运行的任何代码放置在此处(或调用任何其他函数)。

void OnConnection(
Object Application,
ext_ConnectMode ConnectMode,
Object AddInInst,
ref Array custom
)

参数
Application
类型:System.Object
对集成开发环境 (IDE) 的一个实例 (DTE) 的引用,该实例是 Visual Studio 自动化模型的根对象。
ConnectMode
类型:Extensibility.ext_ConnectMode
一个 ext_ConnectMode 枚举值,指示向 Visual Studio 中加载外接程序的方式。
AddInInst
类型:System.Object
一个对外接程序自己的实例的 AddIn 引用。 此引用存储起来以供以后使用(如用于确定外接程序的父集合)。
custom
类型:System.Array
一个空数组,可用来传递在外接程序中使用的特定于主机的数据。

下面我们开始建一个工具栏(Tools)下的菜单

首先判断加载方式

if (connectMode == ext_ConnectMode.ext_cm_UISetup || connectMode == ext_ConnectMode.ext_cm_Startup ||
connectMode == ext_ConnectMode.ext_cm_AfterStartup)

  这里的ConnectMode来自一个枚举 参考msdn http://msdn.microsoft.com/zh-cn/library/extensibility.ext_connectmode.aspx

然后添加注册插件命令和窗口 关键代码:

                    var toolsBar = commandBars[Tools];

                    if (toolsBar != null)
{
toolsSubPopup = (CommandBarPopup)toolsBar.Controls.Add(MsoControlType.msoControlPopup, Type.Missing, Type.Missing, 1, true);
toolsSubPopup.Caption = MainMenuName;
CommandBar toolsSubBar = toolsSubPopup.CommandBar; Command command = commands.AddNamedCommand2(
_addInInstance,
MenuName1,
MenuName1,
MenuName1,
true,
190,
ref contextGUIDS,
(int)vsCommandStatus.vsCommandStatusUnsupported + (int)vsCommandStatus.vsCommandStatusEnabled);
command.AddControl(toolsSubBar); command = commands.AddNamedCommand2(
_addInInstance,
MenuName2,
MenuName2,
MenuName2,
true,
190,
ref contextGUIDS,
(int)vsCommandStatus.vsCommandStatusUnsupported + (int)vsCommandStatus.vsCommandStatusEnabled);
command.AddControl(toolsSubBar, 2);
}

  commandBars[Tools]表示命令栏中的工具栏,这里Tools实际为定义的字符串“Tools”。

  CommandBarPopup表示弹出命令条。

  _addInInstance表示当前插件实例。

  3个Menuname分别表示命令名称的缩写形式,UI显示的名称以及当用户将鼠标指针悬停在任何绑定到新命令的控件上时所显示的文本。

  true表示下面的190 为 Microsoft Office 位图的 ID。

  ContextUIGUIDs表示GUID 确定哪些环境上下文 (即调试模式,设计模式,等等) 显示命令。

  vsCommandStatusValue确定命令的禁用条件是不可见或禁用,当您提供一个 ContextUIGUIDs 参数,并且都不是当前活动的。

  AddNamedCommand2 创建命名命令,该命令由环境保存,并且在下次环境启动时(无论是否加载外接程序)可用。 外接程序以后可以通过响应 QueryStatus 方法来更改 ButtonText 名称。 如果文本以 # 开头,则该字符串的其余部分是一个整数,该整数表示外接程序已注册的附属 DLL 中的资源 ID。有两个默认值顺序状态:该默认值启用了状态和默认值可见性状态。 这些默认状态很重要,如果找不到命令处理程序 (因为该元素未加载或不实现 IDTCommandTarget)。 如果您的组件加载并实现 IDTCommandTarget,默认值不适用。

  Command.AddControl创建此命令的持久性命令栏控件。后面的数字表示菜单位置。

  详细参考http://msdn.microsoft.com/zh-cn/library/envdte80.commands2.addnamedcommand2.aspx

  这样基本上就完成了下图所示的效果

  但是我们需要对2个菜单进行功能型的开发

  QueryStatus方法返回指定的已命名命令的当前状态(启用、禁用、隐藏等)。

  在此方法添加片段

  if (neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
{
if (commandName == GetCommandName(MainMenuName))
{
status = vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
return;
}
        }

  vsCommandStatusSupported表示命令在此上下文中受支持,vsCommandStatusEnabled表示命令当前处于启用状态。

  Exec方法执行指定的命名命令。

            if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
{
if (commandName == GetCommandName(MainMenuName))
{
MessageBox.Show("This is maoya test");
handled = true;
return;
} if (commandName == GetCommandName(MenuName1))
{
MessageBox.Show("This is maoya Test1 test");
handled = true;
return;
} if (commandName == GetCommandName(MenuName2))
{
MessageBox.Show("This is maoya Test2 test");
handled = true;
return;
} }

  这里实现的很简单就是弹出个winform。你可以在这里实现很丰富的功能。


上面是工具栏的实现,下面介绍个操作窗口的

  Onconnection:

                    CommandBar mdiCommandBar = commandBars["Easy MDI Document Window"];
if (mdiCommandBar != null)
{
Command mdiCmd = commands.AddNamedCommand2(_addInInstance, MenuName3,
MenuName3,
MenuName3, false, 0,
ref contextGUIDS); mdiCmd.AddControl(mdiCommandBar);
}

  QueryStatus:

            if (commandName == GetCommandName(MenuName3) || commandName == GetCommandName(MenuName4) || commandName == GetCommandName(MenuName5))
{
status = vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
return;
}

  Exec 功能是新建一个文件

            if (commandName == GetCommandName(MenuName3))
{
_applicationObject.ExecuteCommand("File.NewFile", string.Empty);
handled = true;
return;
}

  


  下面我们在做一个针对项目工程的自定义按钮

  OnConnection:

 CommandBar projectBar = commandBars["Project"];
if (projectBar != null)
{
projectSubPopup = (CommandBarPopup)projectBar.Controls.Add(MsoControlType.msoControlPopup, Type.Missing, Type.Missing, 1, true);
projectSubPopup.Caption = MainMenuName;
CommandBar projectSubBar = projectSubPopup.CommandBar;
Command projectCommand = commands.AddNamedCommand2(
_addInInstance,
MenuName4,
MenuName4,
MenuName4,
true,
190,
ref contextGUIDS,
(int)vsCommandStatus.vsCommandStatusUnsupported + (int)vsCommandStatus.vsCommandStatusEnabled); if (projectSubBar != null)
{
projectCommand.AddControl(projectSubBar, 1);
} }

  QueryStatus:

            if (commandName == GetCommandName(MenuName3) || commandName == GetCommandName(MenuName4) || commandName == GetCommandName(MenuName5))
{
status = vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
return;
}

  Exec 这里可以抓到你选择的是哪一个项目 包括名称 路径等等 根据具体的需求再来处理对应的逻辑

  if (commandName == GetCommandName(MenuName4))
{
MessageBox.Show(string.Format("This is maoya {0} test,/r/n该项目名称为{1}", MenuName4, _applicationObject.SelectedItems.Item(1).Name));
handled = true;
return;
}

  

  

类似的还有操作文件,代码就不贴了 直接上图

值得一提你可以利用文件后缀等做一些特殊操作

在QueryStatus方法中添加

            if (commandName == GetCommandName(MenuName6))
{
var uiHierarchy = (UIHierarchy)_applicationObject.Windows.Item(
Constants.vsWindowKindSolutionExplorer).Object;
if ((from UIHierarchyItem item in (Array)uiHierarchy.SelectedItems select item.Name).Any(itemName => itemName.IndexOf(".config") > -1))
{
status = vsCommandStatus.vsCommandStatusEnabled | vsCommandStatus.vsCommandStatusSupported;
}
}

  


希望对大家有帮助

vs多项目模板及add-in开发的更多相关文章

  1. Node项目模板管理脚手架ptm-cli开发

    目录 一.ptm-cli 使用说明 1.特点 2.安装 3.使用 1)基础帮助命令 2)添加模板/项目 3)编辑模板/项目 4)查看模板/项目 5)删除模板/项目 6)基于模板新建/初始化项目 二 p ...

  2. Cookiecutter: 更好的项目模板工具:(1)简介及可用资源汇总

    原文档地址:https://cookiecutter.readthedocs.io/en/latest/ 本系列只介绍cookiecutter的基础使用,而且会删除与功能使用无关的部分.深度使用及了解 ...

  3. VS2019 自定义项目模板

    前言: 使用"宇宙最强IDE"开发项目时,都需要根据不同情况选择一个项目模板,来满足开发需求:如下 VS为我们提供了基础的项目模板,但现有项目模板未包含基础功能如:日志输出.审计日 ...

  4. Visual Studio项目模板与向导开发

    在[Xamarin+Prism开发详解系列]里面经常使用到[Prism unity app]的模板创建Prism.Forms项目: 备注:由于Unity社区已经不怎么活跃,下一个版本将会有Autofa ...

  5. Windows Phone 8初学者开发—第10部分:数据绑定应用程序和透视应用程序项目模板简介

    原文 Windows Phone 8初学者开发—第10部分:数据绑定应用程序和透视应用程序项目模板简介 原文地址: http://channel9.msdn.com/Series/Windows-Ph ...

  6. 后端开发实践——Spring Boot项目模板

    在我的工作中,我从零开始搭建了不少软件项目,其中包含了基础代码框架和持续集成基础设施等,这些内容在敏捷开发中通常被称为"第0个迭代"要做的事情.但是,当项目运行了一段时间之后再来反 ...

  7. 从零开始实现ASP.NET Core MVC的插件式开发(二) - 如何创建项目模板

    标题:从零开始实现ASP.NET Core MVC的插件式开发(二) - 如何创建项目模板 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/11155 ...

  8. 后端开发实践:Spring Boot项目模板

    在我的工作中,我从零开始搭建了不少软件项目,其中包含了基础代码框架和持续集成基础设施等,这些内容在敏捷开发中通常被称为"第0个迭代"要做的事情.但是,当项目运行了一段时间之后再来反 ...

  9. vue开发:前端项目模板

    简介 vue-cli创建vue项目,整合vuex.vue-router.axios.element-ui 项目模板下载地址 创建项目 使用vue-cli创建项目,功能选择:Babel.Router.v ...

随机推荐

  1. 在stackoverflow上使用markdown

    stackoverflow流派的markdown. Code and Preformatted Text 缩进四个空格,就可以写代码片段了 def hello(): print "hello ...

  2. [自娱自乐] 4、超声波测距模块DIY笔记(四)——终结篇·基于C#上位机软件开发

    前言 上一节我们已经基本上把超声波硬件的发射和接收模块全部做好了,接下来我们着手开发一个软硬结合的基于C#的平面定位软件! 目录 一.整体思路 二.效果提前展示 2-1.软件部分展示 2-2.硬件部分 ...

  3. Openstack Murano(kilo)二次开发之添加Volume

    Openstack Murano(kilo)二次开发之添加Volume 欢迎转载,转载请注明出处:http://www.cnblogs.com/fmnisme/p/openstack_murano_a ...

  4. jenkins插件 build timeout和build timestamp

    build timeout plugin, 允许对job设置timeout时间,当超时时,job将abort. build timestamp pluin,使得job log的每次输出前面都增加当时的 ...

  5. DigitalOcean上使用Tornado+MongoDB+Nginx+Supervisor+DnsPod快速搭建个人博客

    DigitalOcean 之前买了个便宜的VPS并且在上面搭建了我自己写的博客程序,后来VPS里运行MongoDB经常自己挂掉就索性没理了.直到现在VPS已经过期,服务器被强制关掉了.周末在家索性想着 ...

  6. C语言实现单链表-01版

    单链表的应用非常广,它可以实现栈,队列等: Problem 我对学习任何东西都希望能找到尽可能简单的例子,而不是看起来好高大上的: 对链表这样简答的数据结构,有些书也是写得太过“完美”啦: 初学者很难 ...

  7. (笔记)VC6插件安装(VC6LineNumberAddin)

    VC6插件安装步骤如下: 1.下载VC6LineNumberAddin插件及注册文件.(以下是参考链接:) http://files.cnblogs.com/files/tdyizhen1314/VC ...

  8. SAFS Init Files

    There're many deployment files for configuration. We need to learn how SAFS read these depolyment fi ...

  9. uva111动态规划之最长公共子序列

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=74662#problem/C     A B C D E C - Largest Rect ...

  10. bzoj 1207: [HNOI2004]打鼹鼠

    1207: [HNOI2004]打鼹鼠 Time Limit: 10 Sec  Memory Limit: 162 MB Description 鼹鼠是一种很喜欢挖洞的动物,但每过一定的时间,它还是喜 ...