Hook/detect windows language change even when app not focused

僤鯓⒐⒋嵵緔 提交于 2019-11-29 04:13:16

The problem you are facing is related with how WM_INPUTLANGCHANGE message works. This message is sent to programs by operating system in order to inform them about language changes. However, according to documentation this message is sent only to "to the topmost affected window". It means that you can even call a native method GetKeyboardLayout (it is used by InputLanguageManager by the way) but if an application is not active GetKeyboardLayout will always return the last known, outdated, language.

Taking this into account it might be a good idea to use the solution pointed by @VDohnal i.e. find the current topmost window and read keyboard layout for it. Here is a quick proof of concept how to do it inside WPF application. I used an additional thread that periodically finds the topmost window and ready keyboard layout for it. The code is far from being perfect but it works and it might help you to 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);
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!