In case you have a yen to extend your keyboard (or at least want a yen?)

by Michael S. Kaplan, published on 2006/09/26 09:01 -04:00, original URI: http://blogs.msdn.com/b/michkap/archive/2006/09/26/771554.aspx


It was last week in the post Variation on that theme of wanting more keys covered by MSKLC that I talked about Olivier's non-specific question about adding additional keys to the keyboard with MSKLC.

And then yesterday, Olivier gave the specifics in a comment:

In my specific case, I was talking about an Apple Japanese keyboard that has 3 keys not present in default layout:

- Yen key (left to delete key)
-  2 keys, one to left and one to right of space bar (used to switch input method)

Under Windows, these keys currrently don't work.

Hope this helps.

Olivier

So now that he gave some specifics, I thought I would dig in a bit. :-)

For this post, I am going to focus on that Yen key that Olivier mentioned (the same key he refers to on the Japanese Apple keyboard exists on the Windows 106 key Japanese keyboard). Here is a picture of the one I have, just so we know what we are talking about:

Now you can compare this to the keyboard you find up on GlobalDev:

   

Hmmm.... that key does not really seem to be very well represented, does it? It definitely isn't that other key under the backspace, either.

And even though MSKLC has a Japanese keyboard on the list of existing keyboards, that one doesn't have this key either. Which is why MSKLC doesn't have this key, by the way -- because no existing keyboard ever maps the scan code. EVER.

So let's see if we can do something here about this, okay? :-)

We'll take that little app I wrote in Handling [Unicode] input in the console and use it with that Japanese keyboard to see what this key outputs:

E:\test\READ\Debug>read
ReadConsoleInput test
Ctrl-D to quit.

#      UC    u/d  VK   SC  State

  0: U+0000 down 00ff 007d 0000
  1: U+0000  up  00ff 007d 0000

Ok, the scan code is 0x7d. Now let's see what that 0xFF scan code is in winuser.h:

#define VK_ATTN           0xF6
#define VK_CRSEL          0xF7
#define VK_EXSEL          0xF8
#define VK_EREOF          0xF9
#define VK_PLAY           0xFA
#define VK_ZOOM           0xFB
#define VK_NONAME         0xFC
#define VK_PA1            0xFD
#define VK_OEM_CLEAR      0xFE

/*
 * 0xFF : reserved
 */


#endif /* !NOVIRTUALKEYCODES */

It looks like this is simply not a VK value, which explains why the code did not find a character!

Of course it is the keyboard layout DLLs that are created by MSKLC that have the job of mapping scan codes to virtual keys. So, now we know what to do, right? We just have to add the right entry to this table!

If you go into MSKLC and choose to save the US layout as a .KLC file (uscustom.klc), you can look at that file in Notepad.

Now just look at the end of a bunch of entries in the LAYOUT table, which look like this:

35 OEM_2    0  002f  003f  -1    // SOLIDUS, QUESTION MARK, <none>
39 SPACE    0  0020  0020  0020  // SPACE, SPACE, SPACE
56 OEM_102  0  005c  007c  -1    // REVERSE SOLIDUS, VERTICAL LINE, <none>
53 DECIMAL  0  002e  002e  -1   // FULL STOP, FULL STOP,

The first column is the scan code, the second is the virtual key minus the VK_, the third is the impact of the caps lock key, and the columns after that are the characters that show up.

So let's add one column just before the "53  DECIMAL" entry (which must be the last entry in the table). Since I am doing this with the US keyboard, I will use VK_OEM_8, a VK value that is not yet used (you can't duplicate scan codes or virtual keys):

7d OEM_8    0  00a5  00a6  -1    // YEN SIGN, BROKEN BAR, <none>

and now we'll compile this keyboard file (change the directory if you installed MSKLC anywhere special):

"C:\Program Files\Microsoft Keyboard Layout Creator\bin\i386\kbdutool.exe" -u -v -w -x uscustom.klc

It will create a uscustom.dll file which you can substitute in for the one MSKLC creates and puts in the uscustom\i386 directory. And you now have a keyboard that will make use of that key on the Japanese 106-key keyboard....

If you play around with the .KLC file later in MSKLC, the entry should remain intact; the only real limitation here is that you can't see the entry in the UI since there is no key there. Which is only the case because not even the Japanese keyboard handles it (this particular key's use is only mediated by the Japanese IME, currently!). Though I at one point suggested adding it to the US and other keyboards, I didn't get much support for it (sometimes I think I wouldn't have been able to get the VK_OEM_102 key added without a ton of proof that it was defined everywhere!).

Now things are a bit more complicated with keys that do not directly involve input, which is why I focused on this particular keyboard (and key). So try not to think of this post as opening up everything, okay?

In fact, there are many special issues involved with the numeric keypad and the cursor keys (and the additional shift state keys) that are involved here which make this more complicated (so I will talk about them another day, probably).

But you can think of yourself as being on the road now for pimping your keyboard beyond what MSKLC does....

Enjoy!

 

This post brought to you by ¥ (U+00a5, a.k.a. YEN SIGN)


Mihai on 26 Sep 2006 2:35 PM:

<<Yen key (left to delete key) >>

"Yen key (left to backspace key)"

