一、选择Visual Studio Package模板建立插件项目

由于此功能需要在右键菜单上添加命令,所以选择Visual Studio Package模板,根据模板向导步骤插件项目,在Select VSPackage Options步骤的时候选择Menu Command选项,如图-1所示:

图-1

接下来是设置命令的名称,如图-2所示

图-2

修改Command name的值,将其设置为我们要添加到右键菜单时的名称。Command ID可选择是否修改,值是一个十六进制数,由于标识我们的添加的命令。按照模板向导建立好插件项目后,按F5运行插件项目,此时VS会新建一个实验实例,点击工具菜单,可以看到已经有一个命令添加到工具菜单里了,如名称My Command name(如果没有修改Command name的值得话)如图-3所示:

图-3

点击该命令的时候会弹出一个提示框。现在有两个疑问:

1、命令是如何与具体的功能关联?

2、该命令是如何添加到工具菜单?

对于第一个疑问:我们可以打开项目下以Package结尾的cs文件,该文件里有一个Initialize方法和一个MenuItemCallback事件处理方法,Package代码文件只有在我们点击命令的时候才会被

加载运行。当我们点击命令的时候会依次调用构造函数、Initialize方法、MenuItemCallBack事件处理方法,MenuItemCallBack事件处理方法就是在Initialize方法里与我们的命令进行关联。

对于第二个疑问:在项目的文件里我们可以找到一个以vsct(Visual Studio Command Table)为后缀的文件,命令就是通过该文件添加到工具菜单下的,项目在编译的时候会将该文件编译为二进制文件。

二、vsct文件简介

在vsct文件里,我们的菜单命令使用Button元素来表示的,如图-3所示:

图-4

Button元素的guid和id属性是该命令的唯一标识,这两个属性值分别在项目的Guids.cs和PkgCmdID.cs文件里定义了,priority表示命令在目标菜单的排列优先级。Parent子元素表示要将我们的命令添加到哪个菜单下面,如工具、帮助、右键菜单,id属性的值是Group元素的id属性值,如图-4所示。Icon元素是命令前的小图标,其属性值是在GuidSymbol元素定义的,如图-6所示。

图-5

Group元素定义了目标菜单的guid和id,也可以将图-4的guid和id换成guidSHLMainMenu和IDM_VS_MENU_TOOLS,这两种效果是一样的,都是将命令添加到右键菜单里。如果要按照图-4的方式设置guid和id值的话,需要事先知道目标菜单的guid和id值,并且要在Sysmbols元素里定义guid和id,如图-5所示:

图-6

除了红色框里的元素是我们自己定义的,其他的都是向导自动生成。那么为什么使用guidSHLMainMenu和IDM_VS_MENU_TOOLS作为guid和id两个属性的值的时候就不需要在Sysmbols元素里定义了呢?因为这两个元素的值已经在stdidcmd.h和vsshlids.h(C:\Program Files (x86)\Microsoft Visual Studio 12.0\VSSDK\VisualStudioIntegration\Common\Inc)这两个文件里定义了,而这两个文件已经在vsct文件的开头就已经使用Extern元素引入了,所以就不需要我们再去定义了。

三、如何获取目标菜单的guid和id值

1、打开注册表编辑器(打开运行窗口,输入regedit),在[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0\General]找到该路径,右击-新建-DWORD(32-位)值(D),建立一个注册文件,将其命名为EnableVSIPLogging,并将其值改为1。按下Ctrl+Shift,用鼠标点击VS里的菜单,就会弹出一个VSDebug Message窗口,如图-6所示:

图-7

其中Guid和CmdID值就是我们需要的,NameLoc表示我们点击的菜单名称。

四、设置命令只在xml文件的右键菜单里显示

由于命令关联的操作都是在点击命令的时候才调用的,所以要实现此功能需要四个步骤才能实现:

1、在Button元素加入子元素<CommandFlag>DynamicVisibility</CommandFlag>

