Esempio n. 1
0
        protected override bool PreProcessMessage(ref System.Windows.Forms.Message m)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (m.Msg >= WM_KEYFIRST && m.Msg <= WM_KEYLAST)
            {
                var oleMsg = new MSG
                {
                    hwnd    = m.HWnd,
                    lParam  = m.LParam,
                    wParam  = m.WParam,
                    message = (uint)m.Msg
                };

                if (_filterKeys == null)
                {
                    _filterKeys = this.GetService <IVsFilterKeys2, SVsFilterKeys>();
                }

                return(_filterKeys.TranslateAcceleratorEx(
                           new[] { oleMsg },
                           (uint)__VSTRANSACCELEXFLAGS.VSTAEXF_UseTextEditorKBScope,
                           0,
                           Array.Empty <Guid>(),
                           out var _,
                           out var _,
                           out var _,
                           out var _) == VSConstants.S_OK);
            }

            return(base.PreProcessMessage(ref m));
        }
Esempio n. 2
0
        /// <summary>
        /// Preprocess input (keyboard) messages in order to translate them to editor commands if they map. Since our tool window is NOT an
        /// editor the shell won't consider the editor keybindings when doing its usual input pre-translation. We could either set our
        /// window frames InheritKeyBindings property to point to the std editor factory GUID OR we can do this. I chose this method as
        /// it allows us to have the editor keybindings active ONLY when the focus is in the editor, that way we won't have editor
        /// keybindings active in our window UNLESS the editor has focus, which is what we want.
        /// </summary>
        protected override bool PreProcessMessage(ref System.Windows.Forms.Message m)
        {
            //Only try and pre-process keyboard input messages, all others are not interesting to us.
            if (m.Msg >= WM_KEYFIRST && m.Msg <= WM_KEYLAST)
            {
                //Only attempt to do the input -> command mapping if focus is inside our hosted editor.
                if (this.control.IsKeyboardFocusWithin)
                {
                    IVsFilterKeys2 filterKeys = (IVsFilterKeys2)GetService(typeof(SVsFilterKeys));
                    MSG            oleMSG     = new MSG()
                    {
                        hwnd = m.HWnd, lParam = m.LParam, wParam = m.WParam, message = (uint)m.Msg
                    };

                    //Ask the shell to do the command mapping for us and fire off the command if it succeeds with that mapping. We pass no 'custom' scopes
                    //(third and fourth argument) because we pass VSTAEXF_UseTextEditorKBScope to indicate we want the shell to apply the text editor
                    //command scope to this call.
                    Guid cmdGuid;
                    uint cmdId;
                    int  fTranslated;
                    int  fStartsMultiKeyChord;
                    int  res = filterKeys.TranslateAcceleratorEx(new MSG[] { oleMSG },
                                                                 (uint)(__VSTRANSACCELEXFLAGS.VSTAEXF_UseTextEditorKBScope),
                                                                 0 /*scope count*/,
                                                                 new Guid[0] /*scopes*/,
                                                                 out cmdGuid,
                                                                 out cmdId,
                                                                 out fTranslated,
                                                                 out fStartsMultiKeyChord);

                    if (fStartsMultiKeyChord == 0)
                    {
                        //HACK: Work around a bug in TranslateAcceleratorEx that will report it DIDN'T do the command mapping
                        //when in fact it did :( Problem has been fixed (since I found it while writing this code), but in the
                        //mean time we need to successfully eat keystrokes that have been mapped to commands and dispatched,
                        //we DON'T want them to continue on to Translate/Dispatch. "Luckily" asking TranslateAcceleratorEx to
                        //do the mapping WITHOUT firing the command will give us the right result code to indicate if the command
                        //mapped or not, unfortunately we can't always do this as it would break key-chords as it causes the shell
                        //to not remember the first input match of a multi-part chord, hence the reason we ONLY hit this block if
                        //it didn't tell us the input IS part of key-chord.
                        res = filterKeys.TranslateAcceleratorEx(new MSG[] { oleMSG },
                                                                (uint)(__VSTRANSACCELEXFLAGS.VSTAEXF_NoFireCommand | __VSTRANSACCELEXFLAGS.VSTAEXF_UseTextEditorKBScope),
                                                                0,
                                                                new Guid[0],
                                                                out cmdGuid,
                                                                out cmdId,
                                                                out fTranslated,
                                                                out fStartsMultiKeyChord);

                        return(res == VSConstants.S_OK);
                    }

                    //We return true (that we handled the input message) if we managed to map it to a command OR it was the
                    //beginning of a multi-key chord, anything else should continue on with normal processing.
                    return((res == VSConstants.S_OK) || (fStartsMultiKeyChord != 0));
                }
            }

            return(base.PreProcessMessage(ref m));
        }
