This page has been replaced. Click here to go to the new page: KeyTest.aspx.

Pearson Software Consulting Services

    Testing The State Of The SHIFT, CTRL, And ALT Keys

         You may wish to provide extended or alternative functionality of a procedure depending on whether the user has pressed SHIFT, CTRL, or ALT. For example, you might have a procedure that normally processes one range, but you want the procedure to process all ranges if the user presses the SHIFT key. As an existing example, you will get a slightly modified Edit menu if you click the Edit menu with the SHIFT key down.  Similarly, range selection (selecting cells and ranges) behaves differently depending on the state of the CTRL and SHIFT keys.

You test the state (up or down) of a key using the GetKeyState Windows API function.   The GetKeyState function is documented on-line at MSDN.  The result of GetKeyState is evaluated with a bit-wise AND with the value KEY_MASK  (hex &HFF80 decimal -128) to determine the state of the key.

The following are the declarations for the 3 functions:

Public Function IsShiftKeyDown( _ 
    Optional LeftOrRightKey As Long = LeftKeyOrRightKey)
Public Function IsControlKeyDown( _ 
    Optional LeftOrRightKey As Long = LeftKeyOrRightKey) As Boolean
Public Function IsAltKeyDown( _
    Optional LeftOrRightKey As Long = LeftKeyOrRightKey) As Boolean

The functions are nearly identical, differing only the the key code being tested.

The code on this page, and in a downloadable bas module file,  tests for the state of the SHIFT, CTRL, and ALT keys. You can specify whether to test only the Left key, only the Right key, either the Left OR Right keys, or BOTH the Left AND Right keys. Unless you specify otherwise, the procedures' default test  is to check for either the Left or Right key, making no distinction between Left and Right.

Which keys to test (Left, Right, Either, Both) is specified in the LeftKeyOrRightKey parameter to each key-test function. The values for this parameter are declared as Constants in the code module as follows:

Public Const BothLeftAndRightKeys = 0
Public Const LeftKey = 1
Public Const RightKey = 2
Public Const LeftKeyOrRightKey = 3

 You'll note that the value BothLeftAndRightKeys is the bit-wise AND of LeftKey and RightKey, and that the value LeftKeyOrRightKey is the bit-wise OR of LeftKey and RightKey. If the LeftKeyOrRightKey parameter is omitted, the test is for either the left or right key -- the code does not distinguish between the left or right key. 

The complete VBA code module is shown below. You may download the module file here.

Option Explicit
Option Compare Text
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' modKeyState
' By Chip Pearson, www.cpearson.com, chip@cpearson.com
' This module contains functions for testing the state of the SHIFT, ALT, and CTRL
' keys.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''


