/// <summary> /// Gets the InputLanguage that has the same layout as <paramref name="keyboardDescription"/>. /// </summary> internal static InputLanguage GetInputLanguage(WinKeyboardDescription keyboardDescription) { InputLanguage sameLayout = null; InputLanguage sameCulture = null; foreach (InputLanguage lang in InputLanguage.InstalledInputLanguages) { // TODO: write some tests try { if (GetLayoutNameEx(lang.Handle).Name == keyboardDescription.Name) { if (keyboardDescription.Locale == lang.Culture.Name) { return(lang); } if (sameLayout == null) { sameLayout = lang; } } else if (keyboardDescription.Locale == lang.Culture.Name && sameCulture == null) { sameCulture = lang; } } catch (CultureNotFoundException) { // we get an exception for non-supported cultures, probably because of a // badly applied .NET patch. // http://www.ironspeed.com/Designer/3.2.4/WebHelp/Part_VI/Culture_ID__XXX__is_not_a_supported_culture.htm and others } } return(sameLayout ?? sameCulture); }
/// <summary> /// Save the state of the conversion and sentence mode for the current IME /// so that we can restore it later. /// </summary> private void SaveImeConversionStatus(WinKeyboardDescription winKeyboard) { if (winKeyboard == null) { return; } if (InputLanguage.CurrentInputLanguage.Culture.Name != winKeyboard.InputLanguage.Culture.Name) { // Users can switch the keyboards without switching fields, don't save unrelated IME status return; } var windowHandle = new HandleRef(this, Win32.GetFocus()); var contextPtr = Win32.ImmGetContext(windowHandle); if (contextPtr == IntPtr.Zero) { return; } var contextHandle = new HandleRef(this, contextPtr); int conversionMode; int sentenceMode; Win32.ImmGetConversionStatus(contextHandle, out conversionMode, out sentenceMode); winKeyboard.ConversionMode = conversionMode; winKeyboard.SentenceMode = sentenceMode; Win32.ImmReleaseContext(windowHandle, contextHandle); }
/// <summary> /// Save the state of the conversion and sentence mode for the current IME /// so that we can restore it later. /// </summary> private void SaveImeConversionStatus(WinKeyboardDescription winKeyboard) { if (winKeyboard == null) { return; } var windowHandle = new HandleRef(this, winKeyboard.WindowHandle != IntPtr.Zero ? winKeyboard.WindowHandle : Win32.GetFocus()); var contextPtr = Win32.ImmGetContext(windowHandle); if (contextPtr == IntPtr.Zero) { return; } var contextHandle = new HandleRef(this, contextPtr); int conversionMode; int sentenceMode; Win32.ImmGetConversionStatus(contextHandle, out conversionMode, out sentenceMode); winKeyboard.ConversionMode = conversionMode; winKeyboard.SentenceMode = sentenceMode; Win32.ImmReleaseContext(windowHandle, contextHandle); }
private void SwitchKeyboard(WinKeyboardDescription winKeyboard) { if (_fSwitchingKeyboards) { return; } _fSwitchingKeyboards = true; try { KeyboardController.Instance.ActiveKeyboard = ActivateKeyboard(winKeyboard); if (Form.ActiveForm != null) { // If we activate a keyboard while a particular Form is active, we want to know about // input language change calls for that form. The previous -= may help make sure we // don't get multiple hookups. Form.ActiveForm.InputLanguageChanged -= ActiveFormOnInputLanguageChanged; Form.ActiveForm.InputLanguageChanged += ActiveFormOnInputLanguageChanged; } // If we have a TIP (TSF Input Processor) we don't have a handle. But we do the // keyboard switching through TSF so we don't need the workaround below. if (!UseWindowsApiForKeyboardSwitching(winKeyboard)) { return; } _expectedKeyboard = winKeyboard; // The following lines help to work around a Windows bug (happens at least on // XP-SP3): When you set the current input language (by any method), if there is more // than one loaded input language associated with that same culture, Windows may // initially go along with your request, and even respond to an immediate query of // the current input language with the answer you expect. However, within a fraction // of a second, it often takes the initiative to again change the input language to // the _other_ input language having that same culture. We check that the proper // input language gets set by enabling a timer so that we can re-set the input // language if necessary. _fSwitchedLanguages = true; // stop timer first so that the 0.5s interval restarts. _timer.Stop(); _timer.Start(); } finally { _fSwitchingKeyboards = false; } }
private bool SwitchByProfile(WinKeyboardDescription keyboard) { _adaptor.ProcessorProfiles.ChangeCurrentLanguage(keyboard.InputProcessorProfile.LangId); Guid classId = keyboard.InputProcessorProfile.ClsId; Guid guidProfile = keyboard.InputProcessorProfile.GuidProfile; _adaptor.ProfileManager.ActivateProfile(keyboard.InputProcessorProfile.ProfileType, keyboard.InputProcessorProfile.LangId, ref classId, ref guidProfile, keyboard.InputProcessorProfile.Hkl, TfIppMf.ForProcess); RestoreImeConversionStatus( keyboard); // Restore it even though sometimes windows will ignore us Timer.Stop(); Timer.Start(); // Start the timer for restoring IME status for when windows ignores us. return(true); }
private WinKeyboardDescription ActivateKeyboard(WinKeyboardDescription winKeyboard) { try { if (UseWindowsApiForKeyboardSwitching(winKeyboard)) { // Win XP with regular keyboard, or TSF disabled Win32.ActivateKeyboardLayout(new HandleRef(this, winKeyboard.InputLanguage.Handle), 0); return(winKeyboard); } var profile = winKeyboard.InputProcessorProfile; if ((profile.Flags & TfIppFlags.Enabled) == 0) { return(winKeyboard); } ProcessorProfiles.ChangeCurrentLanguage(profile.LangId); if (ProfileMgr == null) { // Win XP with TIP (TSF Input Processor) ProcessorProfiles.ActivateLanguageProfile(ref profile.ClsId, profile.LangId, ref profile.GuidProfile); } else { // Windows >= Vista with either TIP or regular keyboard ProfileMgr.ActivateProfile(profile.ProfileType, profile.LangId, ref profile.ClsId, ref profile.GuidProfile, profile.Hkl, TfIppMf.DontCareCurrentInputLanguage); } } catch (ArgumentException) { // throws exception for non-supported culture, though seems to set it OK. } catch (COMException e) { var profile = winKeyboard.InputProcessorProfile; var msg = string.Format("Got COM exception trying to activate IM:" + Environment.NewLine + "LangId={0}, clsId={1}, hkl={2}, guidProfile={3}, flags={4}, type={5}, catId={6}", profile.LangId, profile.ClsId, profile.Hkl, profile.GuidProfile, profile.Flags, profile.ProfileType, profile.CatId); throw new ApplicationException(msg, e); } return(winKeyboard); }
private void OnTimerTick(object sender, EventArgs eventArgs) { if (_expectedKeyboard == null || !_fSwitchedLanguages) { return; } // This code gets only called if TSF is not available(e.g. Windows XP) if (InputLanguage.CurrentInputLanguage.Culture.KeyboardLayoutId == _expectedKeyboard.InputLanguage.Culture.KeyboardLayoutId) { _expectedKeyboard = null; _fSwitchedLanguages = false; _timer.Enabled = false; return; } SwitchKeyboard(_expectedKeyboard); }
/// <summary> /// Save the state of the conversion and sentence mode for the current IME /// so that we can restore it later. /// </summary> private void SaveImeConversionStatus(WinKeyboardDescription winKeyboard) { if (winKeyboard == null) return; var windowHandle = new HandleRef(this, winKeyboard.WindowHandle != IntPtr.Zero ? winKeyboard.WindowHandle : Win32.GetFocus()); var contextPtr = Win32.ImmGetContext(windowHandle); if (contextPtr == IntPtr.Zero) return; var contextHandle = new HandleRef(this, contextPtr); int conversionMode; int sentenceMode; Win32.ImmGetConversionStatus(contextHandle, out conversionMode, out sentenceMode); winKeyboard.ConversionMode = conversionMode; winKeyboard.SentenceMode = sentenceMode; Win32.ImmReleaseContext(windowHandle, contextHandle); }
private WinKeyboardDescription ActivateKeyboard(WinKeyboardDescription winKeyboard) { try { if (UseWindowsApiForKeyboardSwitching(winKeyboard)) { // Win XP with regular keyboard, or TSF disabled Win32.ActivateKeyboardLayout(new HandleRef(this, winKeyboard.InputLanguage.Handle), 0); return winKeyboard; } var profile = winKeyboard.InputProcessorProfile; if ((profile.Flags & TfIppFlags.Enabled) == 0) return winKeyboard; ProcessorProfiles.ChangeCurrentLanguage(profile.LangId); if (ProfileMgr == null) { // Win XP with TIP (TSF Input Processor) ProcessorProfiles.ActivateLanguageProfile(ref profile.ClsId, profile.LangId, ref profile.GuidProfile); } else { // Windows >= Vista with either TIP or regular keyboard ProfileMgr.ActivateProfile(profile.ProfileType, profile.LangId, ref profile.ClsId, ref profile.GuidProfile, profile.Hkl, TfIppMf.DontCareCurrentInputLanguage); } } catch (ArgumentException) { // throws exception for non-supported culture, though seems to set it OK. } catch (COMException e) { var profile = winKeyboard.InputProcessorProfile; var msg = string.Format("Got COM exception trying to activate IM:" + Environment.NewLine + "LangId={0}, clsId={1}, hkl={2}, guidProfile={3}, flags={4}, type={5}, catId={6}", profile.LangId, profile.ClsId, profile.Hkl, profile.GuidProfile, profile.Flags, profile.ProfileType, profile.CatId); throw new ApplicationException(msg, e); } return winKeyboard; }
private void SwitchKeyboard(WinKeyboardDescription winKeyboard) { if (_fSwitchingKeyboards) return; _fSwitchingKeyboards = true; try { KeyboardController.Instance.ActiveKeyboard = ActivateKeyboard(winKeyboard); if (Form.ActiveForm != null) { // If we activate a keyboard while a particular Form is active, we want to know about // input language change calls for that form. The previous -= may help make sure we // don't get multiple hookups. Form.ActiveForm.InputLanguageChanged -= ActiveFormOnInputLanguageChanged; Form.ActiveForm.InputLanguageChanged += ActiveFormOnInputLanguageChanged; } // If we have a TIP (TSF Input Processor) we don't have a handle. But we do the // keyboard switching through TSF so we don't need the workaround below. if (!UseWindowsApiForKeyboardSwitching(winKeyboard)) return; _expectedKeyboard = winKeyboard; // The following lines help to work around a Windows bug (happens at least on // XP-SP3): When you set the current input language (by any method), if there is more // than one loaded input language associated with that same culture, Windows may // initially go along with your request, and even respond to an immediate query of // the current input language with the answer you expect. However, within a fraction // of a second, it often takes the initiative to again change the input language to // the _other_ input language having that same culture. We check that the proper // input language gets set by enabling a timer so that we can re-set the input // language if necessary. _fSwitchedLanguages = true; // stop timer first so that the 0.5s interval restarts. _timer.Stop(); _timer.Start(); } finally { _fSwitchingKeyboards = false; } }
private bool UseWindowsApiForKeyboardSwitching(WinKeyboardDescription winKeyboard) { return ProcessorProfiles == null || (ProfileMgr == null && winKeyboard.InputProcessorProfile.Hkl == IntPtr.Zero); }
private void OnTimerTick(object sender, EventArgs eventArgs) { if (_expectedKeyboard == null || !_fSwitchedLanguages) return; // This code gets only called if TSF is not available(e.g. Windows XP) if (InputLanguage.CurrentInputLanguage.Culture.KeyboardLayoutId == _expectedKeyboard.InputLanguage.Culture.KeyboardLayoutId) { _expectedKeyboard = null; _fSwitchedLanguages = false; _timer.Enabled = false; return; } SwitchKeyboard(_expectedKeyboard); }
/// <summary> /// Gets the InputLanguage that has the same layout as <paramref name="keyboardDescription"/>. /// </summary> internal static InputLanguage GetInputLanguage(WinKeyboardDescription keyboardDescription) { InputLanguage sameLayout = null; InputLanguage sameCulture = null; foreach (InputLanguage lang in InputLanguage.InstalledInputLanguages) { // TODO: write some tests try { if (GetLayoutNameEx(lang.Handle).Name == keyboardDescription.Name) { if (keyboardDescription.Locale == lang.Culture.Name) return lang; if (sameLayout == null) sameLayout = lang; } else if (keyboardDescription.Locale == lang.Culture.Name && sameCulture == null) sameCulture = lang; } catch (CultureNotFoundException) { // we get an exception for non-supported cultures, probably because of a // badly applied .NET patch. // http://www.ironspeed.com/Designer/3.2.4/WebHelp/Part_VI/Culture_ID__XXX__is_not_a_supported_culture.htm and others } } return sameLayout ?? sameCulture; }
private bool UseWindowsApiForKeyboardSwitching(WinKeyboardDescription winKeyboard) { return(ProcessorProfiles == null || (ProfileMgr == null && winKeyboard.InputProcessorProfile.Hkl == IntPtr.Zero)); }