Arthur's dev blog

International keyboard layout handling

In the Outlook add-in project I'm working on there is a feature that if the users enters '@' character in the body of mail editor window a dropdown popup will show with some options.
Because this feature is on Outlook window we implemented the feature by capturing keyboard events1 and waiting for "shift + 2" keycode. We check for "shift + 2" because the captured windows keyboard message contains keycode and not the actual character.
In a beta phase an European client reported that this functionality doesn't work, a quick session with the client revealed he used European keyboard layout, something new to me as I used to US keyboard layout.

The bug

Comparing keyboard message keycode with "shift+2" to handle '@' character ignores the different keyboard layouts, handling only US keyboard layout, European and Asian keyboard layout will fail.

How to handle different keyboard layouts

.NET framework provide a very useful class: InputLanguage with static CurrentInputLanguage and InstalledInputLanguages properties allowing to get the current and all installed culture/keyboard layout pairs.
But by itself the InputLanguage class doesn't provide a way to convert character to keycode and vice versa. To accomplish this we need to resort to Win32 API in user32 dll, ToUnicodeEx and VkKeyScanEx are able to convert keycode to character and character to keycode respectively (sample code can be found below).

The solution

Using InstalledInputLanguages with GetKeyboardShortcutForChar method (see below) to get all the keycodes for all installed culture/keyboard layout pairs and then including the CurrentInputLanguage in comparing the keyboard message keycode to the collection of keycodes collected for specific character.
I have chosen this approach and not converting the keyboard message keycode into character because then I will have to call ToUnicodeEx for each keyboard event, an overhead my approach lacks.