OleMenuCommandService.cs :  » Development » StyleCop » Microsoft » VisualStudio » Shell » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Development » StyleCop 
StyleCop » Microsoft » VisualStudio » Shell » OleMenuCommandService.cs
//------------------------------------------------------------------------------
// <copyright file="OleMenuCommandService.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------

/*
 */
namespace Microsoft.VisualStudio.Shell{
    
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio.Shell.Interop;
    using Microsoft.Win32;
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Runtime.InteropServices;

    using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
    using IServiceProvider = System.IServiceProvider;
    using VSConstants = Microsoft.VisualStudio.VSConstants;

    /// <include file='doc\OleMenuCommandService.uex' path='docs/doc[@for="OleMenuCommandService"]/*' />
    /// <devdoc>
    ///    
    /// </devdoc>
    [CLSCompliant(false)]
    [System.Runtime.InteropServices.ComVisible(true)]
    public class OleMenuCommandService : System.ComponentModel.Design.MenuCommandService, IOleCommandTarget {

        internal static TraceSwitch MENUSERVICE = new TraceSwitch("MENUSERVICE", "MenuCommandService: Track menu command routing");

        private IOleCommandTarget _parentTarget;
        private IServiceProvider _provider;

        private static uint _queryStatusCount = 0;

        /// <include file='doc\OleMenuCommandService.uex' path='docs/doc[@for="OleMenuCommandService.OleMenuCommandService"]/*' />
        /// <devdoc>
        ///     Creates a new menu command service.
        /// </devdoc>
        public OleMenuCommandService(IServiceProvider serviceProvider) : base(serviceProvider){   
            _provider = serviceProvider;
        }


        /// <include file='doc\OleMenuCommandService.uex' path='docs/doc[@for="OleMenuCommandService.OleMenuCommandService1"]/*' />
        /// <devdoc>
        ///     Creates a new menu command service.
        /// </devdoc>
        public OleMenuCommandService(IServiceProvider serviceProvider, IOleCommandTarget parentCommandTarget) : base(serviceProvider) {
            if (parentCommandTarget == null) {
                throw new ArgumentNullException("parentCommandTarget");
            }
            _parentTarget = parentCommandTarget;
            _provider = serviceProvider;
        }

        /// <include file='doc\OleMenuCommandService.uex' path='docs/doc[@for="OleMenuCommandService.ServiceProvider"]/*' />
        /// <devdoc>
        ///     Returns the service provider.
        /// </devdoc>
        [Obsolete("This method is obsolete and will be removed before the end of M3.2.  Use the proected GetService method instead.")]
        protected IServiceProvider ServiceProvider {
            get {
                return _provider;
            }
        }

        public IOleCommandTarget ParentTarget {
            get { return _parentTarget; }
            set { _parentTarget = value; }
        }

