(PC Magazine Vol 6 No 4 Feb 24, 1987 PC Tutor)
You can turn CapsLock or NumLock on or off a various times from
withing a program. You might want to do this, for instance, if the
program needed number input at some point, when you would turn on
NumLock so the number pad is usable.
A single byte containing all shift state information is maintained
by the PC's BIOS. If you just need to look at this byte, you can get
it by making an INT 16h call with AH equal to 2. In most programming
languages it's easier to fish it out of memory yourself. If you want
to change it, you must directory access the byte. It is located at
hex address 40:17.
Each of the 8 bits in this byte refer to the state of a different
shift key. If you think of bit 7 as the leftmost (or most significant)
bit and bit 0 as the rightmost bit, here's what the 8 bits mean:
Bit A 1 means that: Mask Mask
7 Insert is on 80 7F
6 CapsLock is on 40 BF
5 NumLock is on 20 DF
4 ScrollLock is on 10 EF
3 Alt key is down 08 F7
2 Ctrl key is down 04 FB
1 Left shift is down 02 FD
0 Right Shift is down 01 FE
The "OR Mask" is a hex value that you can use to turn the shift
sate on. The "AND Mask" is a hex value that turns it off. For
instance, if you want to turn on NumLock, you would need to retrieve
the shift state byte from memory, perform a logical OR with the hex
value 20 (to turn the bit on), and store the value back into memory.
You can manipulate these bits in any programming language that
allows you to access memory in segments outside your program. In
BASIC, you'd use DEF SEG, PEEK, and POKE. In Turbo Pascal, you'd use
the MEM array. In assembly language or C, you'd use a far pointer.
In a BASIC program, this code will turn on NumLock:
POKE &H17, &H20 OR PEEK (&H17)
In Turbo Pascal:
Mem [$40:$17] := Mem [$40;$17] OR $20 ;
In assembly language:
OR BYTE PTR ds:[17h],20h
* (char far *) 0x400017 |= 0x20
This last example assumes that your C compiler implements the "far"
keyword the same way as Microsoft C, Versions 3 and 4. In all these
examples, hex addresses and values are used. Note that each of these
languages uses a different notation for hex.
To turn NumLock off, you can use similar code except that you want
to set the bit to zero. In all the examples above, replace 20 with DF.
(In the assembly example, preface DF with a 0.) In the BASIC, Turbo
Pascal, and assembler examples, replace OR with AND. In the C example,
replace the OR operator (|) with an AND operator (&).
Changing the keyboard shift states from within a program is not
always a good idea. Even Lotus's 1-2-3 doesn't turn off NumLock. It
will tel you about it and request that you turn it off, but it won't
turn it off itself.