''''''''''''''''''''''''''''''''''''''''''''''''''''
' Declaration of GetKeyState API function. This
' tests the state of a specified key.
''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Declare Function GetKeyState Lib "user32" ( _
    ByVal nVirtKey As Long) As Integer
    
''''''''''''''''''''''''''''''''''''''''''
' This constant is used in a bit-wise AND
' operation with the result of GetKeyState
' to determine if the specified key is
' down.
''''''''''''''''''''''''''''''''''''''''''
Private Const KEY_MASK As Integer = &HFF80 ' decimal -128

'''''''''''''''''''''''''''''''''''''''''
' KEY CONSTANTS. Values taken
' from VC++ 6.0 WinUser.h file.
'''''''''''''''''''''''''''''''''''''''''
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
'''''''''''''''''''''''''''''''''''''''''
' The following four constants simply
' provide other names, CTRL and ALT,
' for CONTROL and MENU. "CTRL" and
' "ALT" are more familiar than
' "CONTROL" and "MENU". These constants
' provide no additional functionality.
' They simply provide more familiar
' names.
'''''''''''''''''''''''''''''''''''''''''
Private Const VK_LALT = VK_LMENU
Private Const VK_RALT = VK_RMENU
Private Const VK_LCTRL = VK_LCONTROL
Private Const VK_RCTRL = VK_RCONTROL

 ''''''''''''''''''''''''''''''''''''''''''''
' The following constants are used to specify,
' when testing CTRL, ALT, or SHIFT, whether
' the Left key, the Right key, either the
' Left OR Right key, or BOTH the Left AND 
' Right keys are down.
'
' By default, the key-test procedures make
' no distinction between the Left and Right
' keys and will return TRUE if either the
' Left or Right (or both) key is down.
''''''''''''''''''''''''''''''''''''''''''''
Public Const BothLeftAndRightKeys = 0   ' Note: Bit-wise AND of LeftKey and RightKey
Public Const LeftKey = 1
Public Const RightKey = 2
Public Const LeftKeyOrRightKey = 3      ' Note: Bit-wise OR of LeftKey and RightKey


Public Function IsShiftKeyDown(Optional LeftOrRightKey As Long = LeftKeyOrRightKey)
''''''''''''''''''''''''''''''''''''''''''''''''
' IsShiftKeyDown
' Returns TRUE or FALSE indicating whether the
' SHIFT key is down.
'
' If LeftOrRightKey is omitted or LeftKeyOrRightKey,
' the function return TRUE if either the left or the
' right SHIFT key is down. If LeftKeyOrRightKey is
' LeftKey, then only the Left SHIFT key is tested.
' If LeftKeyOrRightKey is RightKey, only the Right
' SHIFT key is tested. If LeftOrRightKey is
' BothLeftAndRightKeys, the codes tests whether
' both the Left and Right keys are down. The default
' is to test for either Left or Right, making no
' distiction between Left and Right.
''''''''''''''''''''''''''''''''''''''''''''''''
    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
''''''''''''''''''''''''''''''''''''''''''''''''
' IsControlKeyDown
' Returns TRUE or FALSE indicating whether the
' CTRL key is down.
'
' If LeftOrRightKey is omitted or LeftKeyOrRightKey,
' the function return TRUE if either the left or the
' right CTRL key is down. If LeftKeyOrRightKey is
' LeftKey, then only the Left CTRL key is tested.
' If LeftKeyOrRightKey is RightKey, only the Right
' CTRL key is tested. If LeftOrRightKey is
' BothLeftAndRightKeys, the codes tests whether
' both the Left and Right keys are down. The default
' is to test for either Left or Right, making no
' distiction between Left and Right.
''''''''''''''''''''''''''''''''''''''''''''''''
    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
''''''''''''''''''''''''''''''''''''''''''''''''
' IsAltKeyDown
' Returns TRUE or FALSE indicating whether the
' ALT key is down.
'
' If LeftOrRightKey is omitted or LeftKeyOrRightKey,
' the function return TRUE if either the left or the
' right ALT key is down. If LeftKeyOrRightKey is
' LeftKey, then only the Left ALT key is tested.
' If LeftKeyOrRightKey is RightKey, only the Right
' ALT key is tested. If LeftOrRightKey is
' BothLeftAndRightKeys, the codes tests whether
' both the Left and Right keys are down. The default
' is to test for either Left or Right, making no
' distiction between Left and Right.
''''''''''''''''''''''''''''''''''''''''''''''''
    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


Sub Test()
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Test
' This is a procedure to test and demonstrate the Key-State
' functions above. Since you can't run a macro in the VBA
' Editor if the SHIFT, ALT, or CTRL key is down, this procedure
' uses OnTime to execute the ProcTest test procedure. OnTime
' will call ProcTest two seconds after running this Test
' procedure. Immediately after executing Test, press the
' key(s) (Left/Right SHIFT, ALT, or CTRL) you want to test
' for. The procedure called by OnTime, ProcTest, displays the
' status of the Left/Right SHIFT, ALT, and CTRL keys.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Application.OnTime Now + TimeSerial(0, 0, 2), "ProcTest", , True
End Sub


Sub ProcTest()
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' ProcTest
' This procedure simply displays the status of the Left adn Right
' SHIFT, ALT, and CTRL keys.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
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

 

 

     
     

 

Created By Chip Pearson and Pearson Software Consulting, LLC 
This Page:                Updated: November 06, 2013     
MAIN PAGE    About This Site    Consulting    Downloads  
Page Index     Search    Topic Index    What's New   
Links   Legalese And Disclaimers
chip@cpearson.com

Copyright 1997-2007  Charles H. Pearson