Skip to content

Links & Notes

Rimas Kudelis edited this page Jul 19, 2023 · 20 revisions

This page holds various links which may be of interest to anyone who wants to develop keyboard layouts for Windows and/or considers moving away from MSKLC and/or wants to reuse the installer generated by MSKLC in a customized build process.

I tried to organize them somewhat, but essentially they're just a dump of the list of my currently opened browser tabs, so some of them might be less relevant than others.

Generic

Building layouts

Installing layouts

Installation notes

All keyboard layouts on Windows are registered as subkeys under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\. When I mention registry subkeys and values below, I'm talking about subkeys of this key and values under those subkeys. Here are examples of registry subkeys for stock layouts:

stock layout 1 stock layout 2

and here's one for my custom layout:

custom layout

MSKLC installer adds some extra keys (Custom Language Display Name, Custom Language Name and Layout Product Code). I'm not sure what the purpose of the two Custom * entries is, but the Layout Product Code entry seems to be required and used by the (un)installer's CA02, CA03 and CA04 custom actions, which are passed no custom action data during (un)installation.

As can also be seen in the screenshot, subkey names for custom layouts registered by the KbdMsi installer custom action start with a000**** and grow upwards in the same fashion the stock ones do (last four characters indicate the language/locale, and the first four must be unique for each layout within that locale).

Layout Id values for custom layouts start with 00c0 and are increased for each layout. I haven't checked though if this is just the first available id, or some predetermined value. For what it's worth, some stock layouts also have Id's in 00C* range

Windows 8-10-11 notes

Begginning with at least Windows 8, stock Windows keyboard layouts spot additional functionality. Sadly, neither the MSKLC-generated layouts, nor any Microsoft examples or other open-source layouts seem to support them yet (at least I'm not aware of that). I've noticed at least three such new features so far. Below are my findings about them.

Abbreviated layout name

This refers to two to four characters, shown in the keyboard switcher/indicator when more than one layout is enabled for a particular language (e.g. DV, DVR, DVL for the three different English Dvorak layouts or LT, LTI, LTS for the three Lithuanian layouts).

I found all of these strings in C:\Windows\System32\en-US\InputSwitch.dll.mui, so InputSwitch.dll is the actual library that provides them, but it is not documented and only has two (seemingly generic) exported functions.

These abbreviated names seem directly linked to each layout's Layout Id value. If I edit the registry and change the Layout Id of my layout to one of those used by the stock layouts, then my layout will use that stock layout's name and abbreviated name. But it has unwanted side effects: it seems that then I can no longer use the original layout, and the whole setup becomes kind of unstable. Probably not worth it, if can't be done properly.

The QWERTY/AZERTY/* indicator

This string is shown in the keyboard list in language options in the Settings app. Here's a (stolen) screenshot from Win8, but same indicator is also visible in Win 11. I haven't found where these strings are even stored yet:

screenshot

Touch-optimized layouts

The on-screen keyboard ships with touch-optimized layouts based on the physical keyboard layouts. It seems that these are implemented in TipRes.dll (e.g. C:\Windows\WinSxS\amd64_microsoft-windows-tabletpc-inputpanel_31bf3856ad364e35_10.0.22000.65_none_f3a35be8937453f0\TipRes.dll). The list of mappings from physical layouts to on-screen layouts is an XML structure stored in the KEYBOARDLIST HTML resource, and works somewhat like this:

  1. Each layout has an ID, and each Layout ID is mapped to a Group ID. Multiple layout IDs might be mapped to the same Group ID.
  • For layouts with registry subkey names which match the 0000**** mask, the ID is that subkey name, but truncated to the last 4 characters (e.g. subkey name 00000427 (Lithuanian IBM layout) becomes ID 0427).
  • For all other layouts, the ID is the value of Layout Id string value plus F000 (e.g., the layout registered as 00010427 (Lithuanian) has the Layout Id string value of 0027 and thus it's ID is F027).
  1. Each Group specifies several Views (typically three, but CJK groups have more) via View child elements.
  • Each View element has Type, Layout and Data attributes.
  • Type is a string (probably one of several constants, which map to an icon or something like that).
  • Layout is a string which references a different HTML/XML resource within the same TipRes.dll file. Each such Layout resource describes how keys are laid out in the on-screen keyboard.
  • Data is also a string which references a different HTML/XML resource within the same TipRes.dll file. Each such resource describes what characters each key described in Layout will input in each relevant shift state, as well as which keys have which pop-up characters (if any).

This kinda makes me wonder why all of this XML-based configuration was embedded in the DLL instead of being stored as plain XML files (with the ability to add new files to the set or even modify existing ones after disabling SFC).

Anyways, like mentioned above, if I install my ltenh layout, it gets a Layout Id of 00c0 and up. There is no mapping for a layout with an ID of F0C0 in TipRes.dll, so I suppose that's why my layout only gets the default the on-screen layout (and I just noticed that that default doesn't even spot an AltGr key on Windows 11). Again, changing layout ID and rebooting switches the on-screen keyboard to the desired one, but causes other issues (and the OSK can't be customized!), so I don't think it's worth all that trouble. Until and unless it can be done properly, I think it's better to just let Windows generate the full OSK for those who need it.