Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Keyboard LED control (capslock/numlock/scrolllock lights)


  • Please log in to reply
30 replies to this topic
evl
  • Members
  • 1237 posts
  • Last active: Oct 20 2010 11:41 AM
  • Joined: 24 Aug 2005
This script allows you to control which capslock/numlock/scrolllock LED indicators are lit up, to produce effects such as flashing and cycling without altering the actual state of those keys (i.e. doesn't interfere with typing).

The script consists of 2 sections: 1) Some examples near the top. 2) The necessary functions.

The code originated here: Using Keyboard LEDs for spectrum.

Credit goes to Shimanov for the original code, Peter for syntax improvements and JGR for the code to get the handle of the keyboard device directly.

; Keyboard LED control (capslock/numlock/scrolllock lights)
;   http://www.autohotkey.com/forum/viewtopic.php?t=10532

; USAGE: KeyboardLED(LEDvalue,"Cmd")  ; LEDvalue: ScrollLock=1, NumLock=2, CapsLock=4 ; Cmd = on/off/switch


Loop, 3 ; flash all LEDs
  {
  KeyboardLED(7,"on")
  Sleep, 500
  KeyboardLED(7,"off")
  Sleep, 500
  }
 
Loop, 3 ; flash ScrollLock LED
  {
  KeyboardLED(7,"off")
  KeyboardLED(4,"switch")
  Sleep, 500
  KeyboardLED(7,"off")
  Sleep, 500
  }

Loop, 3 ; cycle all LEDs left to right
  {
  KeyboardLED(7,"off")
  Sleep, 250
  KeyboardLED(2,"switch")
  Sleep, 250
  KeyboardLED(4,"switch")
  Sleep, 250
  KeyboardLED(1,"switch")
  Sleep, 250
  }

Loop, 3 ; progress bar in LEDs
  {
  KeyboardLED(7,"off")
  Sleep, 500
  KeyboardLED(2,"switch")
  Sleep, 500
  KeyboardLED(6,"switch")
  Sleep, 500
  KeyboardLED(7,"switch")
  Sleep, 500
  }

Loop, 3 ; Knight Rider KITT cycling all LEDs ;-)
  {
  KeyboardLED(2,"switch")
  Sleep, 500
  KeyboardLED(4,"switch")
  Sleep, 500
  KeyboardLED(1,"switch")
  Sleep, 500
  KeyboardLED(4,"switch")
  Sleep, 500
  }

KeyboardLED(0,"off")  ; all LED('s) according to keystate (Command = on or off) 
Return



KeyboardLED(LEDvalue, Cmd)  ; LEDvalue: ScrollLock=1, NumLock=2, CapsLock=4 ; Cmd = on/off/switch
{
  Static h_device
  If ! h_device ; initialise
    {
    device =\Device\KeyBoardClass0
    SetUnicodeStr(fn,device) 
    h_device:=NtCreateFile(fn,0+0x00000100+0x00000080+0x00100000,1,1,0x00000040+0x00000020,0)
    }

  VarSetCapacity( output_actual, 4, 0 )
  input_size = 4
  VarSetCapacity( input, input_size, 0 )

  If Cmd= switch  ;switches every LED according to LEDvalue
   KeyLED:= LEDvalue
  If Cmd= on  ;forces all choosen LED's to ON (LEDvalue= 0 ->LED's according to keystate)
   KeyLED:= LEDvalue | (GetKeyState("ScrollLock", "T") + 2*GetKeyState("NumLock", "T") + 4*GetKeyState("CapsLock", "T"))
  If Cmd= off  ;forces all choosen LED's to OFF (LEDvalue= 0 ->LED's according to keystate)
    {
    LEDvalue:= LEDvalue ^ 7
    KeyLED:= LEDvalue & (GetKeyState("ScrollLock", "T") + 2*GetKeyState("NumLock", "T") + 4*GetKeyState("CapsLock", "T"))
    }
  ; EncodeInteger( KeyLED, 1, &input, 2 ) ;input bit pattern (KeyLED): bit 0 = scrolllock ;bit 1 = numlock ;bit 2 = capslock
  input := Chr(1) Chr(1) Chr(KeyLED)
  input := Chr(1)
  input=
  success := DllCall( "DeviceIoControl"
              , "uint", h_device
              , "uint", CTL_CODE( 0x0000000b     ; FILE_DEVICE_KEYBOARD
                        , 2
                        , 0             ; METHOD_BUFFERED
                        , 0  )          ; FILE_ANY_ACCESS
              , "uint", &input
              , "uint", input_size
              , "uint", 0
              , "uint", 0
              , "uint", &output_actual
              , "uint", 0 )
}

CTL_CODE( p_device_type, p_function, p_method, p_access )
{
  Return, ( p_device_type << 16 ) | ( p_access << 14 ) | ( p_function << 2 ) | p_method
}


NtCreateFile(ByRef wfilename,desiredaccess,sharemode,createdist,flags,fattribs)
{ 
  VarSetCapacity(fh,4,0) 
  VarSetCapacity(objattrib,24,0) 
  VarSetCapacity(io,8,0) 
  VarSetCapacity(pus,8) 
  uslen:=DllCall("lstrlenW","str",wfilename)*2 
  InsertInteger(uslen,pus,0,2) 
  InsertInteger(uslen,pus,2,2) 
  InsertInteger(&wfilename,pus,4) 
  InsertInteger(24,objattrib,0) 
  InsertInteger(&pus,objattrib,8) 
  status:=DllCall("ntdll\ZwCreateFile","str",fh,"UInt",desiredaccess,"str",objattrib,"str",io,"UInt",0,"UInt",fattribs
                  ,"UInt",sharemode,"UInt",createdist,"UInt",flags,"UInt",0,"UInt",0, "UInt") 
  return % ExtractInteger(fh) 
} 


SetUnicodeStr(ByRef out, str_)
{ 
  VarSetCapacity(st1, 8, 0) 
  InsertInteger(0x530025, st1) 
  VarSetCapacity(out, (StrLen(str_)+1)*2, 0) 
  DllCall("wsprintfW", "str", out, "str", st1, "str", str_, "Cdecl UInt") 
} 


ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4) 
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset. 
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned. 
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int). 
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process 
; (since pSource might contain valid data beyond its first binary zero). 
{ 
  Loop %pSize%  ; Build the integer by adding up its bytes. 
    result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1) 
  if (!pIsSigned OR pSize > 4 OR result < 0x80000000) 
    return result  ; Signed vs. unsigned doesn't matter in these cases. 
  ; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart: 
  return -(0xFFFFFFFF - result + 1) 
} 


InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4) 
; The caller must ensure that pDest has sufficient capacity.  To preserve any existing contents in pDest, 
; only pSize number of bytes starting at pOffset are altered in it. 
{ 
  Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data. 
    DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF) 
}


evl
  • Members
  • 1237 posts
  • Last active: Oct 20 2010 11:41 AM
  • Joined: 24 Aug 2005
Here's a simple script I wrote to "disable" the NumLock LED on my laptop (it's quite distracting since I'm usually using an external keyboard and never change the status really). The script just checks the numlock state and if numlock is on it turns the LED off and vice versa (i.e. it becomes a Numlock-Off LED):

Gosub, ~NumLock
Return

~NumLock:: 
~CapsLock:: 
~ScrollLock::
  Sleep, 10 ; improve reliability of setting LED state sometimes
  If (GetKeyState("Numlock", "T"))
    KeyboardLED(2,"off")
  Else
    KeyboardLED(2,"on")
Return

(Obviously this requires the functions from the main script in the 1st post)

T-nm
  • Guests
  • Last active:
  • Joined: --
Wow this rocks, you're cool.
I don't have my other computer with the USB keyboard, so I'll have to try with it another time.
Thanks!

T-nm
  • Guests
  • Last active:
  • Joined: --
Aww it doesn't, but it works with your older version, must be some kind of detection. Like replacing the ACPI for HID :confused:

evl
  • Members
  • 1237 posts
  • Last active: Oct 20 2010 11:41 AM
  • Joined: 24 Aug 2005
Does it work on the USB keyboard if you change the 0 in "device =\Device\KeyBoardClass0" to 1 or 2?

I have a USB keyboard, but it doesn't have LEDs so I can't test.

T-nm
  • Guests
  • Last active:
  • Joined: --
I'm pretty sure it can, but right now I can't. I'll tell you another time, maybe someone can try it out. My saitek gaming keyboard is usb only, can't use the adaptor.
There's also something funny when using the script, when the loop go too fast, like 100ms for each action it sometimes double a key when typing.

Also, remember to check out:
http://www.samurize.... ... 6&lid=1886
Samurize.com - Downloads

It uses the leds as spectrum, but only works with ps2 keyboards.

Rajat
  • Members
  • 1904 posts
  • Last active: Jul 17 2015 07:45 AM
  • Joined: 28 Mar 2004
