Introduction | Example | Tutorial | Applications
Introduction - GetAsyncKeyState VBA
This tutorial shows you how to pause your macro until a key is pressed by calling the GetAsyncKeyState function in VBA. By doing this, you’re able to detect key strokes so you can trigger an action when a key is pressed.
I know this doesn’t literally pause your macro while you wait for a key to be pressed, but in essence that’s the functionality you’re recreating. You can use this feature to exit a userform when a key is pressed or to control the logic of your macro using key presses.
Example - GetAsyncKeyState VBA
Display a message when the F9 key is pressed
#If VBA7 Then
'declare virtual key event listener
Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Long) As Integer
#Else
'declare virtual key event listener
Private Declare Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Long) As Integer
#End If
Private Const VK_F9 = &H78
Sub WaitUntilF9Key()
Do Until GetAsyncKeyState(VK_F9)
DoEvents
Loop
MsgBox "Hello World"
End Sub
Make powerful macros with our free VBA Developer Kit Tutorials like this can be complicated. That’s why we created our free VBA Developer Kit and our Big Book of Excel VBA Macros to supplement this tutorial. Grab them below and you’ll be writing powerful macros in no time.
Tutorial - GetAsyncKeyState VBA
Simple Explanation
There you have it. This macro stays in a loop until the user presses F9. The F9 key is a virtual key constant I declared using the hexadecimal value 78. For a full list of the virtual key constants in VBA format, jump here.
Because the DoEvents method is invoked, the user is able to contine doing whatever he/she wants in Excel. The user can enter data, change data, switch applications and more - just like they normally would. But, the moment they hit the F9 key, the loop ends and the user is presented with a message box.
This is exactly what I do on the Recording screen of my Mouse To Macro Excel Add-in.
If you’re trying to figure out what all the junk about VBA7 at the top of the macro is, it’s just so the macro will work on both 32-bit and 64-bit machines. When you see someone use the PtrSafe keyword in VBA like I did up there, that’s usually what he/she is trying to do.
But I digress. You can make more complicated codes than this. For example, why do you have to leave the loop when a key is pressed? Can you present different information when different keys are pressed?
You better believe you can! Take a look.
More Advanced Example - GetAsyncKeyState VBA
Open notepad or speak the time, depending on which key is pressed
#If VBA7 Then
'declare virtual key event listener
Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Long) As Integer
#Else
'declare virtual key event listener
Private Declare Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Long) As Integer
#End If
Private Const VK_F9 = &H78
Private Const VK_F10 = &H79
Private Const VK_0 = &H30
Sub WaitUntilKey()
Do Until GetAsyncKeyState(VK_F9)
'exit when F9 key is pressed
DoEvents
If GetAsyncKeyState(VK_F10) Then
'if F10 key is pressed
'open notepad
Call Shell("Explorer.exe ""C:\Windows\system32\notepad.exe""", vbNormalFocus)
ElseIf GetAsyncKeyState(VK_0) Then
'if 0 key is pressed
'Speak the time
Application.Speech.Speak "The time is " & Time, True, , True
End If
Loop
End Sub
You can run this macro in the background and anytime you press the F10 key, a new notepad will open.
Likewise, if you run this macro from Excel, anytime you press the 0 key, your computer will speak and tell you what time it is.
Like before, once you hit the F9 key, the macro will end.
I gotta admit. Capturing keystrokes still makes me giddy when I see it in a macro. It’s just so flipping neat!
Full List of GetAsyncKeyState Virtual Keys
I’m sure you noticed I only declared the keys I was looking for in the previous example. That’s only because I’m lazy.
I’m going to make this easy for you by defining EVERY virtual key, including mouse clicks, you can detect with the GetAsyncKeyState function. Even better, I’m going to do it in VBA format so you can copy and paste it in your own macro. By copying and pasting this into the top of your own macro, you’ll be able to run different branches of your macro logic when different keys are pressed.
This is incredibly powerful. Without further delay, here’s the VBA code:
Virtual Keys in VBA Format
#If VBA7 Then
Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Long) As Integer
#Else
Private Declare Function GetAsyncKeyState Lib "user32" _
(ByVal vKey As Long) As Integer
#End If
'List compiled by Ryan Wells at wellsr.com
Private Const VK_LBUTTON = &H1 'Left mouse button
Private Const VK_RBUTTON = &H2 'Right mouse button
Private Const VK_CANCEL = &H3 'Control-break processing
Private Const VK_MBUTTON = &H4 'Middle mouse button (three-button mouse)
Private Const VK_BACK = &H8 'BACKSPACE key
Private Const VK_TAB = &H9 'TAB key
Private Const VK_CLEAR = &HC 'CLEAR key
Private Const VK_RETURN = &HD 'ENTER key
Private Const VK_SHIFT = &H10 'SHIFT key
Private Const VK_CONTROL = &H11 'CTRL key
Private Const VK_MENU = &H12 'ALT key
Private Const VK_PAUSE = &H13 'PAUSE key
Private Const VK_CAPITAL = &H14 'CAPS LOCK key
Private Const VK_ESCAPE = &H1B 'ESC key
Private Const VK_SPACE = &H20 'SPACEBAR
Private Const VK_PRIOR = &H21 'PAGE UP key
Private Const VK_NEXT = &H22 'PAGE DOWN key
Private Const VK_END = &H23 'END key
Private Const VK_HOME = &H24 'HOME key
Private Const VK_LEFT = &H25 'LEFT ARROW key
Private Const VK_UP = &H26 'UP ARROW key
Private Const VK_RIGHT = &H27 'RIGHT ARROW key
Private Const VK_DOWN = &H28 'DOWN ARROW key
Private Const VK_SELECT = &H29 'SELECT key
Private Const VK_PRINT = &H2A 'PRINT key
Private Const VK_EXECUTE = &H2B 'EXECUTE key
Private Const VK_SNAPSHOT = &H2C 'PRINT SCREEN key
Private Const VK_INSERT = &H2D 'INS key
Private Const VK_DELETE = &H2E 'DEL key
Private Const VK_HELP = &H2F 'HELP key
Private Const VK_0 = &H30 '0 key
Private Const VK_1 = &H31 '1 key
Private Const VK_2 = &H32 '2 key
Private Const VK_3 = &H33 '3 key
Private Const VK_4 = &H34 '4 key
Private Const VK_5 = &H35 '5 key
Private Const VK_6 = &H36 '6 key
Private Const VK_7 = &H37 '7 key
Private Const VK_8 = &H38 '8 key
Private Const VK_9 = &H39 '9 key
Private Const VK_A = &H41 'A key
Private Const VK_B = &H42 'B key
Private Const VK_C = &H43 'C key
Private Const VK_D = &H44 'D key
Private Const VK_E = &H45 'E key
Private Const VK_F = &H46 'F key
Private Const VK_G = &H47 'G key
Private Const VK_H = &H48 'H key
Private Const VK_I = &H49 'I key
Private Const VK_J = &H4A 'J key
Private Const VK_K = &H4B 'K key
Private Const VK_L = &H4C 'L key
Private Const VK_M = &H4D 'M key
Private Const VK_N = &H4E 'N key
Private Const VK_O = &H4F 'O key
Private Const VK_P = &H50 'P key
Private Const VK_Q = &H51 'Q key
Private Const VK_R = &H52 'R key
Private Const VK_S = &H53 'S key
Private Const VK_T = &H54 'T key
Private Const VK_U = &H55 'U key
Private Const VK_V = &H56 'V key
Private Const VK_W = &H57 'W key
Private Const VK_X = &H58 'X key
Private Const VK_Y = &H59 'Y key
Private Const VK_Z = &H5A 'Z key
Private Const VK_NUMPAD0 = &H60 'Numeric keypad 0 key
Private Const VK_NUMPAD1 = &H61 'Numeric keypad 1 key
Private Const VK_NUMPAD2 = &H62 'Numeric keypad 2 key
Private Const VK_NUMPAD3 = &H63 'Numeric keypad 3 key
Private Const VK_NUMPAD4 = &H64 'Numeric keypad 4 key
Private Const VK_NUMPAD5 = &H65 'Numeric keypad 5 key
Private Const VK_NUMPAD6 = &H66 'Numeric keypad 6 key
Private Const VK_NUMPAD7 = &H67 'Numeric keypad 7 key
Private Const VK_NUMPAD8 = &H68 'Numeric keypad 8 key
Private Const VK_NUMPAD9 = &H69 'Numeric keypad 9 key
Private Const VK_SEPARATOR = &H6C 'Separator key
Private Const VK_SUBTRACT = &H6D 'Subtract key
Private Const VK_DECIMAL = &H6E 'Decimal key
Private Const VK_DIVIDE = &H6F 'Divide key
Private Const VK_F1 = &H70 'F1 key
Private Const VK_F2 = &H71 'F2 key
Private Const VK_F3 = &H72 'F3 key
Private Const VK_F4 = &H73 'F4 key
Private Const VK_F5 = &H74 'F5 key
Private Const VK_F6 = &H75 'F6 key
Private Const VK_F7 = &H76 'F7 key
Private Const VK_F8 = &H77 'F8 key
Private Const VK_F9 = &H78 'F9 key
Private Const VK_F10 = &H79 'F10 key
Private Const VK_F11 = &H7A 'F11 key
Private Const VK_F12 = &H7B 'F12 key
Private Const VK_F13 = &H7C 'F13 key
Private Const VK_F14 = &H7D 'F14 key
Private Const VK_F15 = &H7E 'F15 key
Private Const VK_F16 = &H7F 'F16 key
Private Const VK_NUMLOCK = &H90 'NUM LOCK key
Private Const VK_SCROLL = &H91 'SCROLL LOCK key
Private Const VK_LSHIFT = &HA0 'Left SHIFT key
Private Const VK_RSHIFT = &HA1 'Right SHIFT key
Private Const VK_LCONTROL = &HA2 'Left CONTROL key
Private Const VK_RCONTROL = &HA3 'Right CONTROL key
Private Const VK_LMENU = &HA4 'Left MENU key
Private Const VK_RMENU = &HA5 'Right MENU key
Private Const VK_PLAY = &HFA 'Play key
Private Const VK_ZOOM = &HFB 'Zoom key
'REMINDER: To remind yourself how to use these keys
' with the GetAsyncKeyState function, please visit:
' http://wellsr.com/vba/2017/excel/GetAsyncKeyState-vba-to-wait-until-a-key-is-pressed/
I haven’t tested every one of these keystrokes, so if you find any errors, please leave a comment and let me know. I’ll work to improve the list with your feedback.
Application Ideas - GetAsyncKeyState VBA
I can see your wheels turning already! Having all these key detection tools at your disposal gives you an incredible amount of power. I’m excited to hear what kind of VBA applications you plan on making with this.
Like I said, I use this in my Mouse To Macro add-in to begin recording and to unload a userform when a certain key is pressed. But that’s just one of an infinite number of possibilities you can do. Leave me a comment with what you’d like to see done with the GetAsyncKeyState function!
Now’s the time I beg ask you to subscribe to my free wellsrPRO VBA Training Program. Once you subscribe, you’ll get access to a free copy of my Excel Add-In with tons of useful features and you’ll get email tutorials where I show you how to do some pretty cool stuff with VBA:)