Keyboard

.


Disable and re-enable CTRL-ALT-DELETE, ALT-TAB and CTRL-ESC

by Stuart Morris

Usefull when that process really should not be interupted. Note: It can cripple the PC

&GLOBAL-DEFINE A A
&GLOBAL-DEFINE SPI_SCREENSAVERRUNNING 97
 
DEFINE VARIABLE retVal   AS INTEGER NO-UNDO.
DEFINE VARIABLE lv-dummy AS INTEGER NO-UNDO.
 
PROCEDURE SystemParametersInfo{&A} EXTERNAL "USER32.DLL":U :
  DEFINE INPUT  PARAMETER uAction  AS LONG NO-UNDO.
  DEFINE INPUT  PARAMETER uParam   AS LONG NO-UNDO.
  DEFINE INPUT  PARAMETER lpvParam AS LONG NO-UNDO.
  DEFINE INPUT  PARAMETER fuWinIni AS LONG NO-UNDO.
  DEFINE OUTPUT PARAMETER retVal   AS LONG NO-UNDO.
END.
 
  /* --- Disable */
 
  RUN SystemParametersInfo{&A} (INPUT  {&SPI_SCREENSAVERRUNNING},
                                       1, /* True */
                                       lv-dummy,
                                       0,
                                OUTPUT retVal
                               )
                               NO-ERROR.
 
  /* --- Enable */
 
  RUN SystemParametersInfo{&A} (INPUT  {&SPI_SCREENSAVERRUNNING},
                                       0, /* False */
                                       lv-dummy,
                                       0,
                                OUTPUT retVal
                               )
                               NO-ERROR.

The keyboard: reading and setting toggle states

This example reads the toggle states of the three most commonly used toggle keys: Capslock, Numlock and Insert. The example also changes these three toggle states: you will see the LED's on your keyboard change.
The GetKeyboardState procedure fetches the keystates of 256 keys at once. There's also a GetKeyState procedure to fetch the state for 1 particular key, but there is no SetKeyState procedure for one key so if you need to change a keystate you will have to use SetKeyboadState and set them all.

{windows.i}
 
DEFINE VARIABLE CapsLockToggle AS LOGICAL.
DEFINE VARIABLE NumLockToggle AS LOGICAL.
DEFINE VARIABLE InsertToggle AS LOGICAL.
 
RUN GetKeyToggleState (OUTPUT CapsLockToggle, 
                       OUTPUT NumLockToggle, 
                       OUTPUT InsertToggle).
 
/* alter all three of them, for demonstration purposes */
RUN SetKeyToggleState (NOT CapsLockToggle, 
                       NOT NumLockToggle, 
                       NOT InsertToggle).
 
 
 
&GLOB  VK_CAPITAL 20
&GLOB  VK_INSERT 45
&GLOB  VK_NUMLOCK 144
&GLOBAL-DEFINE VK_SCROLL    145   /* (hex 91) SCROLL LOCK key  */
&GLOBAL-DEFINE VK_SHIFT     16    /* (hex 10) either SHIFT key */
&GLOBAL-DEFINE VK_CONTROL   17    /* (hex 11) either Ctrl key  */
/* The following only work under Windows NT/2000/XP: */
&GLOBAL-DEFINE VK_LSHIFT    160   /* (hex A0) Left SHIFT key   */
&GLOBAL-DEFINE VK_RSHIFT    161   /* (hex A1) Right SHIFT key  */
&GLOBAL-DEFINE VK_LCONTROL  162   /* (hex A2) Left CTRL key    */
&GLOBAL-DEFINE VK_RCONTROL  163   /* (hex A3) Right CTRL key   */
 
PROCEDURE GetKeyToggleState :
 
  DEFINE OUTPUT PARAMETER CapsLockToggle AS LOGICAL.
  DEFINE OUTPUT PARAMETER NumLockToggle AS LOGICAL.
  DEFINE OUTPUT PARAMETER InsertToggle AS LOGICAL.
 
  DEFINE VARIABLE KBState AS MEMPTR.
  DEFINE VARIABLE ReturnValue AS INTEGER NO-UNDO.
  SET-SIZE(KBState) = 256.
 
  /* Get the current state of the keyboard */
  RUN GetKeyboardState(GET-POINTER-VALUE(KBState), OUTPUT ReturnValue).
 
  CapsLockToggle = GET-BYTE(KBState, 1 + {&VK_CAPITAL}) MOD 2 = 1.
  NumLockToggle  = GET-BYTE(KBState, 1 + {&VK_NUMLOCK}) MOD 2 = 1.
  InsertToggle   = GET-BYTE(KBState, 1 + {&VK_INSERT})  MOD 2 = 1.
 
  SET-SIZE(KBState) = 0.   
 
END PROCEDURE.
 
/* ======================================================= */
 
PROCEDURE SetKeyToggleState :
 
   DEFINE INPUT PARAMETER CapsLockToggle AS LOGICAL.
   DEFINE INPUT PARAMETER NumLockToggle AS LOGICAL.
   DEFINE INPUT PARAMETER InsertLockToggle AS LOGICAL.
 
   DEFINE VARIABLE KBState AS MEMPTR.
   DEFINE VARIABLE ReturnValue AS INTEGER NO-UNDO.
   SET-SIZE(KBState) = 256.
 
   /* Get the current state of the keyboard */
   RUN GetKeyboardState(GET-POINTER-VALUE(KBState), OUTPUT ReturnValue).
 
   PUT-BYTE(KBState,1 + {&VK_CAPITAL})  = IF CapsLockToggle THEN 1 ELSE 0.
   PUT-BYTE(KBState,1 + {&VK_NUMLOCK})  = IF NumLockToggle THEN 1 ELSE 0.
   PUT-BYTE(KBState,1 + {&VK_INSERT})   = IF InsertLockToggle THEN 1 ELSE 0.
 
   RUN SetKeyboardState(INPUT GET-POINTER-VALUE(KBState), OUTPUT ReturnValue).
   SET-SIZE(KBState) = 0.   
 
END PROCEDURE.
 
PROCEDURE GetKeyboardState EXTERNAL {&USER}:
   DEFINE INPUT  PARAMETER KBState AS LONG. /* memptr */
   DEFINE RETURN PARAMETER RetVal  AS LONG. /* bool   */
END PROCEDURE.
 
PROCEDURE SetKeyboardState EXTERNAL {&USER} :
   DEFINE INPUT  PARAMETER KBState AS LONG. /* memptr */
   DEFINE RETURN PARAMETER RetVal  AS LONG. /* bool   */
END PROCEDURE.

explanation

GetKeyboardState fetches an array of 256 keystates, each keystate is one byte in size.
VK_CAPITAL (better known as Capslock) has index 20 in that array. Arrays in C are zero based while Progress starts counting at one, so the put-byte and get-byte statements are called with (1 + {&VK_CAPITAL}).
A key is toggled ON when the low-order bit of its keystate is set to 1. The example tests this by checking if the value is odd or even.
A key is pressed when the high-order bit is set to 1. This may be important to know, but not in this example.

notes

Although the code does change the toggle state for the Insert-button you will not notice it; for some reason the Progress fill-in and editor widgets will keep behaving as if Insert is toggled on.
The Statusbar ActiveX from Microsoft Common Controls V5 has panels that automatically represent the toggle states. However, these panels don't respond to the code.
Based on an idea by Paul Koufalis.