如何在Visual Studio中向工具添加菜单?

时间:2017-03-23 21:19:38

标签: c# visual-studio visual-studio-2015 visual-studio-extensions

我是开发Visual Studio IDE扩展的新手。

我是从微软的官方文件中学习的。

但是,我无法理解如何制作新菜单。

我已添加到工具中,但我想添加包含我的工具的新菜单。

在微软文档中,有很多东西,比如组,按钮和菜单。但是,我无法理解它们之间的层次结构,特别是与ID的链接。

有人可以解释它是如何运作的吗?

提前致谢

1 个答案:

答案 0 :(得分:1)

  

资源:Reference Page

  1. 添加菜单资源文件 Visual Studio菜单命令是从.vsct文件编译的,这些文件由VSCT编译器编译到DLL中的嵌入式.ctmenu资源中。首先,您需要将.vsct文件(名称无关紧要)添加到项目中作为<VSCTCompile>标记。这必须通过直接编辑项目文件来完成。您还需要为VSCT编译器添加一个空的VSPackage.resx文件,以将已编译的资源嵌入到
  2. 项目文件修改(将其添加到任何<ItemGroup>)如下:xml <VSCTCompile Include="YourName.vsct"> <ResourceName>Menus.ctmenu</ResourceName> </VSCTCompile> <EmbeddedResource Include="VSPackage.resx"> <MergeWithCTO>true</MergeWithCTO> <ManifestResourceName>VSPackage</ManifestResourceName> </EmbeddedResource>

    VSCT的内容应如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <Extern href="stdidcmd.h"/>
        <Extern href="vsshlids.h"/>
        <Commands package="PackageGuid">
            <Buttons>⠀
                <Button guid="CommandsGuid" id="MyCommand" priority="0x0101" type="Button">⠀
                    <Parent guid="guidSHLMainMenu" id="IDG_VS_CODEWIN_NAVIGATETOLOCATION"/> ⠀
                    <Icon guid="guidObjectBrowserButtons" id="15"/>⠀
    
                    <Strings> 
                        <ButtonText>My &amp;Powerful Command</ButtonText>
                    </Strings> 
                </Button>
            </Buttons>
        </Commands>
    
        <Symbols>
            <GuidSymbol name="PackageGuid" value="«Package GUID»" />
    
            <GuidSymbol name="CommandsGuid" value="«Command Group GUID»">
                <IDSymbol name="MyCommand" value="0" />
            </GuidSymbol>
        </Symbols>
    </CommandTable>
    

    命令ID值在每个命令组(GUID)中必须是唯一的,因此您无需担心与其他命令发生冲突。

    <Parent>条目指定应该放置命令的组;您可以在Program Files \ Microsoft Visual Studio 12.0 \ VSSDK \ VisualStudioIntegration \ Common \ Inc \ vsshlids.h中找到所有标准组。您还可以在同一文件夹中的stdidcmd.h中找到所有命令ID的列表。

    1. 定义要加载的Visual Studio的VSPackage 要使Visual Studio加载菜单命令文件,您需要在插件中定义VSPackage并在VSIX中注册它。
    2. 首先,添加以下代码文件(类名无关紧要):

      using System;
      using System.Runtime.InteropServices;
      using Microsoft.VisualStudio.Shell;
      
      namespace YourAddin.Namespace {
          // These GUIDS and command IDs must match the VSCT.
          [ProvideMenuResource("Menus.ctmenu", 1)]
          [Guid("«Package GUID»")]
          [PackageRegistration(UseManagedResourcesOnly = true)]
          class YourAddinPackage : Package {
          }
      
          [Guid("«Command Group GUID»")]
          enum YourAddinCommand {
              MyCommand = 0
          }
      }
      

      package类中的属性告诉CreatePkgDef.exe(由VSIX编译器调用)如何在你的插件中发出一个.pkgdef文件,该文件设置了适当的注册表键,用Visual Studio注册addin及其菜单资源原生的基于COM的插件系统。这完全独立于托管插件的MEF注册。

      枚举及其[Guid]属性只是跟踪GUID和命令ID的简便方法;如果你愿意,你可以自由地使用不同的方法。

      您还需要告诉VSIX包含该包并通过将以下行添加到source.extension.vsixmanifest中的<Content>元素来生成pkgdef文件:

      <VsPackage>|%CurrentProject%;PkgdefProjectOutputGroup|</VsPackage>
      

      如果您正在使用设计器(对于版本2 VSIXes),请转到Assets部分,单击New,选择Microsoft.VisualStudio.VsPackage,当前解决方案中的项目,然后选择您的项目.⠀

      1. 修复项目配置⠀ 最后,您需要对csproj文件进行一些更改才能正确注册插件:⠀
      2. 首先,删除<GeneratePkgDefFile>false</GeneratePkgDefFile>如果它存在,告诉VSIX编译器生成一个pkgdef来注册你的包。纯粹基于MEF的插件根本不需要pkgdef文件,因此大多数项目模板都会添加它,但是一旦创建了VSPackage,就需要一个pkgdef来用Visual Studio的本机COM插件加载器注册它。

        接下来,在根元素中的任何位置添加以下标记(不在<ItemGroup>中):xml <PropertyGroup> <UseCodebase>true</UseCodebase> </PropertyGroup>

        VSPackages实际上是在Visual Studio配置单元的配置键中注册并使用普通COM实践加载的COM DLL。使用COM互操作加载托管VSPackage;它们被注册为mscoree.dll,然后查找托管程序集以从同一注册表项加载。默认情况下,PkgDef创建者将发出“Assembly”=“YourAssemblyName”,mscoree将尝试使用标准.Net程序集加载器加载。除非您的VSPackage DLL在GAC中(它不会在GAC中),否则这将无效,VS将默默拒绝加载您的包。在项目文件中设置<UseCodebase>将使其发出“CodeBase”=“$ PackageFolder $ \ YourAddin.dll”($ PackageFolder $代替安装VSIX时的实际DLL路径),告诉mscoree确切的从中加载它的路径。

        1. 实施命令
        2. 完成所有这些操作后,当你在插件中点击F5(在实验实例中运行)时,你的命令就会显示出来。但是,您仍然需要实际执行该命令,以便在单击按钮时发生某些事情。

          对于全局命令,最简单的方法是覆盖包中的Initialize()方法并添加如下代码:

          var mcs = (OleMenuCommandService) GetService(typeof(IMenuCommandService));
          var commandId = new CommandID(typeof(YourAddinCommand).GUID, (int)YourAddinCommand.MyCommand));
          mcs.AddCommand(new MenuCommand(delegate {
              MessageBox.Show("You clicked me!");
          }, commandId);
          

          对于适用于活动编辑器窗口的命令,我编写了一个类,它将拦截器添加到编辑器的命令处理程序链中,并公开了一个接受命令枚举中的条目的简单接口。这既可用于实现新命令,也可用于拦截现有命令。您可以在CommandTargetBase.cs中找到它,您可以在此处查看示例用法。