Esempio n. 3
0
        /// <summary>
        /// Filters out a message before it is dispatched
        /// </summary>
        /// <param name="m">The message to be dispatched. You cannot modify this message.</param>
        /// <returns>True to filter the message and stop it from being dispatched; false to allow the message to continue to the next filter or control.</returns>
        public bool PreFilterMessage(ref Message m)
        {
            //IVsFilterKeys2 performs advanced keyboard message translation
            IVsFilterKeys2 filterKeys2 = services.VsFilterKeys2;

            MSG[] messages = new MSG[1];
            messages[0].hwnd    = m.HWnd;
            messages[0].lParam  = m.LParam;
            messages[0].wParam  = m.WParam;
            messages[0].message = (uint)m.Msg;

            Guid cmdGuid;
            uint cmdCode;
            int  cmdTranslated;
            int  keyComboStarts;

            int hr = filterKeys2.TranslateAcceleratorEx(messages,
                                                        (uint)__VSTRANSACCELEXFLAGS.VSTAEXF_UseTextEditorKBScope //Translates keys using TextEditor key bindings. Equivalent to passing CMDUIGUID_TextEditor, CMDSETID_StandardCommandSet97, and guidKeyDupe for scopes and the VSTAEXF_IgnoreActiveKBScopes flag.
                                                        | (uint)__VSTRANSACCELEXFLAGS.VSTAEXF_AllowModalState,   //By default this function cannot be called when the shell is in a modal state, since command routing is inherently dangerous. However if you must access this in a modal state, specify this flag, but keep in mind that many commands will cause unpredictable behavior if fired.
                                                        0,
                                                        null,
                                                        out cmdGuid,
                                                        out cmdCode,
                                                        out cmdTranslated,
                                                        out keyComboStarts);

            if (hr != VSConstants.S_OK)
            {
                return(false);
            }

            return(cmdTranslated != 0);
        }
Esempio n. 4
0
        public override bool PreProcessMessage(ref Message msg)
        {
            if (msg.Msg >= _wm_KEYFIRST && msg.Msg <= _wm_KEYLAST)
            {
                IVsFilterKeys2 filterKeys = (IVsFilterKeys2)ServiceProvider.GlobalProvider.GetService(typeof(SVsFilterKeys));
                Microsoft.VisualStudio.OLE.Interop.MSG oleMSG = new Microsoft.VisualStudio.OLE.Interop.MSG()
                {
                    hwnd = msg.HWnd, lParam = msg.LParam, wParam = msg.WParam, message = (uint)msg.Msg
                };

                //Ask the shell to do the command mapping for us and without firing off the command. We need to check if this command is one of the
                //supported commands first before actually firing the command.
                filterKeys.TranslateAcceleratorEx(new Microsoft.VisualStudio.OLE.Interop.MSG[] { oleMSG },
                                                  (uint)(__VSTRANSACCELEXFLAGS.VSTAEXF_NoFireCommand | __VSTRANSACCELEXFLAGS.VSTAEXF_UseGlobalKBScope | __VSTRANSACCELEXFLAGS.VSTAEXF_AllowModalState),
                                                  0 /*scope count*/,
                                                  new Guid[0] /*scopes*/,
                                                  out Guid cmdGuid,
                                                  out uint cmdId,
                                                  out int fTranslated,
                                                  out int fStartsMultiKeyChord);

                if (ShouldRouteCommandBackToVS(cmdGuid, cmdId, fTranslated == 1, fStartsMultiKeyChord == 1))
                {
                    return(false);
                }
            }

            return(base.PreProcessMessage(ref msg));
        }
