Can't find the standard command for File > New > File using FindCommand()?

Jawab Can't find the standard command for File > New > File using FindCommand()?

  • 27 April 2012 0:40
     
     

    I am new. I need find the menu item File > New > File... in the Isolated shell using the following code, and I get mc=null. What do I miss?

    var mcs = GetService(typeof(IMenuCommandService))
                        as OleMenuCommandService;
    var cmdID = new CommandID(VSConstants.GUID_VSStandardCommandSet97, int)VSConstants.VSStd97CmdID.FileNew);
    MenuCommand mc = mcs.FindCommand(cmdID );


Semua Balasan

  • 27 April 2012 3:35
    Moderator
     
     Saran Jawaban

    The shel handles this particular command. It does so through it's own implementation of IOleCommandTarget. I'm curious as to why you would want to handle this command yourself. Usually, you handle the file open/save stuff through your DocData object when implementing a custom editor or designer.

    If by chance you need to do something different (such as display your own File Open dialog), you''re much better off just implementing your own custom command.

    Sincerely,


    Ed Dore

  • 27 April 2012 15:25
    Moderator
     
     

    IMenuCommandService is not a way to 'get a command', it is just a dictionary that holds handlers that you have registered. That post you linked about how to disable built in commands is very wrong, I am going to go unmark it as the answer as it is NOT the answer.

    If you want it to be entirely removed there may be a way to #define a symbol in your shell's VSCT that would cause the command to be entirely removed from the shell. I would have to check if the command is set up to support this when I get to work, I don't have the code to look at on this computer.

    If you want to hide a command only sometimes you need to put in place a command handler that will say it is hidden. You would need to use a priority command target (IVsRegisterPriorityCommandTarget) because a package level handler you add would not get called for commands you do not define yourself (and this is such a command).

    Ryan

  • 27 April 2012 15:47
     
     

    Thank you Ryan for the reply. The command is currently available. What I need is to hide it by default, then dynamiccally showing or hiding it again. I'll search for information on how to use IVsRegisterPriorityCommandTarget in the forum. But if you have any suggestion or link that you think would help, it would be great.


    MW

  • 27 April 2012 18:04
    Moderator
     
     Jawab

    Someone just sent me an MSDN article for review on this very topic, but it won't be live for awhile, here is the gist of it

    1:  Create a class that implements the Command Target interface.

          public sealed class CommandTarget : IOleCommandTarget  {}

    2:  In this Class , implement the Exec and Query Status  methods of the interface

        public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
        {
                //Returns the status of the commands.We return S_OK on success, OLECMDERR_E_NOTSUPPORTED for everything we don't handle
               return Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED
       
    }

        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            //Command Execution and return on success
            return Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED;
        }

    3:  In the VSPackage, while initializing the package you can initialize and register the command target. If your command target wants to receive the commands from Visual Studio although they are not registered to your package, or if you want to override the functionality that is already defined by Visual Studio, registering a priority command target will help you.

    IVsRegisterPriorityCommandTarget priCmdTarget = (IVsRegisterPriorityCommandTarget)GetService(typeof(SVsRegisterPriorityCommandTarget));
    CommandTarget cmdTarget = new CommandTarget();
    uint pdwCookie;
    priCmdTarget.RegisterPriorityCommandTarget(0, cmdTarget, out pdwCookie);

    4:  If you want to unregister yourself from being a Priority Command target,

        priCmdTarget.UnregisterPriorityCommandTarget(pdwCookie);

    by sending the cookie that you received while registering the command target.

    The basic approach is to implement QueryStatus and answer the status for the right GUID/ID for the commands you want to affect and return the proper flags for them in the cmdf field of prgCmds[0] (so in this case to make it invislbe you want to set cmdf to (OLECMD_SUPPORTED|OLECMDF_INVISIBLE)).

    Alternatively (instead of implementing IOleCommandTarget) you could register the IMenuCommandService as the callback for the priority command target call (IMenuCommandService also implement IOleCommandTarget) and then you would handle the calls by registering OleMenuCommand object instances with the IMenuCommandService for the commands you want to deal with. The problem with this approach is that you may have to do special things to not have the Exec stop at your handler (i.e. you only want to handle QueryStatus to hide the command, you don't want to handle Exec (i.e. executing the command when it isn't hidden). I don't think IMenuCommandService is well suited for that kind of scenario, but if your Exec callback throw an exception it might work, i.e. something like Marshal.ThrowExceptionForHR(Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED), that would allow command routing to continue, which would eventually cause the shell to find the built in handler that can do File->New.

    Ryan

  • 30 April 2012 21:30
     
     

    Ryan, I tried the method you provided and it didn't work. The item was still visible and function. I'm not sure if I did correctly. But the similar code within the same package class worked ok. Here is the portion of the code, where OnFileNewInit() is added in the package Initialize(). The item is grayed out when it is disabled.

           private void OnFileNewInit()
            {
                IMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as IMenuCommandService;
                if (null != mcs)
                {
                    // create command target
                    CommandID menuCommandID = new CommandID(VSConstants.GUID_VSStandardCommandSet97, (int)VSConstants.VSStd97CmdID.FileNew);
                    OleMenuCommand command = new OleMenuCommand(OnFileNewExe, menuCommandID);
                    command.BeforeQueryStatus += OnFileNewDisable;
                    command.Enabled = false;
                    mcs.AddCommand(command);
                    RegisterPriorityCommandTarget();
                }
           }

            private void OnFileNewExe(object sender, EventArgs e)
            {
                var command = sender as OleMenuCommand;
                if (command.Enabled && DTE.Solution.IsOpen)
                {
                    var evt = new VSCommandEventArgs();
                    HandleFileNew(sender, evt); // customized function
                }
            }

            internal void OnFileNewDisable(object sender, EventArgs e)
            {
                if (sender is OleMenuCommand)
                {
                    var command = sender as OleMenuCommand;
                    if (DTE.Solution.IsOpen)
                        command.Enabled = true;
                    else
                        command.Enabled = false;
                }
            }

            private void RegisterPriorityCommandTarget()
            {
                priCmdTarget = (IVsRegisterPriorityCommandTarget)GetService(typeof(SVsRegisterPriorityCommandTarget));
                if (priCmdTarget != null)
                {
                    priCmdTarget.RegisterPriorityCommandTarget(0, this, out pdwCookie);
                }

            }

    private void HandleFileNew(object sender, VSCommandEventArgs eventArgs)
            {

            }



    MW

  • 01 Mei 2012 4:34
    Moderator
     
     

    You are setting enabled in your code, you want to set Visible if you want to control the command's visibility. You also have to be sure your package is loaded, VS only loads packages as needed, if your package hasn't been loaded your code will not run.

    Ryan

  • 01 Mei 2012 14:24
     
     
    Ryan, you are right. I do want the option to be visiable but not accessable when it is "disabled", so I used Enabled. Thanks for your help!

    MW

  • 01 Mei 2012 14:54
    Moderator
     
     

    If you want to disable it and not hide it then what you have should work. Is it working or not? You seem to say it doesn't work.

    Ryan

  • 01 Mei 2012 15:21
     
     
    Yes, it is working. Sorry for the confusion.

    MW