What the %$#!* is wrong with VkKeyScan[Ex]?

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

The VkKeyScanW and VkKeyScanExW functions have a simple, documented functionality:

...translates a character to the corresponding virtual-key code and shift state...

Not the sort of thing you would need all the time, but it can come in handy.

They both take a WCHAR as a parameter and (from the documentation):

If the function succeeds, the low-order byte of the return value contains the virtual-key code and the high-order byte contains the shift state, which can be a combination of the following flag bits.

If the function finds no key that translates to the passed character code, both the low-order and high-order bytes contain –1.

Bit Meaning
1 Either SHIFT key is pressed.
2 Either CTRL key is pressed.
4 Either ALT key is pressed.
8 The Hankaku key is pressed
16 Reserved (defined by the keyboard layout driver).
32 Reserved (defined by the keyboard layout driver).

Seems simple enough, right? :-)

Unfortunately, things are never as simple as they seem when it comes to keyboards.

The other day, friend Gregory called me up to ask me a question about the keyboard he created with MSKLC.

On his keyboard, he had added the same letter in two different spots on the keyboard (one on the VK_OEM_102 key, and the other on the ALTGR+VK_OEM1 key).

So he was looking at some code he had that used the VkKeyScan function, and it suddenly occurred to him that he had no idea which VK/SC it would return. After trying it out he found it returned the one he didn't actually want it to (the one on the ALTGR+VK_OEM1 key).

And now, he figured since he knew the person who did the development work on MSKLC that he could ask what the deal was here.

After I explained it to him, I thought it might make a nice blog entry!

I'll start off by saying that VkKeyScan has some limitations, starting with the one Gregory ran into -- when a function's purpose is to return the Virtual Key and the shift state, there is only so much it can do when there are two answers to the question, both equally valid.

And the decision in the case of a keyboard created by MSKLC is not one that can be controlled within the tool -- it is in essence controlled by the order in which the entries in the LAYOUT table are written (that order is deterministically created by MSKLC as matching the order of the keys in the US keyboard, and then putting the VK_OEM_102 key almost at the end).

I pointed out to Gregory that he had to pick the one key that would pretty much always lose the battle here. :-)

Now VkKeyScan has other limitations (documented and undocumented).

Such as the fact that it will not work with ligatures.

Or dead keys.


Or anything on the numeric keypad.

There is also that it does not distinguish between the left and the right SHIFT/CTRL/ALT keys, which rules out all of those more complex shift states like the RIGHT CTRL key on the Canadian Multilingual Standard keyboard layout. Or any other complex shift states you can set up.

Now that last paragraph talks about features not in MSKLC, but that I'll be covering soon enough in that series I am working on about interrogating keyboard layouts....

But in any case, you get the point -- VkKeyScan and VkKeyScanEx will definitely never be able to be confused with functions that have all the answers. Since they have been around since Windows 95/NT 3.1, I can think of two possible reasons for this problem. Either

The obvious question that comes up at this point is whether the limitation in MSKLC is one that would be considered a bug to fix.

Interesting question, and from a triage standpoint an interesting issue to consider. There are a lot of relevant facts here:

But maybe it would make a nice KB article at some point. Or a blog entry up here, some day....

If it helps, the sample I am putting together in that other series of posts will not suffer from any of those limitations from either VkKeyScan or VkKeyScanEx! :-)

Though I am sure those who are following that series will understand why a new version of those functions that addressed the limitations might not be likely. It is pretty difficult to extract that info!

Which is not to say that a generic function that took and end result of one or more UTF-16 code units and returned the exact set (or sets) of keystrokes that would produce it would not be useful....

But conceptually where does one draw the line between requiring two or more keystrokes for dead key entry but not allowing the typing of two or more separate characters for combining forms? Perhaps keyboard authors would be willing to make the distinction, but what about the rest of the world?


This post brought to you by "ĩ" (U+0129, a.k.a. LATIN SMALL LETTER I WITH TILDE)

# Michael S. Kaplan on 26 Mar 2006 2:01 PM:

Notice how I did not even get into the issue of the awful name of this function -- I'll be talking about that soon, though. :-)

# Todd on 18 Apr 2008 2:00 PM:

It seems that VkKeyScan might suck more than you've actually let on.  For some reason, in my application, I try to run a string through VkKeyScan one character at a time and collect the VkKeys.  However, the function returns the correct value only on the first character.  After that, it continuously returns -1.

What's up with that?

# Michael S. Kaplan on 18 Apr 2008 2:55 PM:

I'd want to know the code, the keyboard, and the string that repros that....

Though note the follow-up comments poiinting to other VkKeyScan[Ex] problems.

# Todd on 18 Apr 2008 3:28 PM:

My apologies.  I was calling VkKeyScanW from C#.  I was under the assumption that C# characters were unicode.  I thought I needed to call the wide version.  If I cast the C# characters to shorts then it works every time.  If I just call VkKeyScan (without specifying wide), it works as well (without casting to shorts).

Please consider a donation to keep this archive running, maintained and free of advertising.
Donate €20 or more to receive an offline copy of the whole archive including all images.

referenced by

2010/12/27 You have to deal with Hebrew periods where they come up

2008/09/03 Need to know the VK for A, ay?

2006/09/10 Further proof that VkKeyScanEx sucks

2006/04/12 Getting all you can out of a keyboard layout, Part #9a

2006/03/27 Getting all you can out of a keyboard layout, Part #4

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