Introduction
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.
Background
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
WM_INPUTLANGCHANGEREQUEST message so that open programs
change their input language. Additionally, the default input
language is updated using the
SystemParametersInfo 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.
Known Limitations
There are some limitations that more work could probably
overcome:
- Console windows do not switch language when they receive the
WM_INPUTLANGCHANGEREQUEST message. 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.