just tried it out... looks good! can be used for some mail notifications etc.

MIA

CleanNews.in : Bite sized latest news headlines from India with zero bloat


T-nm
  • Members
  • 27 posts
  • Last active: Mar 24 2012 07:03 AM
  • Joined: 22 Jun 2006
Any ideas of how to use it for mail notifications?

evl
  • Members
  • 1237 posts
  • Last active: Oct 20 2010 11:41 AM
  • Joined: 24 Aug 2005
There doesn't seem to be a particularly direct way with AHK (try searching the forums) so I guess the best way would be to retrieve info from a mail monitoring program with SetTimer (you could hide the window so it's not visible).

ninjasnip3r
  • Guests
  • Last active:
  • Joined: --
Omfg, i'm really mad, I dont know how to put this code into order so i can run it correctly... I WANT TO USE

Loop, 3 ; Knight Rider KITT cycling all LEDs ;-)

But how do i put it into the other code? can someone do this for me?¿?¿!!!

PLEASE.

evl
  • Members
  • 1237 posts
  • Last active: Oct 20 2010 11:41 AM
  • Joined: 24 Aug 2005
You just need to put the following part where you want the changes to occur in your script:
Loop, 3 ; Knight Rider KITT cycling all LEDs ;-) 
  { 
  KeyboardLED(2,"switch") 
  Sleep, 500 
  KeyboardLED(4,"switch") 
  Sleep, 500 
  KeyboardLED(1,"switch") 
  Sleep, 500 
  KeyboardLED(4,"switch") 
  Sleep, 500 
  } 

