public async Task <int> TranslateAcceleratorAsync(MSG msg) { var message = new Message { hwnd = msg.hwnd, message = (int)msg.message, wParam = msg.wParam, lParam = msg.lParam, time = (int)msg.time, pt_x = msg.pt.x, pt_y = msg.pt.y }; var used = ComponentDispatcher.RaiseThreadMessage(ref message); if (used) { msg.message = (uint)message.message; msg.wParam = message.wParam; msg.lParam = message.lParam; return(VSConstants.S_OK); } if (_propertyPageSite != null) { await _projectThreadingService.SwitchToUIThread(); return(_propertyPageSite.TranslateAccelerator(new MSG[] { msg })); } return(VSConstants.S_OK); }
/// <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)); } }
public static System.Windows.Interop.MSG MSGFromOleMSG(ref Microsoft.VisualStudio.OLE.Interop.MSG oleMsg) { System.Windows.Interop.MSG msg = new System.Windows.Interop.MSG(); msg.hwnd = oleMsg.hwnd; msg.message = (int)oleMsg.message; msg.wParam = oleMsg.wParam; msg.lParam = oleMsg.lParam; msg.time = (int)oleMsg.time; msg.pt_x = oleMsg.pt.x; msg.pt_y = oleMsg.pt.y; return(msg); }
public static bool HandleComponentMessage(Microsoft.VisualStudio.OLE.Interop.MSG msg) { // Swallow all keyboard input if ((msg.message >= VSIntegrationUtilities.NativeMethods.WM_KEYFIRST && msg.message <= VSIntegrationUtilities.NativeMethods.WM_KEYLAST) || (msg.message >= VSIntegrationUtilities.NativeMethods.WM_IME_FIRST && msg.message <= VSIntegrationUtilities.NativeMethods.WM_IME_LAST)) { /* * // Special case when the Alt key is down * if (Keyboard.IsKeyDown(Key.LeftAlt) || * Keyboard.IsKeyDown(Key.RightAlt)) * { * // Give the main window focus. This will allow it to handle * // the ALT + <key> commands and bring up the menu. * // * // This works because we lose focus and revoke IOleComponent tracking status * Utilities.NativeMethods.SetFocus(Shell.MainWindow.Handle); * return false; * } * } */ // Otherwise it's our message. Don't let the shell translate it // into some goofy command. // Give WPF a chance to translate. System.Windows.Interop.MSG windowsMsg = NativeMethods.MSGFromOleMSG(ref msg); if (!System.Windows.Interop.ComponentDispatcher.RaiseThreadMessage(ref windowsMsg)) { VSIntegrationUtilities.NativeMethods.TranslateMessage(ref msg); VSIntegrationUtilities.NativeMethods.DispatchMessage(ref msg); } return(true); } return(false); }