Иногда в программах требуется получать состояние управляющих клавиш или изменять их состояние. Во времена MS-DOS достаточно было просто прочитать или записать значение WORD по определенному адресу памяти, при этом светодиодные индикаторы клавиатуры реагировали на это включением или выключением. Были очень популярны крохотные, в несколько байт, программы для выключения NumLock при загрузке системы, типа таких:
;-----------------------------------------------------------
; Программа для выключения индикатора NumLock под MS-DOS
; Размер .com-файла после компиляции 9 байт
;-----------------------------------------------------------
.286
.model tiny
.code ; Сегмент кода
org 100h ; Зарезервировано для PSP
start:
pop ax ; После запуска в стеке 0, AX=0
mov ds,ax ; DS=0
mov ds:[417h],ax ; WORD DS:[417h] - состояние *Lock'ов
int 20h ; Выход из программы
end start
В свое время это был самый минимальный рабочий код для выключения клавиши NumLock, хоть и не совсем корректный в плане работы со стеком.
В среде Windows все значительно усложнилось. Теперь получать состояние переключателей приходится при помощи функции
GetKeyState. Для изменения состояния клавиш в Windows есть функция
SetKeyboardState, но она не меняет состояния светодиодов на клавиатуре. Поэтому придется искать другой путь, например, через функцию
keybd_event эмулировать нажатия на соответствующие клавиши. Для удобства я написал небольшую функцию, устанавливающую нужный переключатель в нужное состояние.
;------------------------------------------------------------------
; Функция переключения индикаторов
; Входные параметры:
; dKey - идентификатор клавиши
; dState - состояние (TRUE = включено, FALSE = выключено)
;------------------------------------------------------------------
proc SetLockState dKey:DWORD, dState:DWORD
pusha
; Получить состояние управляющей клавиши
invoke GetKeyState,[dKey]
; Если клавиша уже в нужном положении, то ничего не делать
cmp eax,[dState]
je @f
; Имитировать нажатие клавиши на клавиатуре
invoke keybd_event,[dKey],0,0,NULL
invoke keybd_event,[dKey],0,KEYEVENTF_KEYUP,NULL
@@:
popa
ret
endp
Параметры вызова: dKey - код клавиши, для этого в FASM уже предопределены константы VK_CAPITAL, VK_NUMLOCK и VK_SCROLL, dState - нужное состояние (TRUE - включено, FALSE - выключено). Пример вызова:
...
stdcall SetLockState,VK_CAPITAL,FALSE ; Выключить CapsLock
stdcall SetLockState,VK_NUMLOCK,TRUE ; Включить NumLock
...
В приложении программа, управляющая индикаторами и состоянием клавиш NumLock, CapsLock и ScrollLock. Обратной связи не предусмотрено, поэтому ручные нажатия на клавиши не меняют состояния checkbox'ов.