/*
Keyboard LED control for AutoHotkey_L
http://www.autohotkey.com/forum/viewtopic.php?p=468000#468000
KeyboardLED(LEDvalue, 'Cmd', Kbd)
LEDvalue - ScrollLock=1, NumLock=2, CapsLock=4
Cmd - on/off/switch
Kbd - index of keyboard (probably 0 or 2)
*/
#Requires AutoHotkey v2
KeyboardLED(4, "switch")
KeyboardLED(ledValue, cmd, kbdIndex := 0) {
; KEYBOARD_INDICATOR_PARAMETERS LED bit flags (kbdmou.h)
static SCROLL_LOCK_LED := 0x0001
, NUM_LOCK_LED := 0x0002
, CAPS_LOCK_LED := 0x0004
, LED_MASK := 0x0007 ; SCROLL_LOCK_LED | NUM_LOCK_LED | CAPS_LOCK_LED
; NtCreateFile: DesiredAccess flags (ntioapi.h)
, FILE_READ_ATTRIBUTES := 0x00000080
, FILE_WRITE_ATTRIBUTES := 0x00000100
, SYNCHRONIZE := 0x00100000
; NtCreateFile: ShareAccess
, FILE_SHARE_READ := 0x00000001
; NtCreateFile: CreateDisposition
, FILE_OPEN := 0x00000001
; NtCreateFile: CreateOptions
, FILE_NON_DIRECTORY_FILE := 0x00000020
, FILE_SYNCHRONOUS_IO_NONALERT := 0x00000040
; sizeof(KEYBOARD_INDICATOR_PARAMETERS): USHORT UnitId + USHORT LedFlags
, KEYBOARD_INDICATOR_PARAMETERS_SIZE := 4
; CTL_CODE arguments for IOCTL_KEYBOARD_QUERY_INDICATORS (ntddkbd.h)
, KBD_DEVICE_TYPE := 0x0b ; FILE_DEVICE_KEYBOARD
, KBD_QUERY_FUNCTION := 0x10 ; query indicators
, KBD_SET_FUNCTION := 0x02 ; set indicators
, KBD_METHOD := 0x00 ; METHOD_BUFFERED
, KBD_ACCESS := 0x00 ; FILE_ANY_ACCESS
hDevice := NtCreateFile(
"\Device\KeyBoardClass" kbdIndex,
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
FILE_SHARE_READ,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
0 ; FileAttributes: ignored when opening an existing file
)
; Read actual LED state directly from the device
ioctlQuery := CTL_CODE(KBD_DEVICE_TYPE, KBD_QUERY_FUNCTION, KBD_METHOD, KBD_ACCESS)
inBuf := Buffer(KEYBOARD_INDICATOR_PARAMETERS_SIZE, 0)
outBuf := Buffer(KEYBOARD_INDICATOR_PARAMETERS_SIZE, 0)
DllCall("DeviceIoControl",
"ptr", hDevice,
"uint", ioctlQuery,
"ptr", inBuf,
"uint", KEYBOARD_INDICATOR_PARAMETERS_SIZE,
"ptr", outBuf,
"uint", KEYBOARD_INDICATOR_PARAMETERS_SIZE,
"uint*", &bytesReturned := 0,
"ptr", 0)
currentLeds := NumGet(outBuf, 2, "ushort")
if (cmd = "switch")
keyLed := currentLeds ^ ledValue
else if (cmd = "on")
keyLed := currentLeds | ledValue
else if (cmd = "off")
keyLed := currentLeds & (ledValue ^ LED_MASK)
indicatorParams := keyLed << 16
ioctlSet := CTL_CODE(KBD_DEVICE_TYPE, KBD_SET_FUNCTION, KBD_METHOD, KBD_ACCESS)
success := DllCall("DeviceIoControl",
"ptr", hDevice,
"uint", ioctlSet,
"int*", indicatorParams,
"uint", KEYBOARD_INDICATOR_PARAMETERS_SIZE,
"ptr", 0,
"uint", 0,
"uint*", &bytesReturned,
"ptr", 0)
NtCloseFile(hDevice)
return success
}
CTL_CODE(deviceType, function, method, access) {
return (deviceType << 16) | (access << 14) | (function << 2) | method
}
NtCreateFile(filename, desiredAccess, shareMode, createDisposition, createOptions, fileAttributes) {
pathBuf := Buffer(2 * StrPut(filename, "UTF-16"))
StrPut(filename, pathBuf, "UTF-16")
uniStr := Buffer(2 * A_PtrSize, 0)
objAttrib := Buffer(6 * A_PtrSize, 0)
ioStatus := Buffer(2 * A_PtrSize, 0)
DllCall("ntdll\RtlInitUnicodeString", "ptr", uniStr, "ptr", pathBuf)
NumPut("uint", 6 * A_PtrSize, objAttrib, 0) ; Length
NumPut("ptr", uniStr.Ptr, objAttrib, 2 * A_PtrSize) ; ObjectName
DllCall("ntdll\ZwCreateFile",
"ptr*", &hFile := 0,
"uint", desiredAccess,
"ptr", objAttrib,
"ptr", ioStatus,
"ptr", 0,
"uint", fileAttributes,
"uint", shareMode,
"uint", createDisposition,
"uint", createOptions,
"ptr", 0,
"uint", 0,
"uint")
return hFile
}
NtCloseFile(handle) {
return DllCall("ntdll\ZwClose", "ptr", handle)
}
Скрипт должен переключать состояние CapsLock. У меня работает.