by Michael S. Kaplan, published on 2012/05/17 07:01 -04:00, original URI: http://blogs.msdn.com/b/michkap/archive/2012/05/17/10306133.aspx
The question came in just the other day:
Hi Michael,
Do you have a list of all the keyboard cultures in Win8—or alternately which API would return me such a list (looking at your blog(s) I couldn’t easily determine what this API would be. All the APIs seemed to be about installed keyboards).
Questions like this always make me nervous you see.
Because almost invariably, there is something behind such questions.
Now in the end, there is no specific Win32 function to enumerate every keyboard.
Essentially one has enumerate every subkey to
HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layouts
So, I decided, after saying this, to try to find out the underlying issue. The answer came back readily enough:
There seems to be a change in behaviour (?) of when converting the keyboard ID to a culture. For example, zh-HK used to work but is now returning zh-HanT-HK. I wanted a list of these to ensure we do the right thing on our end.
It asks for the currentInputLanguageTag, and then tries to convert it to lcid using LocaleNameToLCID. However, it seems to fail for Tibetan and also Chinese Traditional IME (Hong Kong with Microsoft IME) languages which come shipped with Windows.
Now here is where the problem is obviously tangled up with someone else's implementation.
You see, that registry key's subkeys are called Keyboard Layout IDentifiers (aka KLIDs), some of which have Layout Id values under them, and at runtime each installed (loaded) keyboard layout has an HKL value associated with it, the lower 16 bits of which has a relationship with the KLID's lower 16 bits -- both of which sometimes have a relationship with the Language Identifier (aka LANGID) values that represent the lower 16 bits of Locale Identifiers.
Times they don't have such a relationship include both situations I directly caused as described in Getting the language (and more!) of an LCID-less keyboard/MSKLC keyboard layout names in your own language and situations I inspired/indirectly caused as described in The evolving Story of Locale Support, part 2 (raising the roof on keyboards).
Anyway, you might have noticed one of the things that was never mentioned:
keyboard IDs.
currentInputLanguageTags.
cultures.
And of course there is no LCID value that LocaleNameToLCID would ever return zh-Hant-HK for 0x0c04 (aka zh-HK).
I mean we have our problems in Windows mapping names -- e.g. Four cases where I don't like ResolveLocaleName (and you shouldn't either!) -- but this looks like an external issue is contributing or causing the problem.
So whatever the problem is here, some work to clean up the stuff the callers are doing will be needed before I could comment on whatever problem the are hitting.
To get back to the original question about a list?
We don't have that, as I said.
But if you enumerate those subkeys under
HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layouts
you can then extract the lower 16 bits, and then anytime it doesn't return 0x0c00, you can call LCIDToLocaleName (removing duplicates at they come up) to get a fairly robust list of "keyboard cultures".
This leaves just two other groups:
I find the last bit to be slightly unfortunate from a decision-making standpoint (I originally recommended they add a Layout Locale Name value too) , but the list will be limited since there are only a few of them.
At some point, I'll probably publish the list here myself, and recommend that the MSDN documentation writers do the same
That just leaves out the IMEs, but the original question was just about keyboards, so I guess they're their own for that bit. :-)
Brian Tkatch on 17 May 2012 8:02 AM:
And here i thought the first on a 'keyboard culture' list would be old coffee.