2

I'm writing a VSPackage and I need to have menu item with checkbox, just like on this sample image below:

enter image description here

I went through this msdn reference regarding .vsct files, bud didn't fine any information explaining how to do it. What I have now is standard menu item with icon and text (code sample from MyPackage.vsct file):

<Buttons>     
  <Button guid="guidMyPackageCmdSet" id="cmdidMyPackage" type="Button">
    <Icon guid="guidImages" id="myPackageBitmap" />
    <CommandFlag>TextChanges</CommandFlag>
    <CommandFlag>DontCache</CommandFlag>
    <CommandFlag>FixMenuController</CommandFlag>
    <Strings>
      <ButtonText>MyPackage</ButtonText>
    </Strings>
  </Button>      
</Buttons>

I need this additional checkbox. How to do it?

Matze
  • 5,100
  • 6
  • 46
  • 69
jwaliszko
  • 16,942
  • 22
  • 92
  • 158

1 Answers1

3

The properties like Checked, Visible, Enabled or Supported can´t be defined via the VSCT file. You need a command handler that controls the command´s state. I´ve created a base class that wraps the creation of the OleMenuCommand instance and handles the command´s BeforeQueryStatus event. This is a slimmed version of my implementation, but it will give you an idea how to solve it...

internal abstract class CommandHandler : IDisposable
{
    private readonly OleMenuCommand command;

    protected CommandHandler(Guid group, int id)
    {
        var commandid = CommandID(group, id);
        this.command = new OleMenuCommand(this.Invoke, commandId);
        this.command.BeforeQueryStatus += this.OnBeforeQueryStatus;
    }

    protected virtual void OnExecute() { } 

    protected virtual void OnQueryStatus(QueryStatusEventArgs e) { }

    private void Invoke(object sender, EventArgs e)
    {
        this.OnExecute();
    }

    private void OnBeforeQueryStatus(object sender, EventArgs e)
    {
        OleMenuCommand command;
        if ((command = sender as OleMenuCommand) != null)
        {
            var e = new QueryCommandEventArgs
            {
                Checked = command.Checked,
            }

            this.OnQueryStatus(e);

            command.Checked = e.Checked;
        }
    }

    public void Dispose()
    {
        this.command.BeforeQueryStatus -= this.OnBeforeQueryStatus;
    }
}

public class QueryCommandEventArgs : EventArgs
{
    public bool Checked { get; set; }
}

The CommandHandler class allows to control the state of any menu command. Just derive new handler implementations from it and override the OnExecute and OnQueryStatus methods, like...

internal sealed class MyCommand : CommandHandler
{
    private bool checked;

    public MyCommand() : base(GuidCmdSet, MyCommandId) { }

    protected override void OnExecute()
    {
        this.checked = !this.checked; // toggle checked state
    }

    protected override void OnQueryStatus(QueryStatusEventArgs e)
    {
        e.Checked = this.checked;
    }
}
Matze
  • 5,100
  • 6
  • 46
  • 69
  • Hi. I didn't notice these properties exposed by `OleMenuCommand`. Thanks. But still, this checkbox looks differently than this one presented on the screenshot in my question. Maybe these from screenshot are just separate menu items toggled by theirs visibility state... ([like shown here](http://dotneteers.net/blogs/divedeeper/archive/2010/05/23/vs-2010-package-development-chapter-2-commands-menus-and-toolbars.aspx))? And second difference - when I click on item, it closes (disappears, which is normally correct behavior). Do you know how to keep it constantly opened (on top) during clicking? – jwaliszko Apr 14 '14 at 18:20
  • Hm; I would say that the checkboxes do look the same as in the screenshot; unfortunately I´ve no clue how to prevent the menu from closing when an item is clicked. – Matze Apr 16 '14 at 10:07