VK_DECIMAL is always valid (except formerly in Serbia)

by Michael S. Kaplan, published on 2007/10/27 15:31 -04:00, original URI: http://blogs.msdn.com/b/michkap/archive/2007/10/27/5717859.aspx


Regular reader, comrade, veritable demigod in all things related to keyboards, and the man behind Tavultesoft Keyman, and provider of Australian beer Marc Durdin mentioned to me:

Hi Michael,

Just an FYI - didn't see a mention of it on your blog...

We had a report recently of a hang in Keyman associated with the Serbian Cyrillic keyboard. After tracing it back to our on screen keyboard, we discovered that the issue was with a ClearKeyboardBuffer function (developed independently, but then updated to use VK_DECIMAL as you suggest in
http://blogs.msdn.com/michkap/archive/2006/04/06/569632.aspx).

With the Serbian Cyrillic layout, ToUnicodeEx(VK_DECIMAL, sc, lpKeyStateNull, sb, sb.Capacity, 0, hkl) returns 0. Unfortunately, ClearKeyboardBuffer can never be terribly robust as we don't know what the keyboard layout is going to give us...

We checked the function against every other layout in XP, and Serbian Cyrillic was the only one to fail. Haven't checked against Vista layouts.

Cheers,

Marc

Marc is right. The ClearKeyboardBuffer function, first introduced in Getting all you can out of a keyboard layout, Part #7, does have a bug in it.

A bug that is reproducible in the Serbian (Cyrillic) keyboard layout that ships with Windows NT 4.0, 2000, XP and Server 2003, and only because that keyboard layout contained a bug in it.

Here is the "broken" layout:

Note especially that key for the Decimal Separator -- looks like there is nothing in it, right?

Looking at the key in all shift states:

Indeed, there is nothing in it.

So much for VK_DECIMAL being the one key that is in literally every layout!

Now the problem is fixed in the layout in Vista:

I just looked at the source code logs, and it turns out that I am the one who checked in the fix for this, back in the end of April 2004. But someone else made the fix, I was just checking it in for him....

The slightly updated version of the function, which allows for this ZERO case and also the cleared out state where multiple characters are returned (which still means that things are cleared out) is:

private static void ClearKeyboardBuffer(uint vk, uint sc, IntPtr hkl) {
    StringBuilder sb = new StringBuilder(10);
    do {
        rc = ToUnicodeEx(vk, sc, lpKeyStateNull, sb, sb.Capacity, 0, hkl);
    } while(rc < 0);
}

The broken keyboard, as I mentioned, has been around for some time. And obviously one could create one if they wanted to that was just as broken, which makes this a good fix to put in....

 

This post brought to you by , (U+002c, a.k.a. COMMA)


no comments

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