Switch / change the Windows language, even if the application is not focused

Is there a way to determine if the windows / os language has changed even when my application is out of focus?
So far, I have managed to achieve what I wanted only if the application was focused with:

string language = ""; System.Windows.Input.InputLanguageManager.Current.InputLanguageChanged += new System.Windows.Input.InputLanguageEventHandler((sender, e) => { language = e.NewLanguage.DisplayName; MessageBox.Show(language); }); 

But, as you can understand, this is not exactly what I want.

I was thinking of another solution, for example, connecting keys that change the language (for example, alt + shift), but I will not know which language is currently used, and the user can change the default hotkey ...

Thank your help.

+7
c # wpf hook
source share
1 answer

The problem you are facing is how the WM_INPUTLANGCHANGE message works. This message is sent to programs by the operating system to inform them of language changes. However, according to the documentation , this message is sent only to "to the topmost damaged window." This means that you can even call your own GetKeyboardLayout method (by the way, it is used by InputLanguageManager), but if the application is inactive, GetKeyboardLayout will always return the last known, outdated language.

Given this, it might be a good idea to use the solution @VDohnal points to, find the current topmost window and read the keyboard layout for it. Here is a brief proof of how to do this in a WPF application. I used an additional thread, which periodically finds the topmost window and a ready-made keyboard layout for it. The code is far from perfect, but it works, and it can help you implement your own solution.

 public partial class MainWindow : Window { [DllImport("user32.dll")] static extern IntPtr GetKeyboardLayout(uint idThread); [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr processId); private CultureInfo _currentLanaguge; public MainWindow() { InitializeComponent(); Task.Factory.StartNew(() => { while (true) { HandleCurrentLanguage(); Thread.Sleep(500); } }); } private static CultureInfo GetCurrentCulture() { var l = GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero)); return new CultureInfo((short)l.ToInt64()); } private void HandleCurrentLanguage() { var currentCulture = GetCurrentCulture(); if (_currentLanaguge == null || _currentLanaguge.LCID != currentCulture.LCID) { _currentLanaguge = currentCulture; MessageBox.Show(_currentLanaguge.Name); } } } 
+6
source share

All Articles