KeyboardLED(0,"off")  ; all LED('s) according to keystate (Command = on or off)

And all of the functions need to go at the end of your script (i.e. everything after the Return in the 1st post).

1991
  • Members
  • 29 posts
  • Last active: Jun 04 2007 03:05 AM
  • Joined: 20 Jan 2006
cool.

way cool.

an interesting thing to do is to make a kind of "light tester"

with the following code the lights blink approximately at 60hz, thus if the keyboard is near a fast switching light like flourescent one or a strobe light, the light that is flashing out of sync is obvious.

{
method for additional security(?) :
ask user password- final digit is one two or three according to the "secret"
oddball LED (found by using a strobelight)?

of course this would be for simple security like for stopping kids from downloading games off of the internet (very very minimal security).
}


loop, 30
{
random,key,0,2
if key=0
{
key1=6
key2=1
}
if key=1
{
key1=5
key2=2
}
if key=2
{
key1=3
key2=4
}
loop, 60
{

KeyboardLED(key2,"off")
KeyboardLED(key1,"on")
sleep,9
KeyboardLED(key1,"off")
KeyboardLED(key2,"on")
sleep,8
}
sleep,1000
}
KeyboardLED(0,"off")
return

of course, with the above function

vzx
  • Guests
  • Last active:
  • Joined: --
Sorry to dredge up this old thread, but I just got started with AutoHotkey and had the urge to make an LED show. I made it first without this script, and when I ported it, it became glitchy, especially with the NumLock. I will present both forms of the code and any help on the 2nd would be appreciated.
/*
---------------leD sHOW by veZquEx-----------------
| eNjOy a CONtiNUOs LoOP OF InDICaTiNG excIteMEnt.|
| WarNINg: mAy scReW wITh caPitAlIzaTION.         |
|               pResS "EsC" TO PAUse              |
---------------------------------------------------
*/


SetNumlockState, off
SetCapsLockState, off
SetScrollLockState, off

Continuous:
Loop {
	Loop 6 {
;walk
		SetNumlockState, on
		Sleep, 100
		SetNumlockState, off
		SetCapsLockState, on
		Sleep, 100
		SetCapsLockState, off
		SetScrollLockState, on
		Sleep, 100
		SetScrollLockState, off
		SetCapsLockState, on
		Sleep, 100
		SetCapsLockState, off
	}
	Loop 4 {
;add
		SetNumlockState, on
		Sleep, 100
		SetCapsLockState, on
		Sleep, 100
		SetScrollLockState, on
		Sleep, 100
		SetScrollLockState, off
		Sleep, 100
		SetCapsLockState, off
		Sleep, 100
		SetNumlockState, off
		Sleep, 300
	}
	Loop 8 {
;flash all
		SetNumlockState, on
		SetCapsLockState, on
		SetScrollLockState, on
		Sleep, 100
		SetScrollLockState, off
		SetCapsLockState, off
		SetNumlockState, off
		Sleep, 100
	}
	SetNumlockState, on
	SetCapsLockState, on
	SetScrollLockState, on
	Sleep, 100
	Loop 3 {
		SetNumlockState, off
		SetCapsLockState, off
		Sleep, 200
		SetNumlockState, on
		SetCapsLockState, on
		SetScrollLockState, off
		Sleep, 200
		SetScrollLockState, on
	}
	Loop 3 {
		SetCapsLockState, off
		SetScrollLockState, off
		Sleep, 200
		SetCapsLockState, on
		SetScrollLockState, on
		SetNumlockState, off
		Sleep, 200
		SetNumlockState, on
	}
	Loop 3 {
		SetNumlockState, off
		SetScrollLockState, off
		Sleep, 200
		SetCapsLockState, off
		SetNumlockState, on
		SetScrollLockState, on
		Sleep, 200
		SetCapsLockState, on
	}
	Sleep, 300
	SetNumlockState, off
	Sleep, 300
	SetCapsLockState, off
	Sleep, 300
	SetScrollLockState, off
	Sleep, 750
}

Escape::
SetNumlockState, on
SetCapsLockState, off
SetScrollLockState, off
Pause
Return
/*
--------------leD sHOW 2 by veZquEx----------------
| eNjOy a CONtiNUOs LoOP OF InDICaTiNG excIteMEnt.|
|               pResS "EsC" TO PAUse              |
---------------------------------------------------
*/



Continuous:
Loop {
	Loop 6 {
;walk
		KeyboardLED(2,"on")
		Sleep, 100
		KeyboardLED(2,"off")
		KeyboardLED(4,"on")
		Sleep, 100
		KeyboardLED(4,"off")
		KeyboardLED(1,"on")
		Sleep, 100
		KeyboardLED(1,"off")
		KeyboardLED(4,"on")
		Sleep, 100
		KeyboardLED(4,"off")
	}
	Loop 4 {
;add
		KeyboardLED(2,"on")
		Sleep, 100
		KeyboardLED(4,"on")
		Sleep, 100
		KeyboardLED(1,"on")
		Sleep, 100
		KeyboardLED(1,"off")
		Sleep, 100
		KeyboardLED(4,"off")
		Sleep, 100
		KeyboardLED(2,"off")
		Sleep, 300
	}
	Loop 8 {
;flash all
	  KeyboardLED(7,"on")
		Sleep, 100
  	KeyboardLED(7,"off")
		Sleep, 100
	}
  KeyboardLED(7,"on")
	Sleep, 100
	Loop 3 {
		KeyboardLED(2,"off")
		KeyboardLED(4,"off")
		Sleep, 200
		KeyboardLED(2,"on")
		KeyboardLED(4,"on")
		KeyboardLED(1,"off")
		Sleep, 200
		KeyboardLED(1,"on")
	}
	Loop 3 {
		KeyboardLED(4,"off")
		KeyboardLED(1,"off")
		Sleep, 200
		KeyboardLED(4,"on")
		KeyboardLED(1,"on")
		KeyboardLED(2,"off")
		Sleep, 200
		KeyboardLED(2,"on")
	}
	Loop 3 {
		KeyboardLED(2,"off")
		KeyboardLED(1,"off")
		Sleep, 200
		KeyboardLED(4,"off")
		KeyboardLED(2,"on")
		KeyboardLED(1,"on")
		Sleep, 200
		KeyboardLED(4,"on")
	}
	Sleep, 300
	KeyboardLED(2,"off")
	Sleep, 300
	KeyboardLED(4,"off")
	Sleep, 300
	KeyboardLED(1,"off")
	Sleep, 750
}

Escape::
KeyboardLED(2,"on")
KeyboardLED(4,"off")
KeyboardLED(1,"off")
Pause
Return

; Keyboard LED control (capslock/numlock/scrolllock lights)
;   http://www.autohotkey.com/forum/viewtopic.php?t=10532

; USAGE: KeyboardLED(LEDvalue,"Cmd")  ; LEDvalue: ScrollLock=1, NumLock=2, CapsLock=4 ; Cmd = on/off/switch


KeyboardLED(LEDvalue, Cmd)  ; LEDvalue: ScrollLock=1, NumLock=2, CapsLock=4 ; Cmd = on/off/switch
{
  Static h_device
  If ! h_device ; initialise
    {
    device =\Device\KeyBoardClass0
    SetUnicodeStr(fn,device)
    h_device:=NtCreateFile(fn,0+0x00000100+0x00000080+0x00100000,1,1,0x00000040+0x00000020,0)
    }

  VarSetCapacity( output_actual, 4, 0 )
  input_size = 4
  VarSetCapacity( input, input_size, 0 )

  If Cmd= switch  ;switches every LED according to LEDvalue
   KeyLED:= LEDvalue
  If Cmd= on  ;forces all choosen LED's to ON (LEDvalue= 0 ->LED's according to keystate)
   KeyLED:= LEDvalue | (GetKeyState("ScrollLock", "T") + 2*GetKeyState("NumLock", "T") + 4*GetKeyState("CapsLock", "T"))
  If Cmd= off  ;forces all choosen LED's to OFF (LEDvalue= 0 ->LED's according to keystate)
    {
    LEDvalue:= LEDvalue ^ 7
    KeyLED:= LEDvalue & (GetKeyState("ScrollLock", "T") + 2*GetKeyState("NumLock", "T") + 4*GetKeyState("CapsLock", "T"))
    }
  ; EncodeInteger( KeyLED, 1, &input, 2 ) ;input bit pattern (KeyLED): bit 0 = scrolllock ;bit 1 = numlock ;bit 2 = capslock
  input := Chr(1) Chr(1) Chr(KeyLED)
  input := Chr(1)
  input=
  success := DllCall( "DeviceIoControl"
              , "uint", h_device
              , "uint", CTL_CODE( 0x0000000b     ; FILE_DEVICE_KEYBOARD
                        , 2
                        , 0             ; METHOD_BUFFERED
                        , 0  )          ; FILE_ANY_ACCESS
              , "uint", &input
              , "uint", input_size
              , "uint", 0
              , "uint", 0
              , "uint", &output_actual
              , "uint", 0 )
}

CTL_CODE( p_device_type, p_function, p_method, p_access )
{
  Return, ( p_device_type << 16 ) | ( p_access << 14 ) | ( p_function << 2 ) | p_method
}


NtCreateFile(ByRef wfilename,desiredaccess,sharemode,createdist,flags,fattribs)
{
  VarSetCapacity(fh,4,0)
  VarSetCapacity(objattrib,24,0)
  VarSetCapacity(io,8,0)
  VarSetCapacity(pus,8)
  uslen:=DllCall("lstrlenW","str",wfilename)*2
  InsertInteger(uslen,pus,0,2)
  InsertInteger(uslen,pus,2,2)
  InsertInteger(&wfilename,pus,4)
  InsertInteger(24,objattrib,0)
  InsertInteger(&pus,objattrib,8)
  status:=DllCall("ntdll\ZwCreateFile","str",fh,"UInt",desiredaccess,"str",objattrib,"str",io,"UInt",0,"UInt",fattribs
                  ,"UInt",sharemode,"UInt",createdist,"UInt",flags,"UInt",0,"UInt",0, "UInt")
  return % ExtractInteger(fh)
}


SetUnicodeStr(ByRef out, str_)
{
  VarSetCapacity(st1, 8, 0)
  InsertInteger(0x530025, st1)
  VarSetCapacity(out, (StrLen(str_)+1)*2, 0)
  DllCall("wsprintfW", "str", out, "str", st1, "str", str_, "Cdecl UInt")
}


ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
  Loop %pSize%  ; Build the integer by adding up its bytes.
    result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
  if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
    return result  ; Signed vs. unsigned doesn't matter in these cases.
  ; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
  return -(0xFFFFFFFF - result + 1)
}


InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity.  To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
  Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
    DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}


engunneer
  • Moderators
  • 9162 posts
  • Last active: Sep 12 2014 10:36 PM
  • Joined: 30 Aug 2005
Using the original script in the first post, it ran on my laptops's LEDs, and changing the device to Device 2, as evl said to do earlier, makes it work with my USB keyboard.

Oddly, one of the lights on my laptop didn't flash, since it doesn't appear to be one of the normal 3 lights. It's even hard to descibe what it does normally. I need to have numlock and this light on at the same time to even use the 'numpad' section of my laptop (normal keys in another use)

Thanks!

FiveOhHO
  • Members
  • 2 posts
  • Last active: Sep 23 2008 08:59 PM
  • Joined: 23 Sep 2008
I don't suppose anyone has extended the code for the ThinkPad T60p with like 9 LED light across? I looked at the code and it's way over my head but just thought I'd ask.