how to programmatically install a keyboard layout?

Alan Sinclair 11 Reputation points
2020-10-21T19:49:20.803+00:00

I need to package several different keyboard layouts aka "input locale identifiers" together, so I need to write some code to install a layout in Windows, but haven't found any documentation. Can anyone show me example code or point me to documentation? Backgound: Microsoft's MSKLC tool enables creation of Keyboard Layouts. Each single layout is 'contained' in a DLL; for a layout MSKLC creates four DLLs for various flavors of Windows (naming them i386, amd64, ia64, wow64). MSKLC also creates the three appropriate MSI installers for that single layout, but those installers cannot be used in this situation. Just deploying the DLLs doesn't enable them, there is obviously some action needed to add the new locale identifiers to what Windows knows about its keyboards.

(I'm unsure this is the right place for this question, and what tags should be used .. please correct me if necessary)

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,426 questions
{count} vote

17 answers

Sort by: Most helpful
  1. Robert Sullivan 11 Reputation points
    2020-11-20T17:13:01.333+00:00

    There has to be more to it than what Drake-WU has described.

    What does 'add the corresponding key value according to other layouts' mean?

    I created a Keyboard Layout with MKLSC. The install package calls out to an imbedded Custom.dll to perform some registry operations.
    The installed keyboard appears within the 'Language Bar'.

    I created a Keyboard layout from the Sample Keyboard Layouts (KBDUS.dll), ClientUs.dll.
    'Installed' it following your suggestion (I think?)

    'add the corresponding key value according to other layouts':
    I modeled the registry values under [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00060409]
    after the registry values for [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000409].
    Is this what you mean?

    HKEY_CURRENT_USER\Keyboard Layout\Substitutes has a REG_SZ entry for d0020409 with a value of 00060409
    HKEY_CURRENT_USER\Keyboard Layout\Preload has a REG_SZ entry for 3 with a value of d0020409

    Note: I picked 00060409 arbitrarily.

    My Keyboard Layout shows up in Settings->Time & Language->Language->English->Options->Add a keyboard.
    I can add the keyboard.
    I can load the layout via LoadKeyBoardLayout("00060409").

    My Keyboard Layout does not show in the 'Language Bar'.

    Does something additional need to occur for an install to show up in the 'Language Bar'?

    Thanks

    0 comments No comments

  2. Alan Sinclair 11 Reputation points
    2020-11-20T20:38:25.523+00:00

    > Does something additional need to occur for an install to show up in the 'Language Bar'

    The custom.dll used in the MSKLC installer has two functions for installing the layout: 'RegisterKeyboard', and 'AddKeyboardToLangBar' (entry points CA01 and CA03 respectively); it also provides two uninstall functions: 'UnRegisterKeyboard' and 'RemoveKeyboardFromLangBar' (entry points CA02 & CA04).

    So I guess you need a function analogous to 'AddKeyboardToLangBar'. Which is probably DrakeWu's example line 3 does:

           ret = ActivateKeyboardLayout(hkl, KLF_SETFORPROCESS);
    

    [I haven't yet had an opportunity to use DrakeWu's example. I only get to revisit this issue occasionally so my apologies if this comment is uselessly out of date]

    Btw the custom.dll's CA03 'AddKeyboardToLangBar' adds more registry entries but I haven't experimented with replicating those

    anonymous userSullivan-9551
    If you get this working please share!

    thanks

    0 comments No comments

  3. Robert Sullivan 11 Reputation points
    2020-11-21T17:14:13.6+00:00

    I am piping in on this due to the fact that I have a Windows 10, C++.
    application that needs to use two Custom Keyboard Layouts in conjunction with
    a Keyboard Filter Driver.

    The real answer here is for Microsoft to simply release the source code for the Custom.dll imbedded within an MSKLC installer package. I am surprised that they have not already done so. I am of course not sure where to post such a request and what tags to attach to it or how to word the topic in order to get the appropriate People's top see it.

    I have not visited MSND for quite some time now. I am surprised at the limited 'tags' one can apply to a topic. I believe that winapi-general seems to be the only suitable 'tag' to apply to any sort of Win32 based question. It seems this site has become really azure concentric.

    When I am done with this post I will post a request for the source code to Custom.dll titles 'MSKLC / Custom.dll Source Code' tagged with winapi-general so you can find it.

    What DrakeWu described will work if one simply wants to load the Keyboard Layout and activate it,
    but the Keyboard Layout will NOT appear within the Language Bar.
    I have two 'Custom' Keyboard 'Installed':

    • A Custom Keyboard Created And Installed Via MSKLC. Named: US-Custom
      This Keyboard shows up within the Language Bar.
    • A Custom Keyboard I created from the KBDUS Sample Layout and 'Installed' as DrakeWu suggested. Named: 'Client-US'.
      This Keyboard DOES NOT show up within the Language Bar.

    Here is some output:
    Initial ActiveKeyBoard:0x04090409
    Initial KeyBoardLayoutName:00000409
    GetLayoutFromRegistry():SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00000409
    Layout Text::US

    // This Is 'My' Keyboard Layout.
    LoadKeyBoardLayout(00060409,(UINT)0)
    LoadedKeyboardLayout:0xFFFE0409
    ActivateKeyboardLayout(0xFFFE0409,KLF_SETFORPROCESS)
    Last LoadedKeyboardLayout:0x04090409
    LoadedKeyboardLayout Now:0xFFFE0409
    GetKeyboardLayoutName():00060409
    GetLayoutFromRegistry():SYSTEM\CurrentControlSet\Control\Keyboard Layouts\00060409
    Layout Text::Client-US
    BufferKeyBoard:Client-US

    // This Is The Keyboard Created And Installed With MSKLC
    LoadKeyBoardLayout(a0000409,(UINT)0)
    LoadedKeyboardLayout:0xF0C00409
    ActivateKeyboardLayout(0xF0C00409,KLF_SETFORPROCESS)
    Last LoadedKeyboardLayout:0xFFFE0409
    LoadedKeyboardLayout Now:0xF0C00409
    GetKeyboardLayoutName():A0000409
    GetLayoutFromRegistry():SYSTEM\CurrentControlSet\Control\Keyboard Layouts\A0000409
    Layout Text::US - Custom
    BufferKeyBoard:US - Custom

    //======================================================================
    As a side bar I am annoyed with the fact that is seems impossible to ascertain the appropriate KLID from a HKL:
    HKL For MSKLC Keyboard: 0xF0C00409
    KLID For MSKLC Keyboard: 0xa0000409

    There seems to be no bit manipulation that can produce a0000409 from F0C00409
    This makes GetKeyboardLayoutList() useless for my purposes.

    0 comments No comments

  4. Robert Sullivan 11 Reputation points
    2020-11-25T19:01:56.937+00:00

    Alan.

    See my post over in stackoverflow

    Not sure if this relates to your install scenario in the end but it relates to mine.
    If you read between the lines one can see that the HKEY_USERS.DEFAULT\Keyboard Layout (I think that is the appropriate key) seems to come into play if you want the system to actually load your keyboard at boot so one does not need to physically load it via LoadKeyboardLayout().

    I will give my request for the Custom.dll source a day or two. If I get no response I will start asking questions on Stackoverflow.

    0 comments No comments

  5. Robert Sullivan 11 Reputation points
    2020-12-09T14:02:34.497+00:00

    Alan, you are testing within a console application?
    See this post.

    0 comments No comments