3

Currently I use following autohotkey script to change keyboard layout using the CapsLock button.

SetCapsLockState, AlwaysOff

+CapsLock::CapsLock

#SingleInstance force


CapsLock::Send, {ALTDOWN}{SHIFTDOWN}{SHIFTUP}{CTRLUP}{ALTUP}
; in wind
; Send, #{SPACE}

    return

I want CapsLock LED be turned on when layout is Persian and off when it is Englsih. Is it possible? Indeed I want LED be switched wile CapsLock remains off.

2 Answers 2

3

There is a library called Keyboard LED Control which can be used to toggle the keyboard leds independent of their corresponding function. Use this method and doing something along the lines of:

#Include led.ahk
global PersionLayout := 0

CapsLock::
    Send, {ALTDOWN}{SHIFTDOWN}{SHIFTUP}{CTRLUP}{ALTUP}
    PersionLayout := !PersionLayout
    If PersionLayout = 1
        KeyboardLED(7, "on")
    Else
        KeyboardLED(7, "off")
Return

Here is the library from the above link for reference led.ahk:

/*

    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)

*/

KeyboardLED(LEDvalue, Cmd, Kbd=0)
{
  SetUnicodeStr(fn,"\Device\KeyBoardClass" Kbd)
  h_device:=NtCreateFile(fn,0+0x00000100+0x00000080+0x00100000,1,1,0x00000040+0x00000020,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"))
    }

  success := DllCall( "DeviceIoControl"
              ,  "ptr", h_device
              , "uint", CTL_CODE( 0x0000000b     ; FILE_DEVICE_KEYBOARD
                        , 2
                        , 0             ; METHOD_BUFFERED
                        , 0  )          ; FILE_ANY_ACCESS
              , "int*", KeyLED << 16
              , "uint", 4
              ,  "ptr", 0
              , "uint", 0
              ,  "ptr*", output_actual
              ,  "ptr", 0 )

  NtCloseFile(h_device)
  return success
}

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(objattrib,6*A_PtrSize,0)
  VarSetCapacity(io,2*A_PtrSize,0)
  VarSetCapacity(pus,2*A_PtrSize)
  DllCall("ntdll\RtlInitUnicodeString","ptr",&pus,"ptr",&wfilename)
  NumPut(6*A_PtrSize,objattrib,0)
  NumPut(&pus,objattrib,2*A_PtrSize)
  status:=DllCall("ntdll\ZwCreateFile","ptr*",fh,"UInt",desiredaccess,"ptr",&objattrib
                  ,"ptr",&io,"ptr",0,"UInt",fattribs,"UInt",sharemode,"UInt",createdist
                  ,"UInt",flags,"ptr",0,"UInt",0, "UInt")
  return % fh
}

NtCloseFile(handle)
{
  return DllCall("ntdll\ZwClose","ptr",handle)
}


SetUnicodeStr(ByRef out, str_)
{
  VarSetCapacity(out,2*StrPut(str_,"utf-16"))
  StrPut(str_,&out,"utf-16")
}

Note: You will likely have to change the default value for Kbd. I had to change mine to Kbd=2 in order to work in Windows 8. Play with this value until you see a response (0-5 should be valid).

6
  • Thanks. Why did you set LEDvalue = 7 ? As I see CapsLock code is 4. Jul 2, 2013 at 15:32
  • Should I remove SetCapsLockState, AlwaysOff? Jul 2, 2013 at 15:36
  • You can keep your top 3 lines. The 7 was for all of the lights on the KB. If you only want the CapsLock LED, 4 should do it. Although, I have seen the numbers switched for certain keyboards, but it will be either 4, 2, or 1. Jul 2, 2013 at 15:39
  • Dear Ellion, When I press CapsLock fast the LED switches but the Keyboard language do not switch, is there any solution? Thanks in advance. Aug 27, 2013 at 6:24
  • Try SetKeyDelay, 0 at the top of your script. This makes it so the keystrokes to change the layout go faster. Your other option is to find a better way to change layout, preferable programmatically. Then to put that in the script instead of your Send keys. Aug 27, 2013 at 13:05
1

I think that the use CapsLock LED is not a good idea, here's an example with TrayTip:

; ListLines, Off
SetCapsLockState, Off
DllCall("RegisterShellHookWindow", "Ptr", A_ScriptHwnd)
OnMessage(DllCall("RegisterWindowMessage"(A_IsUnicode ? "W":"A")
                                         , "Str", "SHELLHOOK", "UInt")
                                         , "ShellMessage")
OnExit, % "ExitScript"
Global bState:=False

~CapsLock::bState:=!bState

ExitScript:
   DllCall("DeregisterShellHookWindow", "Ptr", A_ScriptHwnd)
   ExitApp

ShellMessage(aParams*)
{
   If aParams.1=4 ; HSHELL_WINDOWACTIVATED
   {
      HKL:=DllCall("GetKeyboardLayout", "UInt"
    , DllCall("GetWindowThreadProcessId", "Ptr", WinActive("A")
                                        , "UInt*", 0
                                        , "UInt")
                                      , "Ptr")
      IfEqual, bState, % False, TrayTip,, % "current is: "(HKL&16 ? "fa":"en")
   }
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .