Posted in June 2013

Detecting key states in MapBasic

Here’s another neat little MapBasic function I’ve been using recently. I needed a way of detecting whether a key on the keyboard was currently pressed or not. My intention was to show a hidden debugging dialog if a user shift-clicked on a specific button control, but there’s no in-built functions in MapBasic for detecting key states. Fortunately it’s possible to hook into the Windows User32.dll to use the GetAsyncKeyState call. Here’s how this all works in MapBasic…

First, we’ve got to define the GetASyncKeyState call and a bunch of related constants which map keys to a numeric value. Copy and paste the contents below to a .def file (or download a pre-made version later in this post).

asynckeys.def:

Declare Function GetAsyncKeyState Lib "User32.dll" Alias "GetAsyncKeyState" (ByVal vKey As Integer) As Integer
DEFINE vbKeyShift 16
DEFINE vbKey1 49
DEFINE vbKey2 50
DEFINE vbKey3 51
DEFINE vbKey4 52
DEFINE vbKey5 53
DEFINE vbKey6 54
DEFINE vbKey7 55
DEFINE vbKey8 56
DEFINE vbKey9 57
DEFINE vbKey0 48
DEFINE vbKeyBack 8
DEFINE vbKeyTab 9
DEFINE vbKeyReturn 13
DEFINE vbKeyControl 17
DEFINE vbKeyMenu 18
DEFINE vbKeyPause 19
DEFINE vbKeyEscape 27
DEFINE vbKeySpace 32
DEFINE vbKeyEnd 35
DEFINE vbKeyHome 36
DEFINE vbKeyLeft 37
DEFINE vbKeyRight 39
DEFINE vbKeyUp 38
DEFINE vbKeyDown 40
DEFINE vbKeyInsert 45
DEFINE vbKeyDelete 46
DEFINE vbKeyMultiply 106
DEFINE vbKeyDivide 111
DEFINE vbKeyAdd 107
DEFINE vbKeySubtract 109
DEFINE vbKeyDecimal 110
DEFINE vbKeyF1 112
DEFINE vbKeyF2 113
DEFINE vbKeyF3 114
DEFINE vbKeyF4 115
DEFINE vbKeyF5 116
DEFINE vbKeyF6 117
DEFINE vbKeyF7 118
DEFINE vbKeyF8 119
DEFINE vbKeyF9 120
DEFINE vbKeyF10 121
DEFINE vbKeyF11 122
DEFINE vbKeyF12 123
DEFINE vbKeyNumlock 144
DEFINE vbKeyScrollLock 145
DEFINE vbKeySnapshot 44
DEFINE vbKeyPageUp 33
DEFINE vbKeyPageDown 34
DEFINE vbKeyNumpad1 97
DEFINE vbKeyNumpad2 98
DEFINE vbKeyNumpad3 99
DEFINE vbKeyNumpad4 100
DEFINE vbKeyNumpad5 101
DEFINE vbKeyNumpad6 102
DEFINE vbKeyNumpad7 103
DEFINE vbKeyNumpad8 104
DEFINE vbKeyNumpad9 105
DEFINE vbKeyNumpad0 96
DEFINE vbKeyPressed -32767
DEFINE vbKeyWasPressed 1

Now, you can test for the state of any key by calling getASyncKeyState( vKey ), where vKey is an integer value corresponding to the key you want to test. So getASyncKeyState( vbKeyControl ) will test the state of the control key. The value returned will reflect whether the key is currently pressed (vbKeyPressed), or has been pressed since the last call to the function (vbKeyWasPressed). Easy! Here’s a little sample program to demonstrate how this all works:

Include "asynckeys.def"
Declare Sub Main
Declare Sub KeyCheck

Sub KeyCheck
    ' Store the pressed state of the SHIFT key
    Dim iState As Integer
    iState = getASyncKeyState( vbKeyShift )

    ' Check what the state was
    Do Case iState
        Case vbKeyPressed
            Print "SHIFT is being pressed!"
        Case vbKeyWasPressed
            Print "SHIFT has been pressed since last check"
        Case Else
            Print "Nothing to report..."
    End Case

    ' Keep the dialog around
    Dialog Preserve
End Sub

Sub Main
    Dialog
        Title "ASync Key State"
        Control OKButton
            Title "Check"
            Calling KeyCheck
        Control CancelButton
            Title "Quit"
End Sub

Both the asynckeys.def definition file and the sample program are contained in this archive.

Tagged , , , , ,