本文分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. mysql 语句解释执行顺序

    (7) SELECT (8) DISTINCT <select_list> (1) FROM <left_table> (3) <join_type> JOIN & ...

  2. .NET Socket服务编程之-高效连接接入编

    在.NET上编写网络服务深入都有2,3年了,而这些时间时如何在.NET里实现网络服务积累了一些经验.在接下来的时间里会把这方面的经验通过博客的方式分享出来.而这一章主要是讲解在如果提高服务连接接入的效 ...

  3. Dynamic CRM 2013学习笔记(三)快速创建实体 EntityCreater

    一.实体简介 实体用于在 Microsoft Dynamics CRM 中建立业务数据模型和管理业务数据.例如,可以使用客户.市场活动和事件(案例)等实体跟踪和支持销售.市场营销和服务活动.实体具有一 ...

  4. 基于QT的webkit与ExtJs开发CB/S结构的企业应用管理系统

      一:源起       1.何为CB/S的应用程序       C/S结构的应用程序,是客户端/服务端形式的应用程序,这种应用程序要在客户电脑上安装一个程序,客户使用这个程序与服务端通信,完成一定的 ...

  5. 学习WPF——了解WPF中的XAML

    XAML的简单说明 XAML是用于实例化.NET对象的标记语言,主要用于构建WPF的用户界面 XAML中的每一个元素都映射为.NET类的一个实例,例如<Button>映射为WPF的Butt ...

  6. Linux 进程

    Linux 进程 在用户空间,进程是由进程标识符(PID)表示的.从用户的角度来看,一个 PID 是一个数字值,可惟一标识一个进程.一个 PID 在进程的整个生命期间不会更改,但 PID 可以在进程销 ...

  7. jQuery Mobile + HTML5

    最近项目需要,需要构建一个适合手持设备访问的站点,作者从网上查阅了一些资料,本文就是基于此而来. 首先下载jQuery Mobile http://jquerymobile.com/,选择稳定版即可. ...

  8. 再谈this

    不管学习什么知识,习惯于把自己所学习的知识列成一个list,会有助于我们理清思路,是一个很好的学习方法.强烈推荐. 以下篇幅有点长,希望读者耐心阅读. 以下内容会分为如下部分: 1.涵义 1.1:th ...

  9. 【Android】EventBus 源码解析

    EventBus 源码解析 本文为 Android 开源项目实现原理解析 中 EventBus 部分项目地址:EventBus,分析的版本:ccc2771,Demo 地址:EventBus Demo分 ...

  10. atitit.GMT UTC Catitit.GMT UTC CST DST CET 星期 月份 节日 时间的不同本质and起源

    atitit.GMT UTC Catitit.GMT UTC CST DST CET 星期 月份 节日 时间的不同本质and起源 1. GMT(Greenwich Mean Time)是格林尼治平时 ...