Esempio n. 5
0
        void OnLoad(object sender, EventArgs e)
        {
            if (_fKeys == null)
            {
                _fKeys = GetService <IVsFilterKeys2>(typeof(SVsFilterKeys));
            }

            if (_form.ToolBar != 0)
            {
                System.ComponentModel.Design.CommandID tbId = new System.ComponentModel.Design.CommandID(AnkhId.CommandSetGuid, (int)_form.ToolBar);

                if (_tbHost == null)
                {
                    IVsUIShell uiShell = GetService <IVsUIShell>(typeof(SVsUIShell));

                    Marshal.ThrowExceptionForHR(uiShell.SetupToolbar(_form.Handle, (IVsToolWindowToolbar)this, out _tbHost));
                }

                Guid toolbarCommandSet = tbId.Guid;
                Marshal.ThrowExceptionForHR(
                    _tbHost.AddToolbar(VSTWT_LOCATION.VSTWT_TOP, ref toolbarCommandSet, (uint)tbId.ID));
                Marshal.ThrowExceptionForHR(_tbHost.Show(0));
                Marshal.ThrowExceptionForHR(_tbHost.ForceUpdateUI());
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Preprocess input (keyboard) messages in order to translate them to editor commands if they map. Since we are in a modal dialog
        /// we need to tell the shell to allow pre-translate during a modal loop as well as instructing it to use the editor keyboard scope
        /// even though, as far as the shell knows, there is no editor active (in a document or tool window, the shell knows nothing about
        /// random modal dialogs such as this one).
        /// </summary>
        private void FilterThreadMessage(ref System.Windows.Interop.MSG msg, ref bool handled)
        {
            if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST)
            {
                IVsFilterKeys2 filterKeys = (IVsFilterKeys2)ServiceProvider.GlobalProvider.GetService(typeof(SVsFilterKeys));
                Microsoft.VisualStudio.OLE.Interop.MSG oleMSG = new Microsoft.VisualStudio.OLE.Interop.MSG()
                {
                    hwnd = msg.hwnd, lParam = msg.lParam, wParam = msg.wParam, message = (uint)msg.message
                };

                //Ask the shell to do the command mapping for us and fire off the command if it succeeds with that mapping. We pass no 'custom' scopes
                //(third and fourth argument) because we pass VSTAEXF_UseTextEditorKBScope to indicate we want the shell to apply the text editor
                //command scope to this call.
                Guid cmdGuid;
                uint cmdId;
                int  fTranslated;
                int  fStartsMultiKeyChord;
                int  res = filterKeys.TranslateAcceleratorEx(new Microsoft.VisualStudio.OLE.Interop.MSG[] { oleMSG },
                                                             (uint)(__VSTRANSACCELEXFLAGS.VSTAEXF_UseTextEditorKBScope | __VSTRANSACCELEXFLAGS.VSTAEXF_AllowModalState),
                                                             0 /*scope count*/,
                                                             new Guid[0] /*scopes*/,
                                                             out cmdGuid,
                                                             out cmdId,
                                                             out fTranslated,
                                                             out fStartsMultiKeyChord);

                if (fStartsMultiKeyChord == 0)
                {
                    //HACK: Work around a bug in TranslateAcceleratorEx that will report it DIDN'T do the command mapping
                    //when in fact it did :( Problem has been fixed (since I found it while writing this code), but in the
                    //mean time we need to successfully eat keystrokes that have been mapped to commands and dispatched,
                    //we DON'T want them to continue on to Translate/Dispatch. "Luckily" asking TranslateAcceleratorEx to
                    //do the mapping WITHOUT firing the command will give us the right result code to indicate if the command
                    //mapped or not, unfortunately we can't always do this as it would break key-chords as it causes the shell
                    //to not remember the first input match of a multi-part chord, hence the reason we ONLY hit this block if
                    //it didn't tell us the input IS part of key-chord.
                    res = filterKeys.TranslateAcceleratorEx(new Microsoft.VisualStudio.OLE.Interop.MSG[] { oleMSG },
                                                            (uint)(__VSTRANSACCELEXFLAGS.VSTAEXF_NoFireCommand | __VSTRANSACCELEXFLAGS.VSTAEXF_UseTextEditorKBScope | __VSTRANSACCELEXFLAGS.VSTAEXF_AllowModalState),
                                                            0,
                                                            new Guid[0],
                                                            out cmdGuid,
                                                            out cmdId,
                                                            out fTranslated,
                                                            out fStartsMultiKeyChord);
                    handled = (res == VSConstants.S_OK);
                    return;
                }

                //We return true (that we handled the input message) if we managed to map it to a command OR it was the
                //beginning of a multi-key chord, anything else should continue on with normal processing.
                handled = ((res == VSConstants.S_OK) || (fStartsMultiKeyChord != 0));
            }
        }
Esempio n. 7
0
        void OnLoad(object sender, EventArgs e)
        {
            if (_fKeys == null)
                _fKeys = GetService<IVsFilterKeys2>(typeof(SVsFilterKeys));

            if (_form.ToolBar != 0)
            {
                System.ComponentModel.Design.CommandID tbId = new System.ComponentModel.Design.CommandID(AnkhId.CommandSetGuid, (int)_form.ToolBar);

                if (_tbHost == null)
                {
                    IVsUIShell uiShell = GetService<IVsUIShell>(typeof(SVsUIShell));

                    Marshal.ThrowExceptionForHR(uiShell.SetupToolbar(_form.Handle, (IVsToolWindowToolbar)this, out _tbHost));
                }

                Guid toolbarCommandSet = tbId.Guid;
                Marshal.ThrowExceptionForHR(
                    _tbHost.AddToolbar(VSTWT_LOCATION.VSTWT_TOP, ref toolbarCommandSet, (uint)tbId.ID));
                Marshal.ThrowExceptionForHR(_tbHost.Show(0));
                Marshal.ThrowExceptionForHR(_tbHost.ForceUpdateUI());
            }
        }