Discussion:
Detect modifier keys from VBA?
(too old to reply)
automandc
2007-08-10 01:16:00 UTC
Permalink
I want to control the behavior of a macro based on whether a modifier like
"Ctrl" or "Alt" is held down when the macro is run. I know you can detect
the state of CapsLock and NumLock, but is there any way to detect the current
state of the other keys on the keyboard? (Note, I am not using a form).

Ideally, I'd like this to work from a toolbar button -- i.e., clicking the
button runs the macro one way, clicking the button while holding shift or
ctrl runs it a different way.
Helmut Weber
2007-08-10 02:18:37 UTC
Permalink
Hi automandc,

I did it once, but can't find it anymore.
You need API-function GetKeyState()
or related functions.
--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
Helmut Weber
2007-08-10 02:35:28 UTC
Permalink
If you want to know it all,
from Thomas Gahler, MVP:

There is some german in the text,
but you'll make it.


' ---------- Start Modul1 ----------
Option Explicit


'API zum feststellen des Keyboard-Status deklarieren.
Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As
Integer


'Konstanten zum feststellen des Keyboard-Status definieren.
Public Const VK_LBUTTON As Integer = &H1
Public Const VK_RBUTTON As Integer = &H2
Public Const VK_CANCEL As Integer = &H3
Public Const VK_MBUTTON As Integer = &H4 ' NOT
contiguous
with L RBUTTON


Public Const VK_BACK As Integer = &H8
Public Const VK_TAB As Integer = &H9


Public Const VK_CLEAR As Integer = &HC
Public Const VK_RETURN As Integer = &HD


Public Const VK_SHIFT As Integer = &H10
Public Const VK_CONTROL As Integer = &H11
Public Const VK_MENU As Integer = &H12
Public Const VK_PAUSE As Integer = &H13
Public Const VK_CAPITAL As Integer = &H14


Public Const VK_ESCAPE As Integer = &H1B


Public Const VK_SPACE As Integer = &H20
Public Const VK_PRIOR As Integer = &H21
Public Const VK_NEXT As Integer = &H22
Public Const VK_END As Integer = &H23
Public Const VK_HOME As Integer = &H24
Public Const VK_LEFT As Integer = &H25
Public Const VK_UP As Integer = &H26
Public Const VK_RIGHT As Integer = &H27
Public Const VK_DOWN As Integer = &H28
Public Const VK_SELECT As Integer = &H29
Public Const VK_PRINT As Integer = &H2A
Public Const VK_EXECUTE As Integer = &H2B
Public Const VK_SNAPSHOT As Integer = &H2C
Public Const VK_INSERT As Integer = &H2D
Public Const VK_DELETE As Integer = &H2E
Public Const VK_HELP As Integer = &H2F


' VK_A thru VK_Z are the same as their ASCII equivalents: 'A' thru 'Z'
' VK_0 thru VK_9 are the same as their ASCII equivalents: '0' thru '9'


Public Const VK_NUMPAD0 As Integer = &H60
Public Const VK_NUMPAD1 As Integer = &H61
Public Const VK_NUMPAD2 As Integer = &H62
Public Const VK_NUMPAD3 As Integer = &H63
Public Const VK_NUMPAD4 As Integer = &H64
Public Const VK_NUMPAD5 As Integer = &H65
Public Const VK_NUMPAD6 As Integer = &H66
Public Const VK_NUMPAD7 As Integer = &H67
Public Const VK_NUMPAD8 As Integer = &H68
Public Const VK_NUMPAD9 As Integer = &H69
Public Const VK_MULTIPLY As Integer = &H6A
Public Const VK_ADD As Integer = &H6B
Public Const VK_SEPARATOR As Integer = &H6C
Public Const VK_SUBTRACT As Integer = &H6D
Public Const VK_DECIMAL As Integer = &H6E
Public Const VK_DIVIDE As Integer = &H6F
Public Const VK_F1 As Integer = &H70
Public Const VK_F2 As Integer = &H71
Public Const VK_F3 As Integer = &H72
Public Const VK_F4 As Integer = &H73
Public Const VK_F5 As Integer = &H74
Public Const VK_F6 As Integer = &H75
Public Const VK_F7 As Integer = &H76
Public Const VK_F8 As Integer = &H77
Public Const VK_F9 As Integer = &H78
Public Const VK_F10 As Integer = &H79
Public Const VK_F11 As Integer = &H7A
Public Const VK_F12 As Integer = &H7B
Public Const VK_F13 As Integer = &H7C
Public Const VK_F14 As Integer = &H7D
Public Const VK_F15 As Integer = &H7E
Public Const VK_F16 As Integer = &H7F
Public Const VK_F17 As Integer = &H80
Public Const VK_F18 As Integer = &H81
Public Const VK_F19 As Integer = &H82
Public Const VK_F20 As Integer = &H83
Public Const VK_F21 As Integer = &H84
Public Const VK_F22 As Integer = &H85
Public Const VK_F23 As Integer = &H86
Public Const VK_F24 As Integer = &H87


