Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Detecting the shift state of keys in realtime
Message
From
07/02/2019 08:50:31
 
 
To
07/02/2019 03:56:01
General information
Forum:
Visual FoxPro
Category:
Windows API functions
Environment versions
Visual FoxPro:
VFP 9 SP2
OS:
Windows 10
Miscellaneous
Thread ID:
01665968
Message ID:
01666020
Views:
41
>>>Me again,
>>>
>>>I have been playing around with the WinApi's getKeyState and GetKeyboardState function to determine when the Shift, Ctrl, or Alt key are pressed when a routine occurs. But the results tend to be random. Does anyone have a solution that returns the state of these keys? FYI. the routine is occurring in a TImer. I am attempt to implement a more dynamic tooltip that would display the content based on the state of the shift state and the content the mouse happens to be over at the time.
>>>
>>>Any suggestion are welcome.
>>
>>Use GetAsyncKeyState(). It returns a 32-bit value that can have the lower 16-bits parsed using BITAND(lnResult, 0x8000) to determine if the key is down or up (non-zero = down, zero = up).
>>
>>You can see all of the virtual keys to test, including VK_SHIFT, VK_CONTROL, VK_MENU (alt), as well as VK_RSHIFT, VK_LSHIFT, etc.
>>
>>
#define key_lshift 0xa0
>>#define key_rshift 0xa1
>>#define key_lctrl 0xa2
>>#define key_rctrl 0xa3
>>#define key_lalt 0xa4
>>#define key_ralt 0xa5
>>
>>DECLARE INTEGER GetAsyncKeyState IN WIN32API INTEGER nVKey
>>
>>LOCAL llLShiftDown, llRShiftDown, llLCtrlDown, llRCtrlDown, llLAltDown, llRAltDown
>>llLShiftDown = isKeyDown(key_lshift)
>>llRShiftDown = isKeyDown(key_rshift)
>>llLCtrlDown  = isKeyDown(key_lctrl)
>>llRCtrlDown  = isKeyDown(key_rctrl)
>>llLAltDown   = isKeyDown(key_lalt)
>>llRAltDown   = isKeyDown(key_ralt)
>>
>>* The same works for reading mouse buttons
>>#define left_button 0x1
>>#define right_button 0x2
>>#define middle_button 0x4
>>llLeftButtonDown   = isKeyDown(left_button)
>>llRightButtonDown  = isKeyDown(right_button)
>>llMiddleButtonDown = isKeyDown(middle_button)
>>
>>
>>FUNCTION isKeyDown
>>LPARAMETERS tnVKey
>>    RETURN (BITAND(GetAsyncKeyState(tnVKey), 0x8000) != 0)
>>
>>You can also BINDEVENTS(thisForm.HWnd, WM_KEYDOWN, "thisForm", "my_method") and intercept keystrokes which are made as they are made. This will be for any keystroke directed to that window. See WM_KEYDOWN for the bits to examine there to retrieve the vKey and live state as it changes.
>
>I cannot make this work by only Pressing the left shift key, it only triggers if I press Ctrl+shift.
>
>Ctrl alone does work, so it seems GetAsyncKeyState does not trigger with only shift key pressed?

I created this program to test it. It works here. Maybe I posted something incorrectly in the code above?
#define key_lshift 0xa0
#define key_rshift 0xa1
#define key_lctrl 0xa2
#define key_rctrl 0xa3
#define key_lalt 0xa4
#define key_ralt 0xa5
#define left_button 0x1
#define right_button 0x2
#define middle_button 0x4

LOCAL llLShiftDown, llRShiftDown, llLCtrlDown, llRCtrlDown, llLAltDown, llRAltDown
LOCAL llLeftButtonDown, llRightButtonDown, llMiddleButtonDown

DECLARE INTEGER GetAsyncKeyState IN WIN32API INTEGER nVKey
DO WHILE INKEY() != 27
    llLShiftDown = (BITAND(GetAsyncKeyState(key_lshift), 0x8000) != 0)
    llRShiftDown = (BITAND(GetAsyncKeyState(key_rshift), 0x8000) != 0)
    llLCtrlDown  = (BITAND(GetAsyncKeyState(key_lctrl), 0x8000) != 0)
    llRCtrlDown  = (BITAND(GetAsyncKeyState(key_rctrl), 0x8000) != 0)
    llLAltDown   = (BITAND(GetAsyncKeyState(key_lalt), 0x8000) != 0)
    llRAltDown   = (BITAND(GetAsyncKeyState(key_ralt), 0x8000) != 0)
    IF llLShiftDown
        CLEAR
        ? "Left shift"
    ENDIF
    IF llRShiftDown
        CLEAR
        ? "Right shift"
    ENDIF
    IF llLCtrlDown
        CLEAR
        ? "Left control"
    ENDIF
    IF llRCtrlDown
        CLEAR
        ? "Right control"
    ENDIF
    IF llLAltDown
        CLEAR
        ? "Left alt"
    ENDIF
    IF llRAltDown
        CLEAR
        ? "Right alt"
    ENDIF

    * The same works for reading mouse buttons
    llLeftButtonDown   = (BITAND(GetAsyncKeyState(left_button), 0x8000) != 0)
    llRightButtonDown  = (BITAND(GetAsyncKeyState(right_button), 0x8000) != 0)
    llMiddleButtonDown = (BITAND(GetAsyncKeyState(middle_button), 0x8000) != 0)
    IF llLeftButtonDown
        CLEAR
        ? "Left mouse button"
    ENDIF
    IF llRightButtonDown
        CLEAR
        ? "Right mouse button"
    ENDIF
    IF llMiddleButtonDown
        CLEAR
        ? "Middle mouse button"
    ENDIF
ENDDO
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform