My laptop has a Portuguese keyboard which I use when I am at home, but at work, I use an external keyboard with a Belgian layout. This is annoying because every time I switch keyboards, I need to go to every open program and manually change its input language with the language bar. Worse, when I start a new program, it starts with the default language, which means that sometimes I have to switch input language also.
One way to work around this problem could be to buy a new keyboard, but I like the IBM model M keyboard and I have yet to find a better keyboard.
Instead of doing that, I wrote a program that switches to the correct input language when I start using a keyboard.
Although more than one keyboard may be connected to the same computer, the Win32 API treats them as if there was only one keyboard. A program receives key strokes from every keyboard, but has no way of knowing which keyboard sent a particular stroke.
Usually, this is exactly what the program wants. It is the role of the Operating System to shield the program from the complexity of dealing with multiple input devices. But in this case, we need to know which device has been used in order to switch the input language. Luckily, the raw input API exposes which device is sending the messages, which solves our problem.
How it works
Describing the raw input API is outside of the scope of this article.
The MSDN documentation
already provides plenty of information about it. We will stick to the essential.
The API allows a program to register to receive notifications each time a keyboard sends an event.
When the notification is received, the program checks if it comes
from a different device than the previous one. In that case,
the program selects the appropriate input language and broadcasts the
message so that open programs change their input language. Additionally,
the default input language is updated using the
function, which causes new programs to start with the correct input language.
When a keyboard is used for the first time, the program asks the user which language is to be used.
When the program is closed, a file is saved in
%USERPROFILE%\Local Settings\Application Data\RightKeyboard
that contains the associations between the device identifiers and the input languages.
When the program starts, that information is loaded so that the program
already knows the correct language for any previously used keyboard.
Using the program
The program is easy to use. Simply run it and an icon will appear in the notification area. The icon allows to close the program when right-clicked. The first time a keyboard is used, a popup will appear with a list of the available input languages. Select the correct language, then click OK. From now on, each time that keyboard is used, every application will switch to that language. More input languages can be added in the Regional and Language Options on the Control Panel.
You can download the program from the CodeProject page where I originally published this article.
There are some limitations that more work could probably overcome:
Console windows do not switch language when they receive the
WM_INPUTLANGCHANGEREQUESTmessage. Any such window that is already open when the program switches the input language will keep the current language.
When the program switches the input language, the currently focused window receives the key before the change. Because of that, the first key that is pressed on another keyboard is always incorrect, unless that particular key is the same on the previous language.
After hibernating, the device handles become invalid, which makes the program ask the language for a previously known keyboard.