Esempio n. 1
0
        /// <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);
        }
Esempio n. 8
0
		/// <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);
		}
Esempio n. 9
0
		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;
		}
Esempio n. 10
0
		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;
			}
		}
Esempio n. 11
0
		private bool UseWindowsApiForKeyboardSwitching(WinKeyboardDescription winKeyboard)
		{
			return ProcessorProfiles == null ||
				(ProfileMgr == null && winKeyboard.InputProcessorProfile.Hkl == IntPtr.Zero);
		}
Esempio n. 12
0
		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);
		}
Esempio n. 13
0
		/// <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));
 }