【问题标题】:How to add menu to tools in Visual Studio?如何将菜单添加到 Visual Studio 中的工具?
【发布时间】:2017-08-16 15:58:07
【问题描述】:

我对开发 Visual Studio IDE 扩展非常陌生。

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

但是,我不明白如何制作新菜单。

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

在 microsoft 文档中有很多东西,例如组、按钮和菜单。但是,我无法理解它们之间的层次结构,尤其是与 ID 的链接。

有人能解释一下它是如何工作的吗?

提前致谢

【问题讨论】:

  • 您是要制作顶级菜单、向现有菜单添加子菜单,还是仅添加菜单项?

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


【解决方案1】:

资源:Reference Page

  1. 添加菜单资源文件 Visual Studio 菜单命令是从 .vsct 文件编译的,这些文件由 VSCT 编译器编译成 DLL 内的嵌入式 .ctmenu 资源。首先,您需要将 .vsct 文件(名称无关紧要)作为<VSCTCompile> 标记添加到您的项目中。这必须通过直接编辑项目文件来完成。您还需要为 VSCT 编译器添加一个空的 VSPackage.resx 文件,以将编译后的资源嵌入到

工程文件修改(添加到任意<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>

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

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

  1. 为 Visual Studio 定义要加载的 VSPackage 要让 Visual Studio 加载您的菜单命令文件,您需要在插件中定义一个 VSPackage 并将其注册到 VSIX。

首先,添加如下代码文件(类名无所谓):

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
    }
}

包类中的属性告诉 CreatePkgDef.exe(由 VSIX 编译器调用)如何在您的插件中生成一个 .pkgdef 文件,该文件设置适当的注册表项以使用 Visual Studio 注册插件及其菜单资源基于本机 COM 的插件系统。这完全独立于托管插件的 MEF 注册。

枚举及其 [Guid] 属性只是一种方便的跟踪 GUID 和命令 ID 的方法;如果您愿意,可以随意使用不同的方法。

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

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

如果您使用设计器(适用于版本 2 VSIX),请转到资产部分,单击新建,选择 Microsoft.VisualStudio.VsPackage,当前解决方案中的项目,然后选择您的项目。⠀

  1. 修复项目配置⠀ 最后,您需要对 csproj 文件进行一些更改才能正确注册插件:⠀

首先,如果存在&lt;GeneratePkgDefFile&gt;false&lt;/GeneratePkgDefFile&gt;,请删除它,以告知 VSIX 编译器生成 pkgdef 以注册您的包。纯粹基于 MEF 的插件根本不需要 pkgdef 文件,因此大多数项目模板都会添加它,但是一旦您创建了 VSPackage,您需要一个 pkgdef 来将其注册到 Visual Studio 的本机 COM 插件加载器。

接下来,在根元素的任意位置(不是&lt;ItemGroup&gt;)添加以下标记:xml &lt;PropertyGroup&gt; &lt;UseCodebase&gt;true&lt;/UseCodebase&gt; &lt;/PropertyGroup&gt;

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

  1. 执行命令

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

对于全局命令,最简单的方法是覆盖包中的 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 中找到它,您可以在此处查看示例用法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多