Michael S. Kaplan on 26 Sep 2006 3:59 PM:

Well I wasn't going to change his text I was quoting! :-)

Olivier on 27 Sep 2006 12:13 PM:

On the Apple Japanese keyboard, the key next to the Yen key is named "delete", different than a Windows keyoard.

This link has an image of the JIIS keyboard: http://developer.apple.com/technotes/tn/tn1152.html

Michael S. Kaplan on 27 Sep 2006 1:07 PM:

The trick should work here anyway (if not then the key of that keyboard must be generating a different scan code, and you have to find out what scan code it generates).

Emerson on 30 Sep 2006 3:03 PM:

Hey, it seems that has much to do with my problem.
Basically, I want to add two scan codes to my layout: 73 (REVERSE SOLIDUS, LOW LINE) and 7d (YEN SIGN, VERTICAL LINE). I added 73 with VK_OEM_8 and it worked wonderfully. Now I need to add 7d with another VK, would you suggest one?
Thanks in advance.

Michael S. Kaplan on 30 Sep 2006 3:50 PM:

Well, you can actually just look at the .KLC file created by MSKLC and then at winuser.h where the VKs are defined....  like maybe VK_OEM_AX or something similar?

Like I said, the key is just to make sure it is not already on the keyboard (either explicitly in the layout file or implicitly like the numpad keys).

Emerson on 30 Sep 2006 8:22 PM:

Yeah, I got it, but I could not make it work the way I want.

Unfortunately I tried a lot of VKs (VK_OEM_AX, VK_JUNJA, VK_FINAL, VK_ACCEPT, VK_MODECHANGE, VK_NEXT, VK_F13, etc.) and none of them has worked.

It gives me an error with the following messages:

kbdname.c
kbdname.C(80) : error C2121: '#' : invalid character : possibly the result of a macro expansion
kbdname.C(80) : error C2121: '#' : invalid character : possibly the result of a macro expansion
kbdname.C(80) : error C2065: 'ERROR' : undeclared identifier
kbdname.C(80) : error C2099: initializer is not a constant
kbdname.C(275) : error C2014: preprocessor command must start as first nonwhite space
kbdname.C(275) : error C2078: too many initializers
kbdname.C(278) : error C2059: syntax error : ';'

CL.EXE returned 2

LINK : warning LNK4224: /DEBUG:FULL is no longer supported; ignored
LINK : warning LNK4224: /DEBUG:FULL is no longer supported; ignored
LINK : fatal error LNK1181: cannot open input file 'kbdname.obj'

LINK.EXE returned 1181


It's like VK_OEM_8 is the only one accepted. Or I am doing something wrong...

Actually, if I add only 73 with VK_OEM_8, 7d works even without being listed in the .KLC file:

39 SPACE 0 0020 0020 0020 -1 -1 // SPACE, SPACE, SPACE, <none>, <none>
73 OEM_8 0 005c 005f -1 -1 -1 // REVERSE SOLIDUS, LOW LINE, <none>, <none>, <none>
53 DECIMAL 0 002c 002e -1 -1 -1 // COMMA, FULL STOP, , ,

But it prints \ instead of ¥.

Anyway, I'm kind of satisfied with that... VK_OEM_8 made my day.

Thanks a lot.

Emerson on 30 Sep 2006 8:44 PM:

Ooops... One correction: adding only 73 does not enable 7d.

I thought it did because just after I installed the layout with only 73, the yen key worked (printing a "\"), but I also noticed the dead keys were not working.

So I rebooted and the dead keys work now, but not the yen key. In other words, the layout works exactly the way it's supposed to: with 73 enabled (VK_OEM_8), but not 7d.

It seems it's impossible to find another "free-to-use" VK_ :(

Now I am sad again, heh.

Emerson on 30 Sep 2006 9:06 PM:

Damn! Sorry for "flooding" your blog, Michael! (You can edit my comments to make them more "pleasant" to eyes.)

Forget what I said about the yen key working because I did not reboot. I had simply selected the wrong layout.

Other than that, things keep going the way I described (I need other "free-to-use" VKs).

That's it.

Many thanks.

Michael S. Kaplan on 30 Sep 2006 11:20 PM:

Well, three posts do not make a flood, but it is getting closer.... :-)

I think I said you really can't grab VK values that have alternate functionality attached to them, like a lot of the ones you have tried. You need to try one (like OEM_AX?) that is not attached to other special behavior....

Michael S. Kaplan on 1 Oct 2006 12:40 AM:

A couple of "extra" ones you could try are ABNT_C1 and ABNT_C2 (from kbd.h, where you can see VK_ABNT_C1 and VK_ABNT_C2 defined)....

referenced by

2011/11/04 The evolving Story of Locale Support, part 4 (working beyond one's bugs, and the case for an MSKLC update)

2010/06/08 Hunting for VK_HANGUL, aka If you press a key that your code can't process, did you really press it?

2008/10/27 Not only going BACK, but changing how to do it

2008/06/27 Adding keys to your layout when you don't know what they are (aka Life with a 108-key keyboard layout)

2008/05/16 My Spidey senses blame the rogue text editor

2007/07/04 Pimping the numeric keypad

2006/10/07 Pimping your Brazilian keyboard

go to newer or older post, or back to index or month or day