Author Topic: CapsLock, NumLock, ScrollLock  (Read 3183 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
CapsLock, NumLock, ScrollLock
« on: June 24, 2019, 06:39:13 am »
A simple demo to show how we can use DECLARE LIBRARY to get the initial key state of CapsLock, NumLock, and ScrollLock, and how we can use QB64 to change them for us, if wanted.

Code: [Select]
DECLARE LIBRARY
    FUNCTION GetKeyState% (BYVAL nVirtKey AS LONG)
    SUB keybd_event (BYVAL bVK AS _BYTE, BYVAL bScan AS _BYTE, BYVAL dwFlags AS LONG, BYVAL dwExtraInfo AS _OFFSET)
END DECLARE



VK_CAPITAL = &H14
VK_NUMLOCK = &H90
VK_SCROLLLOCK = &H91

DO
    LOCATE 1, 1
    PRINT GetKeyState(VK_CAPITAL), GetKeyState(VK_NUMLOCK), GetKeyState(VK_SCROLLLOCK)
    a$ = INKEY$
    SELECT CASE a$
        CASE "c", "C"
            keybd_event VK_CAPITAL, &H45, 1, 0
            keybd_event VK_CAPITAL, &H45, 3, 0
        CASE "n", "n"
            keybd_event VK_NUMLOCK, &H45, 1, 0
            keybd_event VK_NUMLOCK, &H45, 3, 0
        CASE "s", "S"
            keybd_event VK_SCROLLLOCK, &H45, 1, 0
            keybd_event VK_SCROLLLOCK, &H45, 3, 0
        CASE CHR$(27)
            SYSTEM
        CASE ""
        CASE ELSE
            PRINT a$
    END SELECT
    _LIMIT 30
LOOP

This prints 3 values on the screen for us -- one for each keystate our OS/program might be in.  To toggle the values, hit C for caps lock, N for num lock, and S for scroll lock.  (It wouldn't make much sense to do a demo where we hit the actual keys and watched the values change -- this little program does the work for us WITHOUT having to press those keys.)

NOTE: This only works for Windows (as far as I know, since these are windows API calls).

NOTE 2: If you notice, there's no library actually listed in the DECLARE LIBRARY statement.  That's because QB64 already has declared these functions, and we're just making use of them naturally.



Since these functions are already available inside libqb, they'd be a breeze to implement into the language as a set of new keywords.  If several people see the need/use of adding a _CAPSLOCK function/sub (and same for the other keys), let me know and I'll add them into the language for us.

If added, all one would have to do is something like:

PRINT _CAPSLOCK  'to print a value to tell us if it's currently ON or OFF.
_CAPSLOCK ON 'to set it on
_CAPSLOCK OFF 'to set it off

Just ask yourself, is it worth adding multiple new words to the language to support these functions?  Or is it better to just leave them as DECLARE LIBRARY statements, as per the demo above, and not add to the ever-growing list of keywords?
« Last Edit: June 24, 2019, 06:41:07 am by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: CapsLock, NumLock, ScrollLock
« Reply #1 on: June 24, 2019, 07:31:34 am »
Interresting approach, i usually go the DEF SEG / PEEK / POKE way. You can use the returned flag% to decide, if you've to restore the old state later or not.
Code: QB64: [Select]
  1. '---------------------------------------------------------------------
  2. 'Function: Switch off the CapsLock.
  3. '
  4. 'Synopsis: flag% = CapsLockOff% (VOID)
  5. '
  6. 'Result:   flag% --> = FALSE (0), if CapsLock was already off
  7. '                    = TRUE (-1), if CapsLock was currently on
  8. '---------------------------------------------------------------------
  9. FUNCTION CapsLockOff%
  10. DEF SEG = 0
  11. ks% = PEEK(&H417)
  12. POKE &H417, (ks% AND &HFFBF)
  13. CapsLockOff% = -((ks% AND 64) / 64)
  14.  
  15. '---------------------------------------------------------------------
  16. 'Function: Switch on the CapsLock.
  17. '
  18. 'Synopsis: flag% = CapsLockOn% (VOID)
  19. '
  20. 'Result:   flag% --> = FALSE (0), if CapsLock was currently off
  21. '                    = TRUE (-1), if CapsLock was already on
  22. '---------------------------------------------------------------------
  23. FUNCTION CapsLockOn%
  24. DEF SEG = 0
  25. ks% = PEEK(&H417)
  26. POKE &H417, (ks% OR &H40)
  27. CapsLockOn% = -((ks% AND 64) / 64)
  28.  
  29. '---------------------------------------------------------------------
  30. 'Function: Switch off the NumLock
  31. '
  32. 'Synopsis: flag% = NumLockOff% (VOID)
  33. '
  34. 'Result:   flag% --> = FALSE (0), if NumLock was already off
  35. '                    = TRUE (-1), if NumLock was currently on
  36. '---------------------------------------------------------------------
  37. FUNCTION NumLockOff%
  38. DEF SEG = 0
  39. ks% = PEEK(&H417)
  40. POKE &H417, (ks% AND &HFFDF)
  41. NumLockOff% = -((ks% AND 32) / 32)
  42.  
  43. '---------------------------------------------------------------------
  44. 'Function: Switch on the NumLock
  45. '
  46. 'Synopsis: flag% = NumLockOn% (VOID)
  47. '
  48. 'Result:   flag% --> = FALSE (0), if NumLock was currently off
  49. '                    = TRUE (-1), if NumLock was already on
  50. '---------------------------------------------------------------------
  51. FUNCTION NumLockOn%
  52. DEF SEG = 0
  53. ks% = PEEK(&H417)
  54. POKE &H417, (ks% OR &H20)
  55. NumLockOn% = -((ks% AND 32) / 32)
  56.  
  57. '---------------------------------------------------------------------
  58. 'Function: Switch off the ScrollLock
  59. '
  60. 'Synopsis: flag% = ScrollLockOff% (VOID)
  61. '
  62. 'Result:   flag% --> = FALSE (0), if ScrollLock was already off
  63. '                    = TRUE (-1), if ScrollLock was currently on
  64. '---------------------------------------------------------------------
  65. FUNCTION ScrollLockOff%
  66. DEF SEG = 0
  67. ks% = PEEK(&H417)
  68. POKE &H417, (ks% AND &HFFEF)
  69. ScrollLockOff% = -((ks% AND 16) / 16)
  70.  
  71. '---------------------------------------------------------------------
  72. 'Function: Switch on the ScrollLock
  73. '
  74. 'Synopsis: flag% = ScrollLockOn% (VOID)
  75. '
  76. 'Result:   flag% --> = FALSE (0), if ScrollLock was currently off
  77. '                    = TRUE (-1), if ScrollLock was already on
  78. '---------------------------------------------------------------------
  79. FUNCTION ScrollLockOn%
  80. DEF SEG = 0
  81. ks% = PEEK(&H417)
  82. POKE &H417, (ks% OR &H10)
  83. ScrollLockOn% = -((ks% AND 16) / 16)
  84.  
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: CapsLock, NumLock, ScrollLock
« Reply #2 on: June 24, 2019, 07:39:31 am »
POKE actually doesn’t change the state for me — at least it doesn’t change the indicator lights on the keyboard, signaling a state change, which can be rather confusing, on my system. 

Question:  When POKE works, does it work on Linux/Mac systems for us?  I find the Windows calls easier and more reliable for my needs, but it might be nice to use the old methods if they work on the other platforms.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: CapsLock, NumLock, ScrollLock
« Reply #3 on: June 24, 2019, 08:08:09 am »
Hi Steve, it would be nice to have these new keywords.

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: CapsLock, NumLock, ScrollLock
« Reply #4 on: June 24, 2019, 08:25:20 am »
POKE actually doesn’t change the state for me — at least it doesn’t change the indicator lights on the keyboard, signaling a state change, which can be rather confusing, on my system. 

Actually you're right, just tested it here on my win7 system. And i must confess i haven't used these routines for long time, probably never in conjunction with QB64. I remember it worked with QBasic 1.1 on winXP, but that's at least 10 years ago.
Probably newer win versions block this kind of hardware banging now. However, it's interesting that it still reads the current key state correctly.

Question:  When POKE works, does it work on Linux/Mac systems for us?  I find the Windows calls easier and more reliable for my needs, but it might be nice to use the old methods if they work on the other platforms.

Never worked with Linux/Mac.
« Last Edit: June 24, 2019, 08:27:12 am by RhoSigma »
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack