Testing Key States
This page describes VBA code to test the state of the SHIFT, CTRL, and ALT keys.
You may wish to provide varying behavior of a procedure depending on the state of the
SHIFT,
ALT, or
CTRL keys. For example, you could design a procedure to omit
confirmation dialogs if the
SHIFT key is down when the procedure is run. Excel itself does things
similar to this. For example, the items on the
EDIT menu are different if you have
the
SHIFT key down as you access the menu. Using some simple Windows API functions, you can
do similar things.
VBA does not give you access to the keyboard state. Therefore, you must use the GetKeyState Windows API
function. This function returns the state (pressed or not pressed) of a specified key. The code in this article provides three
functions written in VBA that you can use in your own code:
- IsShiftKeyDown Indicates whether the left, right, either, or both SHIFT keys
are pressed.
- IsControlKeyDown Indicates whether the left, right, either, or both CTRL keys
are pressed.
- IsAltKeyDown Indicates whether the left, right, either, or both ALT keys
are pressed.
Each of these procedures returns
True or
False indicating the state of the key(s) --
True if the key is pressed or
False if the key is not pressed.
The function declarations are as follows:
Public Function IsShiftKeyDown(Optional LeftOrRightKey As Long = LeftKeyOrRightKey) As Boolean
Public Function IsControlKeyDown(Optional LeftOrRightKey As Long = LeftKeyOrRightKey) As Boolean
Public Function IsAltKeyDown(Optional LeftOrRightKey As Long = LeftKeyOrRightKey) As Boolean
Each of these procedures takes an optional parameters indicating whether the left, right, either or both keys are to be tested. If
this parameter is omitted, the code tests for either right or left or both, make no distinction whether the key is the left or right
key. The values allowed for this parameter are:
Public Const BothLeftAndRightKeys = 0 ' BOTH left and right together
Public Const LeftKey = 1 ' LEFT key only
Public Const RightKey = 2 ' RIGHT key only
Public Const LeftKeyOrRightKey = 3 ' EITHER left or right or BOTH
While the code in this article test only the SHIFT, CTRL, and
ALT keys, it can be adapted to test any key. To do this you would supply the appropriate
key code to the GetKeyState API function. (See
the MSDN article for GetKeyState for more information.)
There is nothing specific to Excel or indeed VBA in this code. You can use this code in any application that supports VBA or in
VB6 code.
The complete code is shown below. The code is also available as a downloadable bas module file.
Option Explicit
Option Compare Text
Private Declare Function GetKeyState Lib "user32" ( _
ByVal nVirtKey As Long) As Integer
Private Const KEY_MASK As Integer = &HFF80 ' decimal -128
Private Const VK_LSHIFT = &HA0
Private Const VK_RSHIFT = &HA1
Private Const VK_LCONTROL = &HA2
Private Const VK_RCONTROL = &HA3
Private Const VK_LMENU = &HA4
Private Const VK_RMENU = &HA5
Private Const VK_LALT = VK_LMENU
Private Const VK_RALT = VK_RMENU
Private Const VK_LCTRL = VK_LCONTROL
Private Const VK_RCTRL = VK_RCONTROL
Public Const BothLeftAndRightKeys = 0
Public Const LeftKey = 1
Public Const RightKey = 2
Public Const LeftKeyOrRightKey = 3
Public Function IsShiftKeyDown(Optional LeftOrRightKey As Long = LeftKeyOrRightKey) As Boolean
Dim Res As Long
Select Case LeftOrRightKey
Case LeftKey
Res = GetKeyState(VK_LSHIFT) And KEY_MASK
Case RightKey
Res = GetKeyState(VK_RSHIFT) And KEY_MASK
Case BothLeftAndRightKeys
Res = (GetKeyState(VK_LSHIFT) And GetKeyState(VK_RSHIFT) And KEY_MASK)
Case Else
Res = GetKeyState(vbKeyShift) And KEY_MASK
End Select
IsShiftKeyDown = CBool(Res)
End Function
Public Function IsControlKeyDown(Optional LeftOrRightKey As Long = LeftKeyOrRightKey) As Boolean
Dim Res As Long
Select Case LeftOrRightKey
Case LeftKey
Res = GetKeyState(VK_LCTRL) And KEY_MASK
Case RightKey
Res = GetKeyState(VK_RCTRL) And KEY_MASK
Case BothLeftAndRightKeys
Res = (GetKeyState(VK_LCTRL) And GetKeyState(VK_RCTRL) And KEY_MASK)
Case Else
Res = GetKeyState(vbKeyControl) And KEY_MASK
End Select
IsControlKeyDown = CBool(Res)
End Function
Public Function IsAltKeyDown(Optional LeftOrRightKey As Long = LeftKeyOrRightKey) As Boolean
Dim Res As Long
Select Case LeftOrRightKey
Case LeftKey
Res = GetKeyState(VK_LALT) And KEY_MASK
Case RightKey
Res = GetKeyState(VK_RALT) And KEY_MASK
Case BothLeftAndRightKeys
Res = (GetKeyState(VK_LALT) And GetKeyState(VK_RALT) And KEY_MASK)
Case Else
Res = GetKeyState(vbKeyMenu) And KEY_MASK
End Select
IsAltKeyDown = CBool(Res)
End Function
The following are test procedures to illustrate the code. Run the procedure named Test and then press
the keys that you want to test. Test calls ProcTest via OnTime
to allow you to press the appropriate keys. The results are displayed in the Debug window of the VBA Editor.
Sub Test()
Application.OnTime Now + TimeSerial(0, 0, 2), "ProcTest", , True
End Sub
Sub ProcTest()
Debug.Print "SHIFT KEY: ", "LEFT: " & CStr(IsShiftKeyDown(LeftKey)), _
"RIGHT: " & CStr(IsShiftKeyDown(RightKey)), _
"EITHER: " & CStr(IsShiftKeyDown(LeftKeyOrRightKey)), _
"BOTH: " & CStr(IsShiftKeyDown(BothLeftAndRightKeys))
Debug.Print "ALT KEY: ", "LEFT: " & CStr(IsAltKeyDown(LeftKey)), _
"RIGHT: " & CStr(IsAltKeyDown(RightKey)), _
"EITHER: " & CStr(IsAltKeyDown(LeftKeyOrRightKey)), _
"BOTH: " & CStr(IsAltKeyDown(BothLeftAndRightKeys))
Debug.Print "CTRL KEY: ", "LEFT: " & CStr(IsControlKeyDown(LeftKey)), _
"RIGHT: " & CStr(IsControlKeyDown(RightKey)), _
"EITHER: " & CStr(IsControlKeyDown(LeftKeyOrRightKey)), _
"BOTH: " & CStr(IsControlKeyDown(BothLeftAndRightKeys))
End Sub
This page last updated: 5-October-2007