1

I've got this problem for a while now and I cannot find a solution anywhere. I'm currently writing an add-in (using C#) for Visual Studio 2010. I've added a new menu to the VS menu bar. Within this menu there are several commands e.g. "login" and "logout". The behavior I'd like to enforce would be that both commands are visible, but only "login" would be initially enabled and "logout" initially disabled.

I achieve this through the following code in the OnConnection() method:

    LoginCommand = applicationObject.Commands.AddNamedCommand(
                           addInInstance, 
                           LOGIN_NAME,
                           LOGIN_CAPTION,  
                           LOGIN_TOOLTIP, 
                           true, 59, 
                           ref contextUIGuids,
                           (int)(vsCommandStatus.vsCommandStatusSupported | 
                                vsCommandStatus.vsCommandStatusEnabled)
                        );

    LogoutCommand = applicationObject.Commands.AddNamedCommand(
                            addInInstance, 
                            LOGOUT_NAME,
                            LOGOUT_CAPTION, 
                            LOGOUT_TOOLTIP, 
                            true, 59, 
                            ref contextUIGuids,
                            (int)(vsCommandStatus.vsCommandStatusSupported)
                        );

When I issue the "login" command and I've successfully logged in, I want it the other way around so that the "login" command is disabled in the menu and "logout" is enabled - until I log out.

And this is where I'm stuck. I just don't know where and how exactly to implement the state switching of the commands. I guess I have to handle this in the QueryStatus() method, but Microsoft's documentation on this topic is rather less helpful or eye opening.

Kiquenet
  • 14,494
  • 35
  • 148
  • 243
Christian
  • 707
  • 1
  • 7
  • 15

2 Answers2

2

You need to add the AfterExecute event to your LoginCommand events. Add the following in the OnConnection method:

Events events = (EnvDTE.Events) applicationObject.Events;
CommandEvents LoginEvent = events.get_CommandEvents(LoginCommand.Guid, LoginCommand.ID);
cmdEvent.AfterExecute += new _dispCommandEvents_AfterExecuteEventHandler(LoginEvent_AfterExecute);

and create the LoginEvent_AfterExecute method:

private void LoginEvent_AfterExecute(string guid, int id, object customIn, object customOut)
{
    //Delete the LoginCommand from the commands2 object and recreate it
    LoginCommand.Delete();

    LoginCommand = applicationObject.Commands.AddNamedCommand(
                       addInInstance, 
                       LOGIN_NAME,
                       LOGIN_CAPTION,  
                       LOGIN_TOOLTIP, 
                       true, 59, 
                       ref contextUIGuids,
                       (int)(vsCommandStatus.vsCommandStatusSupported)
                    );

    //Delete the LogoutCommand and recreate it
    LogoutCommand.Delete();  

    LogoutCommand = applicationObject.Commands.AddNamedCommand(
                        addInInstance, 
                        LOGOUT_NAME,
                        LOGOUT_CAPTION, 
                        LOGOUT_TOOLTIP, 
                        true, 59, 
                        ref contextUIGuids,
                        (int)(vsCommandStatus.vsCommandStatusSupported| 
                            vsCommandStatus.vsCommandStatusEnabled)
                    );

}

Resources:

chaliasos
  • 9,659
  • 7
  • 50
  • 87
  • Thanks, that helped me indeed, but what I actually meant was **how** to actually change the states of the commands so that they're either enabled or disabled. – Christian Jun 14 '12 at 12:47
  • Please check again. Not sure if it works, I have not tested it. – chaliasos Jun 14 '12 at 13:02
  • I've implemented the `LoginEvent_AfterExecute()` method as posted here, but I get following error: _No overload for 'LoginEvent_AfterExecute' matches delegate 'EnvDTE._dispCommandEvents_AfterExecuteEventHandler'_. This error occurs at this point: `LoginEvent.AfterExecute += new _dispCommandEvents_AfterExecuteEventHandler(LoginEvent_AfterExecute);` I'm sorry for the lack of my C# knowledge. But I don't find anything helpful on the internet. Thanks again for your help! – Christian Jun 15 '12 at 07:31
  • Nothing to worry about. Check again please. I also posted some helpful links. I think the 1st is what you need, although it is written in VB it will help you. – chaliasos Jun 15 '12 at 08:08
1

Alright, I figured out a solution, though I'm not quite sure if it's elegant. After a command (e.g. LoginCommand) gets executed the QueryStatus() method gets called multiple times, but with a different value for commandName.

public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText)
    {
        if(neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
        {
            if (loginOkay == 0)
            {
                if (commandName == addInInstance.ProgID + "." + LOGIN_NAME)
                {
                    status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported;
                }
                if (commandName == addInInstance.ProgID + "." + LOGOUT_NAME ||
                    commandName == addInInstance.ProgID + "." + LOCK_NAME ||
                    commandName == addInInstance.ProgID + "." + UNLOCK_NAME ||
                    commandName == addInInstance.ProgID + "." + CHECKIN_NAME ||
                    commandName == addInInstance.ProgID + "." + CHECKOUT_NAME)
                {
                    status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
                }
            }
            else if (loginOkay == 1)
            {
                if (commandName == addInInstance.ProgID + "." + LOGIN_NAME)
                {
                    status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
                }
                if (commandName == addInInstance.ProgID + "." + LOGOUT_NAME ||
                    commandName == addInInstance.ProgID + "." + LOCK_NAME ||
                    commandName == addInInstance.ProgID + "." + UNLOCK_NAME ||
                    commandName == addInInstance.ProgID + "." + CHECKIN_NAME ||
                    commandName == addInInstance.ProgID + "." + CHECKOUT_NAME)
                {
                    status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported;
                }
            }
            else
            {
                status = vsCommandStatus.vsCommandStatusUnsupported;
            }
        }
    }

Anyway, thank you Schaliasos for your help. I'd love to vote your answer up, but since I'm lagging the reputation points I can't.

Community
  • 1
  • 1
Christian
  • 707
  • 1
  • 7
  • 15