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:

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

  1. 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: http://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.

  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.

Leave a Reply

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