What is the VK for the semicolon?

by Michael S. Kaplan, published on 2005/12/01 00:01 -08:00, original URI: http://blogs.msdn.com/michkap/archive/2005/12/01/498775.aspx

It was just yesterday when someone sent the following question to various people inside of Microsoft:

We have a small problem regarding the correct VK representation of the semicolon. Under the standard US KB the virtual key is VK_OEM_1 (0xba) but this may not be true for other languages. I suggested to simply use the ASCII char key (0x3b) for semicolon for all other case but I’m not that sure about it.

The use is very straightforward.

We handle the WM_KEYDOWN message in some point and want to catch the semicolon key press.

Simply check the message wParam (wParam == ‘;’) doesn’t work.

The reason is that the char ‘;’ is not sent within the wParam and instead what is sent is VK_OEM_1.

This is fine, but according the MSDN the code VK_OEM_1 works only for US standard KB.

So what is going to happen under different keyboards layout and/or other languages settings?

Which VK should we use to catch the semicolon?  

Since I found no other choices, I simply trap for both VK_OEM_1 and the char ‘;’ but that might be an incomplete solution.

Do you have any idea what the correct code might be?

The answer of course is that there is no one code for the semicolon that spans all of the keyboard layouts.

But I do not blame people for the misunderstanding, at all.

It was over a year ago that I listed out Some Keyboarding Terms, in particular:

  • Scan code -- The numeric value given to each physical key on a keyboard; the scan code is a hardware-dependent number that identifies the key. Scan codes have a fixed position on the physical keyboard, irregardless of the keyboard layout chosen by the user.
  • Virtual Key -- Also called the VK, the code that is given by the Windows USER subsystem to represent a keystroke. It is mapped from a scan code by using the keyboard layout definition and is thus entirely dependent on the user's chosen layout. The reason for this is the [unfortunate, IMHO] choice to have e.g. VK_A to be used for the 'A' key, which meant that on keyboards that put 'A' in a different position the VK would have to be moved.

    If you look at the red text in the VK definition, it hints at the problem that causes the confusion.

    I mean, since there is a VK_A that represents the letter A, why wouldn't we expect there to be a VK_SEMICIOLON to represent the semicolon, right?

    Of course, there are lots of problems with such a model. For example, that semicolon key is also a colon key. Who would win the contest?

    And since not every keyboard pairs up the same characters in the various shift states, how would you find the character that was not used for the name?

    The real problem is that when a WNDPROC receives a WM_KEYDOWN message with the virtual key VK_OEM1, it has not received a semicolon. At all. It has received notification that a parrticular key was pressed, and nothing else. When it receives a VK_A, there is no difference; it is a notification that a key has been pressed. Now the keyboard layout has been asked what is the virtual key, but it has not yet been asked what is the character (and it quite possibly may never be asked).

    If that WNDPROC passes the message to the DefWindowProcIf you call the TranslateMessage function, then the keyboard will be asked what is the character based on all of the information about the current keyboard buffer and the shift state, and a subsequent WM_CHAR message will be sent, which will contain the ";" or the "A" or whatever.

    The fact that the values for VK_A through VK_Z are identical to the code points for the letters A - Z is an unfortunate accident since it raises such unrealistic expectations for other characters....

    In the end, we are left with two possible options to solve the original problem:


    This post brought to you by ";" (U+003b, a.k.a. SEMICOLON)

  • # orcmid on Thursday, December 01, 2005 10:36 AM:

    Wow, two keepers in a row today. (I actually, I keep most of them, but this one is a gem.)

    I need to explain this to people at some point, after using it correctly myself, and this is lovely. It is interesting how we get screwed up adding too much semantics to what there is. Distinguishing the key from the character we think the user is intending is powerful stuff.

    I ran into the user-confusion side of this when messing with language choices without having the right keyboard and not doing the settings right. It was a mess until I gave up and set everything back to my case. I'll have to try again some day.

    # Mike Dimmick on Thursday, December 01, 2005 2:35 PM:

    *scratches head* I'm sure it's the call to TranslateMessage() that causes the WM_CHAR message to be generated. This is part of the boilerplate message loop that every Windows application includes and it seems few Windows developers really understand!

    # Michael S. Kaplan on Thursday, December 01, 2005 3:30 PM:

    Yes, you are correct, it is the TranslateMessage call that does the work here (among other things that the function does)....

    referenced by

    2006/07/13 IME + .NET = Input Madness Editor?

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