Convert a Character Code to a string describing the Keyboard Keys which must be pressed

Character Code Sample

Different keyboard layouts use different virtual key codes and shift combinations to represent character codes. This tip demonstrates how to convert a key code into the equivalent virtual key code and shift state, as well as how to provide the name of a virtual key on the keyboard.

There are two stages in converting a character into the keyboard equivalent. The first stage is to obtain the Keyboard Scan Code for the character, using the API call VkKeyScan. This provides the key's virtual key code and the shift state. Once that has been done, the virtual key code can be converted to the name of the key using the MapVirtualKey and GetKeyNameText functions.

Converting a Character to the Virtual Key and Shift State

The code below shows how this is achieved. First, the GetVersion function is called to determine whether the system is NT and has Unicode support or not. This is indicated by the high-bit of the return value being set. Then a suitable value is prepared for the VkKeyScan call. For Unicode systems this is an Integer value whereas ANSI systems use Byte values. Then the result of the call is an integer where the low-byte is the virtual key code and the high-byte is the shift state, made up from a ORed combination of the constants in VB's ShiftConstant values:

Private Declare Function GetVersion Lib "kernel32" () As Long
Private Declare Function VkKeyScan Lib "user32" Alias "VkKeyScanA" ( _
   ByVal cChar As Byte) As Integer
Private Declare Function VkKeyScanW Lib "user32" ( _
   ByVal cChar As Integer) As Integer


Dim bNt As Boolean
Dim iKeyCode As Integer
Dim b() As Byte
Dim iKey as integer
Dim vKey as KeyCodeConstants
Dim iShift As ShiftConstants

   ' Determine if we have Unicode support or not:
   bNt = ((GetVersion() And &H80000000) = 0)
   ' Get the keyboard scan code for the character:
   If (bNt) Then
      b = sChar
      CopyMemory iKey, b(0), 2
      iKeyCode = VkKeyScanW(iKey)
      b = StrConv(sChar, vbFromUnicode)
      iKeyCode = VkKeyScan(b(0))
   End If
   ' Split into shift and key portions:
   iShift = (iKeyCode And &HFF00&) \ &H100&
   vKey = iKeyCode And &HFF&

Converting the Virtual Key Code to a Keyboard Name

To convert the key code, first the Unicode or ANSI version of MapVirtualKey is called. This returns a scan code which can be used to obtain the name of the key from the GetKeyNameText function. This function expects the scan code in a long value shifted to the high word and a pointer to an buffer which will hold the keyboard text name. In the Unicode world this needs to be a byte array with two bytes for each character in the buffer whereas in ANSI it is a pre-allocated VB string. The code to achieve this is shown below:

Dim lScanCode As Long
Dim sBuf As String
Dim lSize As Long
Dim b() As Byte

   ' Translate the virtual-key code into a scan code.
   If (bNt) Then
      lScanCode = MapVirtualKeyW(vKey, 0)
      lScanCode = MapVirtualKey(vKey, 0)
   End If
   ' GetKeyNameText retrieves the name of a key (the scan code
   ' must be in bits 16-23):
   lScanCode = lScanCode * &H10000
   If (bNt) Then
      ReDim b(0 To 512) As Byte
      lSize = GetKeyNameTextW(lScanCode, VarPtr(b(0)), 256)
      If (lSize > 0) Then
         sBuf = b
         sKeyName = Left$(sBuf, lSize)
      End If
      sBuf = Space$(256)
      lSize = GetKeyNameText(lScanCode, sBuf, 256)
      sKeyName & Left$(sBuf, lSize)
   End If

Using It

The sample application in the download wraps this function into a simple function within a module called GetKeyboardString. This takes a character as a VB string and returns a string with the keystroke, as well as populating two optional parameters vKey and iShift with the virtual key and shift flags.