0

The VBA code "WaitUntilF9Key" detects the "F9" key pressed when its pressed and not until it is pressed. The "WaitUntilLButton" fires right away, not when the left keypad button is pressed. Why would this be? Tkx

Option Compare Database
Option Explicit
Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer

Public Const VK_LBUTTON = &H1
Public Const VK_RBUTTON = &H2
Private Const VK_F9 = &H78

Sub WaitUntilF9Key()
    Do Until GetAsyncKeyState(VK_F9)
        DoEvents
    Loop
    MsgBox ("Ta Da")
End Sub

Sub WaitUntilLButton()
    Do Until GetAsyncKeyState(VK_LBUTTON)
        DoEvents
    Loop
    MsgBox ("Ta Da")
End Sub
  • 2
    Busy-looping like this doesn't strike me as an ideal approach. Consider implementing subclassing callbacks... whatever you need this for. – Mathieu Guindon Mar 15 '19 at 19:37
  • 2
    You're using [GetAsyncKeyState](https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getasynckeystate) incorrectly - it can't be safely cast to a `Boolean` like your loop condition implies - you actually have to ***interpret*** the value. From the docs: "If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState." – Comintern Mar 15 '19 at 19:45
  • Thank-you both Comintern 2 and Mathiew Guidon 2. I appreciated the elaboration from the docs of the operation and return value. I still do not understand why the differences between the different key codes. I have given the approach of having the user interact with the keyboard to one of detecting the location of a pattern on the screen and initiating a change in key state i.e. mouseLeftdown at that location - which will probably not be obvious either. Comments welcome. – user3354549 Mar 17 '19 at 20:16

1 Answers1

2

GetAsyncKeyState returns a byte, not a boolean. You need to 'And' it with the bit you're looking for to get a meaningful result.

In your case, the bit you want is &H8000. From the microsoft docs for GetAsyncKeyState:

If the &H8000 bit of the return value is set, the key has been pressed at least once since the last time the thread called GetAsyncKeyState

Sub WaitUntilF9Key()
    Do Until GetAsyncKeyState(VK_F9) And &H8000
        DoEvents
    Loop
    MsgBox ("Ta Da")
End Sub

Sub WaitUntilLButton()
    Do Until GetAsyncKeyState(VK_LBUTTON) And &H8000
        DoEvents
    Loop
    MsgBox ("Ta Da")
End Sub

That said, like others have mentioned, busy-looping like this should usually be avoided if possible

Josh Eller
  • 2,045
  • 6
  • 11
  • Reminds me of a [recent question](https://stackoverflow.com/q/55049440/1188513) essentially asking why `Not 1` isn't `0`, treating an integer return value like a Boolean, pretty much like this. – Mathieu Guindon Mar 15 '19 at 19:49