Zhro
Zhro

Reputation: 2614

How to determine if a numpad is present and how to obtain the scan code for the numpad enter key?

I would like to add certain behavior to my program that binds a function to the numpad enter key, if it is present, or bind an alternate key if it is not.

According to Microsoft:

The scan code is the value that the keyboard hardware generates when the user presses a key. It is a device-dependent value that identifies the key pressed, as opposed to the character represented by the key. An application typically ignores scan codes. Instead, it uses the device-independent virtual-key codes to interpret keystroke messages.

(source)

I know that on my keyboard it is 0x9C (156), but this is not guaranteed to hold true for all keyboards.

I can't use MapVirtualKey() with VK_RETURN and MAPVK_VK_TO_VSC as this always returns the scan code for the primary return key in the center of the keyboard.

How can I obtain this information without any intervention on the part of the user?

My language is C/C++ and this is for Win32 only.

Upvotes: 0

Views: 1981

Answers (4)

DJm00n
DJm00n

Reputation: 1441

As an addition to @Lexikos great answer:

The scan code is the value that the keyboard hardware generates when the user presses a key. It is a device-dependent value that identifies the key pressed, as opposed to the character represented by the key.

This was true in encient days. At least since Windows NT system uses PS/2 Scan Code Set 1 for all keyboard APIs. With some bugs that are specifically supported for backwards compatibility (for example NumLock and Pause scan codes are swapped. They are special.).

Under all Microsoft operating systems, all keyboards actually transmit Scan Code Set 2 values down the wire from the keyboard to the keyboard port. These values are translated to Scan Code Set 1 by the i8042 port chip. The rest of the operating system, and all applications that handle scan codes expect the values to be from Scan Code Set 1. Scan Code Set 3 is not used or required for operation of Microsoft operating systems. (Keyboard Scan Code Specification Revision 1.3a — March 16, 2000)

Because of this some API docs are reffering to scan codes as to virtual scan codes.

Modern USB or Bluetooth keyboard are using HID protocol with its HID Usage IDs to report key presses (see 10 Keyboard/Keypad Page (0x07) in HID Usage Tables spec for a list of possible keyboard key Usage IDs).

These HID Usages get converted to PS/2 Scan Code Set 1 by kbdclass driver (HID client mapper driver for keyboards) via call to HidP_TranslateUsagesToI8042ScanCodes API. It works according to published spec. So we actually have a published scan code list that is used in Windows. If you're interested in history behind this scan code mess - there is a good page.

There is no way to detect if keypad Enter button is present on particular keyboard hardware.

Upvotes: 1

Lexikos
Lexikos

Reputation: 1067

For Numpad Enter to be recognized as either kind of Enter, the keyboard hardware must send a scan code that maps to VK_RETURN within the current keyboard layout. Keyboard layout is determined by system settings and the window which is receiving keyboard input (or the user), not by the physical keyboard. It is quite possible that the virtual keyboard layout does not match the physical keyboard (i.e. the labels on the keys don't match their functions).

There are two strategies for allowing different physical keyboard layouts to function correctly:

  1. Change the labels visible on the keys but keep the scan codes in the same physical positions. For the function of each key to match its label, the user must choose, install or create the correct keyboard layout in software.
  2. Physically move keys, or assign pre-established scan codes to different physical positions. The OS doesn't know or care where any key is physically; it just maps scan codes to virtual keycodes based on the current keyboard layout.

Both Enter and Numpad Enter are mapped to VK_RETURN; there is no virtual key code reserved for Numpad Enter, so no way for it to have different scan codes on different keyboard layouts. With strategy #1, any key can be turned into Enter, but not specifically Numpad Enter. With strategy #2, Numpad Enter still has the same scan code as usual.

At the hardware level, Enter sends 0x1C while Numpad Enter sends 0xE0 0x1C (source: my own observations and a document by Andries Brouwer). Windows has different ways of reporting this: with bit 24 of WM_KEYDOWN's lParam, the LLKHF_EXTENDED flag for low level keyboard hooks, the RI_KEY_E0 flag for Raw Input, and possibly more.

In short, it is safe to assume that Numpad Enter is 0x1C plus the extended-key flag, since in any other case, it is impossible to identify.

I know that on my keyboard it is 0x9C (156)

I assume that you received this value from DirectInput, which defines an enum constant DIK_NUMPADENTER with value 0x9C. This value is not a scan code.

Upvotes: 1

catnip
catnip

Reputation: 25388

Anders makes a good point - I don't know of a way to tell if that key is present on (one of the) keyboard (s) present on any particular system. Also, don't forget about the Onscreen Keyboard and touch devices in general.

Why not simply bind your function to both keys regardless? Do you have a good reason not to do this?

Upvotes: 0

Anders
Anders

Reputation: 101746

The scan code depends on the hardware, it might not be the same on a different system. There can be more than one scan code that maps to a virtual key. Virtual keys are supposed to be somewhat generic and not tied to the hardware.

You can tell the difference in WM_KEYDOWN and WM_KEYUP; WPARAM is VK_RETURN and bit 24 is set in LPARAM when the Enter key on the numpad is used:

Indicates whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.

GetKeyboardType can tell you some information about "the keyboard" but since there can be more than one keyboard connected these days you would have to go deeper to find out if there are any keyboards that have the properties you are looking for. Perhaps the SetupAPI knows.

Upvotes: 1

Related Questions