Public Const VK_NUMLOCK As Integer = &H90
Public Const VK_SCROLL As Integer = &H91


'
' VK_L VK_R - left and right Alt, Ctrl and Shift virtual keys.
' Used only as parameters to GetAsyncKeyState() and GetKeyState().
' No other API or message will distinguish left and right keys in
this
way.
' /
Public Const VK_LSHIFT As Integer = &HA0
Public Const VK_RSHIFT As Integer = &HA1
Public Const VK_LCONTROL As Integer = &HA2
Public Const VK_RCONTROL As Integer = &HA3
Public Const VK_LMENU As Integer = &HA4
Public Const VK_RMENU As Integer = &HA5


Public Const VK_ATTN As Integer = &HF6
Public Const VK_CRSEL As Integer = &HF7
Public Const VK_EXSEL As Integer = &HF8
Public Const VK_EREOF As Integer = &HF9
Public Const VK_PLAY As Integer = &HFA
Public Const VK_ZOOM As Integer = &HFB
Public Const VK_NONAME As Integer = &HFC
Public Const VK_PA1 As Integer = &HFD
Public Const VK_OEM_CLEAR As Integer = &HFE


Public Function funcIsTasteGedrückt(iTastenCode As Integer) As Boolean
If Abs(GetKeyState(iTastenCode) < 0) Then
funcIsTasteGedrückt = True
End If
End Function
' ---------- Ende Modul1 ----------


Hier das Demobeispiel, die Funktion liefert eine Boolean-Wert zurück

Sub Demo()
MsgBox funcIsTasteGedrückt(VK_SHIFT)
End Sub

HTH
Peter T
2007-08-10 11:42:15 UTC
Permalink
Along the lines Helmut suggests -

Public Declare Function GetAsyncKeyState _
Lib "user32" (ByVal vKey As Long) As Integer

Function IsKeyDown(key As Long) As Boolean
If GetAsyncKeyState(key) Then
If GetAsyncKeyState(key) Then
IsKeyDown = True
End If
End If
End Function

Sub test()
Dim bShift As Boolean
Dim bCtrl As Boolean

' hold shift or ctrl or both or neither and run
bShift = IsKeyDown(vbKeyShift)
bCtrl = IsKeyDown(vbKeyControl)

Debug.Print bShift, bCtrl

'If bShift And bCtrl Then
' MsgBox "don't press Shift & Ctrl together"
'ElseIf bShift Then
' MsgBox "Shift code"
'ElseIf bCtrl Then
' MsgBox "Ctrl code"
'Else
' MsgBox "other code"
'End If

End Sub

It might seem odd to test key twice but I've found doing that can't prevent
detecting a false positive, which for some reason can occur (eg,
occasionally first time key is tested just after releasing the key).

Regards,
Peter T
Post by automandc
I want to control the behavior of a macro based on whether a modifier like
"Ctrl" or "Alt" is held down when the macro is run. I know you can detect
the state of CapsLock and NumLock, but is there any way to detect the current
state of the other keys on the keyboard? (Note, I am not using a form).
Ideally, I'd like this to work from a toolbar button -- i.e., clicking the
button runs the macro one way, clicking the button while holding shift or
ctrl runs it a different way.
automandc
2007-08-10 19:48:00 UTC
Permalink
Thanks to both you and Helmut -- that worked perfectly!
Post by Peter T
Along the lines Helmut suggests -
Public Declare Function GetAsyncKeyState _
Lib "user32" (ByVal vKey As Long) As Integer
Function IsKeyDown(key As Long) As Boolean
If GetAsyncKeyState(key) Then
If GetAsyncKeyState(key) Then
IsKeyDown = True
End If
End If
End Function
Sub test()
Dim bShift As Boolean
Dim bCtrl As Boolean
' hold shift or ctrl or both or neither and run
bShift = IsKeyDown(vbKeyShift)
bCtrl = IsKeyDown(vbKeyControl)
Debug.Print bShift, bCtrl
'If bShift And bCtrl Then
' MsgBox "don't press Shift & Ctrl together"
'ElseIf bShift Then
' MsgBox "Shift code"
'ElseIf bCtrl Then
' MsgBox "Ctrl code"
'Else
' MsgBox "other code"
'End If
End Sub
It might seem odd to test key twice but I've found doing that can't prevent
detecting a false positive, which for some reason can occur (eg,
occasionally first time key is tested just after releasing the key).
Regards,
Peter T
Post by automandc
I want to control the behavior of a macro based on whether a modifier like
"Ctrl" or "Alt" is held down when the macro is run. I know you can detect
the state of CapsLock and NumLock, but is there any way to detect the
current
Post by automandc
state of the other keys on the keyboard? (Note, I am not using a form).
Ideally, I'd like this to work from a toolbar button -- i.e., clicking the
button runs the macro one way, clicking the button while holding shift or
ctrl runs it a different way.
Loading...