动态显示工具栏上的自定义Visual Studio VSPackage命令

时间:2014-07-17 09:12:45

标签: c# visual-studio toolbar vspackage

假设我们在工具栏上有一个带工具栏和几个命令的VSPackage。 如何以编程方式显示/隐藏工具栏上的某个命令?如果您是用户,则可以通过自定义工具栏来执行此操作。因此,我强烈认为必须有一种方法可以从代码中做到这一点。

由于我们没有开发AddIn,我们无法使用 DTE.Commands.AddNamedCommand(AddInInstance, Name, ButtonText, ToolTip, MSOButton)

没关系,因为我们仍然可以使用 Visual Studio命令表(.vsct)格式定义命令,这是VSPackages的建议方式:

<?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="vsshlids.h" />

  <Commands package="testPackage">

    <Menus>  <!-- Define the menus, toolbars, etc. -->
      <Menu guid="commands" id="toolbar" type="Toolbar">
        <Parent guid="guidSHLMainMenu" id="IDG_VS_BUILD_SOLUTION" />
        <CommandFlag>DefaultDocked</CommandFlag>
        <Strings>
          <ButtonText>TestToolbar</ButtonText>
        </Strings>
      </Menu>
    </Menus>

    <Groups>  <!-- Define the groups for commands -->
      <Group guid="commands" id="toolbarGroup" priority="0x0001">
        <Parent guid="commands" id="toolbar" />
      </Group>
    </Groups>

    <Buttons>  <!-- Define the commands as buttons -->
      <Button guid="commands" id="button0" type="Button">
        <Parent guid="commands" id="toolbarGroup" />
        <CommandFlag>DynamicVisibility</CommandFlag>
        <Strings>
          <ButtonText>TestButton0</ButtonText>
        </Strings>
      </Button>
      <Button guid="commands" id="button1" type="Button">
        <Parent guid="commands" id="toolbarGroup" />
        <CommandFlag>DynamicVisibility</CommandFlag>
        <Strings>
          <ButtonText>TestButton1</ButtonText>
        </Strings>
      </Button>
    </Buttons>

  </Commands>

  <Symbols>
    <GuidSymbol name="testPackage" value="{FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF}" />

    <GuidSymbol name="commands" value="{EEEEEEEE-EEEE-EEEE-EEEE-EEEEEEEEEEEE}">
      <IDSymbol name="toolbar" value="0x0100" />
      <IDSymbol name="toolbarGroup" value="0x0010" />
      <IDSymbol name="button0" value="0x0000" />
      <IDSymbol name="button1" value="0x0001" />
    </GuidSymbol>
  </Symbols>

</CommandTable>

稍后在C#代码中,您可以设置我们刚刚定义的MenuCommand的不同属性:

System.ComponentModel.Design.MenuCommand menuCommand = <Acquire your menu command>;
menuCommand.Enabled = <enabled>;
menuCommand.Visible = <visible>;
menuCommand.Supported = <supported>;

问题是,如果将菜单命令放在工具栏上,那么将Visible属性设为false将不会隐藏按钮,只会使其变灰。 (它可以隐藏在任何其他菜单上。)这是Visual Studio的一个功能,而不是错误。

然而,我需要的是:隐藏 Button0 。 (假设 Button0 仅在某些特殊条件适用时显示,例如:您的硬盘驱动器空间少于X MB或安装了其他工具,或者只是在这里自行构成条件。)

如果不需要,可以使用AddIn时间中的以下技术删除按钮:

EnvDTE.Command button0 = DTE.Commands.Item(commandsGuid, button0CommandId); // Both are the same as in the .vsct file
if (button0 != null)
    button0.Delete();
找到了

Command0 ,但在尝试删除时,我遇到了异常:未指定错误(HRESULT异常:0x80004005(E_FAIL))毕竟,它有点意义,因为它是通过.vsct机制创建的,而不是以编程方式创建的。

我的想法已经不多了。请帮助我了解如何在运行时以编程方式隐藏/显示或添加/删除工具栏按钮。有没有其他方法来定义VSPackage命令但是.vsct文件?

任何帮助表示感谢。

1 个答案:

答案 0 :(得分:7)

首先,您必须在vsct文件中的按钮上设置DynamicVisibility标志:

  <Button guid="commands" id="button0" priority="0x1001" type="Button">
    <Parent guid="commands" id="toolbarGroup" />
    <CommandFlag>DefaultInvisible</CommandFlag>
    <CommandFlag>DynamicVisibility</CommandFlag>
    <Strings>
      <ButtonText>TestButton1</ButtonText>
    </Strings>
  </Button>

接下来,在使用OleMenuCommand类而不是MenuCommand覆盖Package.Initialize create命令处理程序并订阅BeforeQueryStatus事件,如下所示:

OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (null != mcs)
{
   // Create the command for the menu item.
   CommandID menuCommandID = new CommandID(GuidList.guidToolbarCmdSet, (int)PkgCmdIDList.cmdidButton0);
   var menuItem = new OleMenuCommand(MenuItemCallback, menuCommandID);
   menuItem.BeforeQueryStatus += BeforeQueryStatusCallback;
   mcs.AddCommand(menuItem);
}

现在在BeforeQueryStatusCallback中,您可以显示或隐藏按钮

private void BeforeQueryStatusCallback(object sender, EventArgs e)
{
    var cmd = (OleMenuCommand)sender
    cmd.Visible = true;
}