2、为Package类加入特性ProvideAutoLoad,该特性表示当满足条件的时候,事先加载该类里的相关运行。而条件是由该特性的构造函数来设置的,相关的条件已经定义为UIContextGuids80抽象类的常量字段了。

3、将Initialize方法里的MenuCommand类改为OleMenuCommand类,并订阅OleMenuCommand类实例的BeforeQueryStatus事件,如图-8所示:

图-8

4、在BeforeQueryStatus事件处理函数里显示控制操作,如控制命令只在xml文件的右键菜单里才能显示,代码如下所示:

 1 private void menuItem_BeforeQueryStatus(object sender, EventArgs e)
2 {
3 OleMenuCommand menuCommand = sender as OleMenuCommand;
4 if (menuCommand != null)
5 {
6     IntPtr hierarchyPtr, selectionContainerPtr;
7 uint projectItemId;
8 IVsMultiItemSelect mis;
9 IVsMonitorSelection monitorSelection = (IVsMonitorSelection)Package.GetGlobalService(typeof(SVsShellMonitorSelection));
10 monitorSelection.GetCurrentSelection(out hierarchyPtr, out projectItemId, out mis, out selectionContainerPtr);
11
12 IVsHierarchy hierarchy = Marshal.GetTypedObjectForIUnknown(hierarchyPtr, typeof(IVsHierarchy)) as IVsHierarchy;
13 if (hierarchy != null)
14     {
15       object value;
16 hierarchy.GetProperty(projectItemId, (int)__VSHPROPID.VSHPROPID_Name, out value);
17
18 if (value != null && value.ToString().EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
19 {
20   menuCommand.Visible = true;
21 }
22 else
23 {
24   menuCommand.Visible = false;
25 }
26     }
27  }
28 }

到此,在xml文件的右键菜单里添加命令的功能已经实现。如图-9所示:

图-9

五、为命令添加关联功能

添加功能可以在MenuItemCallBack事件处理函数里进行操作,需要判断当前的xml文件是否是新建的,如果是需要加上根元素,为了防止用户是在根元素所在行的后面点击命令(这样就找不到根元素),所以在开始查找操作之前需要将光标移到第一行,然后根据查找的结果判断是否需要添加根元素。如果是新建的xml文件的话可以直接将xml元素信息添加到第一行后面,如果已经存在根元素,则将根元素的结束元素替换成xml元素信息,代码如下所示:

DTE dte = ServiceProvider.GlobalProvider.GetService(typeof(DTE)) as DTE;
if (dte == null)
  return;
TextSelection ts = dte.ActiveDocument.Selection as TextSelection;
//防止用户在</mappings>结束符后进行操作,在结束符后操作的的FindText方法返回的结果为false
ts.MoveToLineAndOffset(1, 1);
bool result = ts.FindText("</mappings>",(int)vsFindOptions.vsFindOptionsMatchWholeWord);
if (!result)
{
  if (ts.ActivePoint.Line == 1)
  {
    ts.EndOfLine();
ts.NewLine();
  }
  string str = "<mappings>\r\n" + sb.ToString();
  ts.Insert(str);
}
else
{
  //需要添加此操作,否则不会替换成功
  ts.SelectAll();
  ts.ReplacePattern("</mappings>", sb.ToString(), (int)vsFindOptions.vsFindOptionsMatchWholeWord);
}

VS2013在右键菜单添加命令插件开发的更多相关文章

  1. win7下给右键菜单添加启动cmd命令

    win7下给右键菜单添加启动cmd命令 (2013-07-20 19:20:56) 转载▼ 标签: it 右键 cmd 分类: 小软件操作技巧     最近编辑器在用windows下的gvim,但进入 ...

  2. 系统右键菜单添加剪贴板清空项(隐藏DOS窗口)

    @color 0A @title 系统右键菜单添加剪贴板清空项(隐藏DOS窗口) by wjshan0808 @echo off echo 请输入右键菜单名称 set /p name= ::创建本机A ...

  3. 《ArcGIS Engine+C#实例开发教程》第六讲 右键菜单添加与实现

    原文:<ArcGIS Engine+C#实例开发教程>第六讲 右键菜单添加与实现 摘要:在这一讲中,大家将实现TOCControl控件和主地图控件的右键菜单.在AE开发中,右键菜单有两种实 ...

  4. 为Windows资源管理器右键菜单添加菜单项

    为Windows资源管理器右键菜单添加菜单项 在Windows下命令行用的比较多,经常在资源管理器里翻到某个目录,若想要在此目录下跑命令,只能是打开cmd.exe,然后一路cd才能到达此目录. 每次都 ...

  5. 右键菜单添加带图标的Notepad++

    给Notepad++ 加带图标右键菜单 方式一: 拷贝以下代码建立一个reg文件,替换相关路径,保存,双击运行加入注册表 Windows Registry Editor Version 5.00 [H ...

  6. Windows下给鼠标右键菜单添加获得完全控制权限的菜单项

    这段时间计算机C分区里多了很多无用的文件,而且不在同一个目录下,搜索出来删除的时候提示没有管理员权限,需要在右键属性里面修改,非常麻烦,于是查询了一下发现可以在文件右键菜单添加一个获取权限的菜单项,这 ...

  7. VSTO 为Office已有右键菜单添加自己的菜单项(word,Excel)

    原文:VSTO 为Office已有右键菜单添加自己的菜单项(word,Excel) private void AddRightMenu()         {            Microsoft ...

  8. 右键菜单添加包含ICON图片的快捷打开方式

    右键菜单添加包含ICON图片的快捷打开方式: ①保存如下代码为“submit.reg”, ②修改对应的程序地址 ③双击创建的文件,导入到注册表中,即可 Windows Registry Editor ...

  9. vmware 安装不成功导致的问题解决以及右键菜单添加打开终端命令

    转自http://blog.csdn.net/puweilan/article/details/8609952 在VMware安装Ubuntu完成后,一直停留在VMware Easy Install, ...

随机推荐

  1. 查看java进程中哪个线程在消耗系统资源

    1 top -p $pid -H  加上-H这个参数后,会列出有哪些线程.这样就可以看到哪个线程id最消耗系统资源了.看到的线程id是10进制的数字. 2 jstack $pid 可以打印出制定jav ...

  2. hdu 1728 逃离迷宫 [ dfs ]

    传送门 逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  3. XCode 或者ITune 添加账号时,提示:This action could not be completed. 或者 Access Privileges

    当遇到This action could not be completed 或者 You do not have enough access privileges for this operation ...

  4. HDU 6437 最(大) 小费用最大流

    Problem L.Videos Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Other ...

  5. P1427 小鱼的数字游戏 洛谷

    https://www.luogu.org/problem/show?pid=1427 题目描述 小鱼最近被要求参加一个数字游戏,要求它把看到的一串数字(长度不一定,以0结束,最多不超过100个,数字 ...

  6. [Lydsy1706月赛]大根堆

    4919: [Lydsy1706月赛]大根堆 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 358  Solved: 150[Submit][Stat ...

  7. Spring事务管理概述

    以下内容引用自http://wiki.jikexueyuan.com/project/spring/transaction-management.html: 数据库事务是一个被视为单一的工作单元的操作 ...

  8. 【Nginx】http模块的数据结构

    定义fttp模块方式很简单,比如:ngx_module_t ngx_http_mytest_module; 其中,ngx_module_t是一个Nginx模块的数据结构. typedef struct ...

  9. 系统重装 Ghost系统的disk to image等等是什么意思

    localdiskto disk to imade from imagepartitionto partition to image from imagecheckimage file disk这些是 ...

  10. Selenium系列之--04 常见元素操作总结

    一.Selenium总共有八种定位方法  By.id()  通过id定位 By.name()  通过name 定位 By.xpath() 通过xpath定位 By.className() 通过clas ...