        private MenuCommand FindCommand(Guid guid, int id, ref int hrReturn) {
            hrReturn = (int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_UNKNOWNGROUP;

            MenuCommand result = null;

            //first query the IMenuCommandService and ask it to FindCommand
            IMenuCommandService menuCommandService = GetService(typeof(IMenuCommandService)) as IMenuCommandService;
            if (menuCommandService != null)
            {
              result = menuCommandService.FindCommand(new CommandID(guid, (int)id));  
            }
            //if the IMenuCommandService cames back w/o a command, then ask ourselves
            if (result == null && this != menuCommandService)
            {
              result = FindCommand(guid, (int)id);
            }

            if(result == null) {
                ICollection commands = GetCommandList(guid);
                if(commands != null) {                
                    // The default error now must be "Not Supported" because the command group is known
                    hrReturn = (int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED;
                    Debug.WriteLineIf(MENUSERVICE.TraceVerbose, "\t...VSMCS Found group");
                    // Get the list of command inside this group
                    foreach (MenuCommand command in commands) {
                        // we are looping again on the list of commands to check the DynamicItemMatch
                        // but this is unavoidable in this context....
                        // If the command is a OleMenuCommand, then we can try to do a dynamic match
                        IOleMenuCommand vsCommand = command as IOleMenuCommand;
                        if ( (null != vsCommand) && (vsCommand.DynamicItemMatch(id)) )
                        {
                            Debug.WriteLineIf(MENUSERVICE.TraceVerbose, "\t...VSMCS Found command2");
                            hrReturn = NativeMethods.S_OK;
                            result = command;
                        }
                    }            
                }
            }else {
                Debug.WriteLineIf(MENUSERVICE.TraceVerbose, "\t... VSMCS Found command");
                hrReturn = NativeMethods.S_OK;
            }
            return result;
        }


        /// <include file='doc\OleMenuCommandService.uex' path='docs/doc[@for="OleMenuCommandService.GlobalInvoke"]/*' />
        /// <devdoc>
        ///     Invokes a command on the local form or in the global environment.
        ///     The local form is first searched for the given command ID.  If it is
        ///     found, it is invoked.  Otherwise the the command ID is passed to the
        ///     global environment command handler, if one is available.
        /// </devdoc>
        public override bool GlobalInvoke(CommandID commandID) {

            // is it local?
            if(base.GlobalInvoke(commandID)) {
                return true;
            }
            
            // pass it to the global handler
            IVsUIShell uiShellSvc = GetService(typeof(SVsUIShell)) as IVsUIShell;
            if (uiShellSvc != null) {
                Object dummy = null;
                Guid tmpGuid = commandID.Guid;
                if ( NativeMethods.Failed(uiShellSvc.PostExecCommand(ref tmpGuid, (uint)commandID.ID, 0, ref dummy)) )
                    return false;
                return true;
            }
            return false;
        }

        /// <include file='doc\OleMenuCommandService.uex' path='docs/doc[@for="OleMenuCommandService.GlobalInvoke1"]/*' />
        /// <devdoc>
        ///     Invokes a command on the local form or in the global environment.
        ///     The local form is first searched for the given command ID.  If it is
        ///     found, it is invoked.  Otherwise the the command ID is passed to the
        ///     global environment command handler, if one is available.
        /// </devdoc>
        public override bool GlobalInvoke(CommandID commandID, object arg) {

            // is it local?
            if(base.GlobalInvoke(commandID, arg)) {
                return true;
            }

            // pass it to the global handler
            IVsUIShell uiShellSvc = GetService(typeof(SVsUIShell)) as IVsUIShell;
            if (uiShellSvc == null)
                return false;

            Object dummy = arg;
            Guid tmpGuid = commandID.Guid;
            if ( NativeMethods.Failed(uiShellSvc.PostExecCommand(ref tmpGuid, (uint)commandID.ID, 0, ref dummy)) )
                return false;
            return true;
        }

        /// <include file='doc\OleMenuCommandService.uex' path='docs/doc[@for="OleMenuCommandService.OnCommandChanged"]/*' />
        /// <devdoc>
        ///     This is called by a menu command when it's status has changed.
        /// </devdoc>
        protected override void OnCommandsChanged(MenuCommandsChangedEventArgs e) {

            base.OnCommandsChanged(e);

            if (0 == _queryStatusCount) {
                // UpdateCommandUI(0) can not be called inside QueryStatus because this will cause an infinite
                // sequence of calls to QueryStatus during idle time.
                IVsUIShell uiShellSvc = GetService(typeof(SVsUIShell)) as IVsUIShell;
                if (uiShellSvc != null) {
                    NativeMethods.ThrowOnFailure(uiShellSvc.UpdateCommandUI(0));
                }
            }
        }

        /// <include file='doc\OleMenuCommandService.uex' path='docs/doc[@for="OleMenuCommandService.ShowContextMenu"]/*' />
        /// <devdoc>
        ///     Shows the context menu with the given command ID at the given
        ///     location.
        /// </devdoc>
        public override void ShowContextMenu(CommandID menuID, int x, int y) {
            
            IOleComponentUIManager cui = GetService(typeof(NativeMethods.OleComponentUIManager)) as IOleComponentUIManager;
            Debug.Assert(cui != null, "no component UI manager, so we can't display a context menu");
            if (cui != null) {
                POINTS[] pt = new POINTS[] { new POINTS() };
                pt[0].x = (short)x;
                pt[0].y = (short)y;

                Guid tmpGuid = menuID.Guid;
                NativeMethods.ThrowOnFailure( cui.ShowContextMenu(0, ref tmpGuid, menuID.ID, pt, this) );
            }
        }

        private uint HiWord(uint val) {
            return ((val >> 16) & 0xFFFF);
        }
        private uint LoWord(uint val) {
            return (val & 0xFFFF);
        }

        /// <include file='doc\OleMenuCommandService.uex' path='docs/doc[@for="OleMenuCommandService.IOleCommandTarget.Exec"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Executes the given command.
        /// </devdoc>
        int IOleCommandTarget.Exec(ref Guid guidGroup, uint nCmdId, uint nCmdExcept, IntPtr pIn, IntPtr vOut) {
            const uint vsCmdOptQueryParameterList = 1;

            Guid commandGroup = Guid.Empty;
            try {
                commandGroup = guidGroup;
            }
            catch (NullReferenceException) {
                // Here we assume that the only reason for the exception is a null guidGroup.
                // We do not handle the default command group as definied in the spec for IOleCommandTarget,
                // so we have to return OLECMDERR_E_NOTSUPPORTED.
                return (int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED;
            }

            int hr = NativeMethods.S_OK;

            MenuCommand cmd = FindCommand(commandGroup, (int)nCmdId, ref hr);
            // If the command is not supported check if it can be handled by the parent command service
            if ( (cmd== null || !cmd.Supported) && _parentTarget != null) 
            {
                return _parentTarget.Exec(ref commandGroup, nCmdId, nCmdExcept, pIn, vOut);
            }
            else if (cmd != null) {
                // Try to see if the command is a IOleMenuCommand.
                IOleMenuCommand vsCmd = cmd as IOleMenuCommand;
                // Check the execution flags;
                uint loWord = LoWord(nCmdExcept);
                // If the command is not an OleMenuCommand, it can not handle the show help option.
                if (((uint)OLECMDEXECOPT.OLECMDEXECOPT_SHOWHELP == loWord) && (null == vsCmd))
                {
                    return NativeMethods.S_OK;
                }
                object o = null;
                if (pIn != IntPtr.Zero)
                {
                    o = Marshal.GetObjectForNativeVariant(pIn);
                }
                if (null == vsCmd)
                {
                    cmd.Invoke(o);
                }
                else
                {
                    switch (loWord)
                    {
                        // Default execution of the command: call the Invoke method
                        case (uint)OLECMDEXECOPT.OLECMDEXECOPT_PROMPTUSER:
                        case (uint)OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER:
                        case (uint)OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT:
                            {
                                IMenuCommandInvokeEx invokeEx = vsCmd as IMenuCommandInvokeEx;
                                if (null != invokeEx)
                                {
                                    invokeEx.Invoke(o, vOut, (OLECMDEXECOPT)loWord);
                                }
                                else
                                {
                                    vsCmd.Invoke(o, vOut);
                                }
                            }
                            break;

                        case (uint)OLECMDEXECOPT.OLECMDEXECOPT_SHOWHELP:
                            // Check the hi word of the flags to see what kind of help
                            // is needed. We handle only the request for the parameters list.
                            if (vsCmdOptQueryParameterList == HiWord(nCmdExcept) && IntPtr.Zero != vOut)
                            {
                                // In this case vOut is a pointer to a VARIANT that will receive
                                // the parameters description.
                                if (!string.IsNullOrEmpty(vsCmd.ParametersDescription))
                                {
                                    Marshal.GetNativeVariantForObject(vsCmd.ParametersDescription, vOut);
                                }
                            }
                            break;

                        default:
                            break;
                    }
                }
            }

            return hr;

        }

        /// <include file='doc\OleMenuCommandService.uex' path='docs/doc[@for="OleMenuCommandService.IOleCommandTarget.QueryStatus"]/*' />
        /// <internalonly/>
        /// <devdoc>
        /// Inquires about the status of a command.  A command's status indicates
        /// it's availability on the menu, it's visibility, and it's checked state.
        /// The exception thrown by this method indicates the current command status.
        /// </devdoc>
        int IOleCommandTarget.QueryStatus(ref Guid guidGroup, uint nCmdId, OLECMD[] oleCmd, IntPtr oleText) {
            // According with MSDN the Guid for the command group can be null and in this case the default
            // command group should be used. Given the interop definition of IOleCommandTarget, the only way
            // to detect a null guid is to try to access it and catch the NullReferenceExeption.
            Guid commandGroup = Guid.Empty;
            try {
                commandGroup = guidGroup;
            }
            catch (NullReferenceException) {
                // Here we assume that the only reason for the exception is a null guidGroup.
                // We do not handle the default command group as definied in the spec for IOleCommandTarget,
                // so we have to return OLECMDERR_E_NOTSUPPORTED.
                return (int)Microsoft.VisualStudio.OLE.Interop.Constants.OLECMDERR_E_NOTSUPPORTED;
            }

            _queryStatusCount += 1;
            int hr = NativeMethods.S_OK;
            try {
                for (uint i = 0; i < oleCmd.Length && NativeMethods.Succeeded(hr); i++)
                {
                    MenuCommand cmd = FindCommand(commandGroup, (int)oleCmd[i].cmdID, ref hr);

                    oleCmd[i].cmdf = 0;
                    if ((cmd != null) && NativeMethods.Succeeded(hr))
                    {
                        oleCmd[i].cmdf = (uint)cmd.OleStatus;
                    }

                    if ((oleCmd[i].cmdf & (int)NativeMethods.tagOLECMDF.OLECMDF_SUPPORTED) != 0)
                    {
                        // Find if the caller needs the text of the command
                        if ((IntPtr.Zero != oleText) && (NativeMethods.OLECMDTEXT.GetFlags(oleText) == NativeMethods.OLECMDTEXT.OLECMDTEXTF.OLECMDTEXTF_NAME))
                        {
                            string textToSet = null;
                            if (cmd is DesignerVerb)
                            {
                                textToSet = ((DesignerVerb)cmd).Text;
                            }
                            else if (cmd is IOleMenuCommand)
                            {
                                textToSet = ((IOleMenuCommand)cmd).Text;
                            }
                            if (null != textToSet)
                            {
                                NativeMethods.OLECMDTEXT.SetText(oleText, textToSet);
                            }
                        }
                    }
                    else if (_parentTarget != null)
                    {
                        // If the command is not supported and this command service has a parent,
                        // ask the parent about the command.
                        OLECMD[] newOleArray = { oleCmd[i] };
                        hr = _parentTarget.QueryStatus(ref commandGroup, 1, newOleArray, oleText);
                        oleCmd[i] = newOleArray[0];
                    }
                    // SBurke, if the flags are zero, the shell prefers
                    // that we return not supported, or else no one else will
                    // get asked
                    //
                    if (oleCmd[i].cmdf == 0) {
                        hr = NativeMethods.OLECMDERR_E_NOTSUPPORTED;
                    }
                }
            }
            finally {
                if (0 < _queryStatusCount)
                    _queryStatusCount -= 1;
            }
            return hr;

        }
    }
}


www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.