C#: Get current keyboard layout\input language

Get current input language on Windows with C#

On some occasions, you may want to get a "global" input language - that is, the keyboard layout used by the current foreground window\application\whatever. Basically, simulating the behaviour of the language panel on Windows.

The common use cases are on-screen keyboards, fullscreen applications, and widgets.

While I wasn't able to find a premade function that get this particular thing during my searches, it turned out not to be too hard to assemble:

[DllImport("user32.dll")] static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr hwnd, IntPtr proccess);
[DllImport("user32.dll")] static extern IntPtr GetKeyboardLayout(uint thread);
public CultureInfo GetCurrentKeyboardLayout() {
	try {
		IntPtr foregroundWindow = GetForegroundWindow();
		uint foregroundProcess = GetWindowThreadProcessId(foregroundWindow, IntPtr.Zero);
		int keyboardLayout = GetKeyboardLayout(foregroundProcess).ToInt32() & 0xFFFF;
		return new CultureInfo(keyboardLayout);
	} catch (Exception _) {
		return new CultureInfo(1033); // Assume English if something went wrong.
	}
}

So, first, we import a couple of functions from user32.dll:

  • GetForegroundWindow, to get the current foreground\active window' pointer.
  • GetWindowThreadProcessId, to get the ID of the thread that created the particular window.
  • GetKeyboardLayout, to get the keyboard layout ID currently used by the given thread.

The actual function then proceeds to combine these in a straightforward manner to obtain the keyboard layout ID for the current active window.

Then a System.Globalization.CultureInfo is created based on ID, permitting to conveniently get the language name in various formats and a handful of other useful information.

If there's no foreground window available, GetKeyboardLayout will return 0 (which is not a valid ID for CultureInfo), and the catch-block will return En-US as a fallback language (alternatively, you can return null and handle that separately).

And that's it. Have fun!

Related posts:

7 thoughts on “C#: Get current keyboard layout\input language

  1. This method does not work sometimes because it needs a thread id, and you are getting this from the current foreground window. Problem is that you not always have a window opened and apparently, apps from windows store wont be usable.
    Maybe if you get a random working thread this will work. Or, if that doesn’t work, you may search for a usable window that is not necessarily in the foreground.
    You can do the second option based on the answer to that question here :
    https://stackoverflow.com/questions/20470389/how-to-get-running-applications-in-windows?noredirect=1&lq=1
    As for the other options, I not YET tested.

    • Not having a window opened is not an issue as even the desktop is formally just another window (see GetDesktopWindow).

      Finding a random process is a way to get some input language, but not necessarily the one that’s being used by the foreground application, as there’s that setting to allow different applications to have different input language states.

      So this really boils down to UWP app windows being Their Own Thing for whatever reason. Seems like Spy++ can see them, but you’d need to research how does it accomplish that.

  2. This will not work when UWP app (from widnows store) is active and you change the input method. Somehow it gets detected only when a desktop app is the foreground window. Any idea how to fix that?

    • Good question. Running as administrator does not seem to affect this either.

      I can’t test at this exact moment, but can only assume that either GetWindowThreadProcessId or GetKeyboardLayout return not what they should for store apps. Perhaps there’s a separate\newer API somewhere..?

      • I checked this. Both methods return correct data. Or at least the data change when changing the active window.
        I have been searching extensively and so far without success of finding any solution to this.

  3. Hi,
    I have a code similar to yours (may have been originated by yours?).
    It works fine on Win7, except for English.
    If the current keyboard language is English and you change to another language by mouse, it will still show English, regardless of the computer default language. It will change to the correct language by another mouse click.
    I tried all kinds of workarounds, but for no avail.
    Please try to change from English to any other by mouse, and help me find a way to fix this.
    Sam

    • Perhaps something was different on Windows 7, because on Win8 and Win10 that is working perfectly fine: https://yal.cc/wp-content/uploads/2016/07/cs-keyboard-layout-switch.gif

      Does it remain undetected permanently, or does it take note by the time you start typing something? The most I can think of is that the language bar could be stealing window focus (while likely not counting as a window), therefore making the change not immediately noticeable by code.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.