Keyboard layout switcher (Left shift = first system layout, Right shift = second one)

Post your working scripts, libraries and tools for AHK v1.1 and older
LogicDaemon
Posts: 21
Joined: 21 Feb 2014, 01:22

Keyboard layout switcher (Left shift = first system layout, Right shift = second one)

14 Jan 2018, 09:04

this is follow up to https://autohotkey.com/board/topic/2466 ... her/page-2

My problem is that I wanted to set specific layouts to specific keys, as in Left shift = En, Right shift = Ru; but I didn't find API function to switch to specific layout.

Code: Select all

;This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License <http://creativecommons.org/licenses/by-sa/4.0/>.
#NoEnv
#SingleInstance force
FileEncoding UTF-8
Process Priority,, High

layouts := GetLayoutList()
~LShift Up:: SwtichLang(layouts[1])
~RShift Up:: SwtichLang(layouts[2])

SwtichLang(newLocale) {
    Thread Priority, 1 ; No re-entrance
    If (A_ThisHotkey == "~" A_PriorKey " Up") {
	If ( InputLocaleID := DllCall("GetKeyboardLayout", "UInt", ThreadID := DllCall("GetWindowThreadProcessId", "UInt", WinExist("A"), "UInt", 0), "UInt") ) {
	    If (InputLocaleID != newLocale) { ; if language is not english XOR requested non-english
		ControlGetFocus,ctl
		PostMessage 0x50,3,%newLocale%,%ctl%,A ;WM_INPUTLANGCHANGEREQUEST - change locale, documentation https://msdn.microsoft.com/en-us/library/windows/desktop/ms632630.aspx
		; wParam
		; INPUTLANGCHANGE_BACKWARD 0x0004 A hot key was used to choose the previous input locale in the installed list of input locales. This flag cannot be used with the INPUTLANGCHANGE_FORWARD flag.
		; INPUTLANGCHANGE_FORWARD 0x0002 A hot key was used to choose the next input locale in the installed list of input locales. This flag cannot be used with the INPUTLANGCHANGE_BACKWARD flag.
		; INPUTLANGCHANGE_SYSCHARSET 0x0001 The new input locale's keyboard layout can be used with the system character set.
		
	    }
	}
    }
}

GetLayoutList() { ; List of system loaded layouts, from Lyt.ahk / https://autohotkey.com/boards/viewtopic.php?p=132600#p132600
    aLayouts := []
    size := DllCall("GetKeyboardLayoutList", "UInt", 0, "Ptr", 0)
    VarSetCapacity(list, A_PtrSize*size)
    size := DllCall("GetKeyboardLayoutList", Int, size, Str, list)
    Loop % size
	aLayouts[A_Index] := NumGet(list, A_PtrSize*(A_Index - 1))
    Return aLayouts
}
It actually should work with any dual-layout setup where one layout is US-English, since nothing else is hardcoded.
Last edited by LogicDaemon on 16 Feb 2018, 15:10, edited 3 times in total.
stealzy
Posts: 91
Joined: 01 Nov 2015, 13:43

Re: Keyboard layout switcher (Left shift = En, Right shift = Ru)

14 Jan 2018, 15:09

LogicDaemon wrote:GetKeyboardLayout seems to be only working once for a process
You are mistaken, it's something about your code.
Class Lyt:

Code: Select all

#Include Lyt.ahk
~LShift Up::(A_PriorKey = "LShift") ? Lyt.Set("en")
~RShift Up::(A_PriorKey = "RShift") ? Lyt.Set("-en")
; Lyt.Set("ru") Lyt.Set(1) Lyt.Set(2) Lyt.Set("Switch") Lyt.Set("Forward")
LogicDaemon wrote:by LogicDaemon <www.logicdaemon.ru> International License
Very nice :clap:. Do you think about EULA to the next version? Just don't forget to make the checkbox for not visiting your site.
LogicDaemon
Posts: 21
Joined: 21 Feb 2014, 01:22

Re: Keyboard layout switcher (Left shift = En, Right shift = Ru)

14 Jan 2018, 17:29

Very nice :clap:. Do you think about EULA to the next version? Just don't forget to make the checkbox for not visiting your site.
In my country, absence of license means program is for running it only (including copying to RAM) without permission for copying to non-volatile medium copy (except for single backup copy, which is permitted regardless of any copyright and/or EULAs). Why do these two lines hurt you so much?
You are mistaken, it's something about your code.
probably it is, still it's not something on the surface. I'll appreciate if anyone explains my mistake.

I tried following code on Win 8.1, it didn't work (it always switched with one shift, and never switched with the other). It does work on Windows 10 though.

Code: Select all

#NoEnv
#SingleInstance force
FileEncoding UTF-8
Process Priority,, High
SetFormat IntegerFast, Hex

~LShift Up:: SwtichLang(0)
~RShift Up:: SwtichLang(1)
SwtichLang(switchLocale) {
    static LOCALE_EN := 0x4090409, LOCALE_RU := 0x4190419
    Thread Priority, 1 ; No re-entrance
    If (A_ThisHotkey == "~" A_PriorKey " Up") {

	If ( InputLocaleID := DllCall("GetKeyboardLayout", "UInt", ThreadID := DllCall("GetWindowThreadProcessId", "UInt", WinExist("A"), "UInt", 0), "UInt") ) {
	    If ((InputLocaleID != LOCALE_EN ) ^ switchLocale) { ; if language is not english XOR requested Russian
		ControlGetFocus,ctl
		PostMessage 0x50,0,0,%ctl%,A ;WM_INPUTLANGCHANGEREQUEST - change locale, documentation https://msdn.microsoft.com/en-us/library/windows/desktop/ms632630(v=vs.85).aspx
		;Sleep 1
		;ToolTip % InputLocaleID " | " DllCall("GetKeyboardLayout", "UInt", ThreadID := DllCall("GetWindowThreadProcessId", "UInt", WinExist("A"), "UInt", 0), "UInt")
	    }
	}
    }
}
stealzy
Posts: 91
Joined: 01 Nov 2015, 13:43

Re: Keyboard layout switcher (Left shift = En, Right shift = Ru)

15 Jan 2018, 02:21

Code: Select all

#Include Lyt.ahk
~LShift Up::(A_PriorKey = "LShift") ? Lyt.Set("en")
~RShift Up::(A_PriorKey = "RShift") ? Lyt.Set("ru")

; ~LShift Up::Lyt.Set("en")
; ~RShift Up::Lyt.Set("ru")
Does it work?
LogicDaemon
Posts: 21
Joined: 21 Feb 2014, 01:22

Re: Keyboard layout switcher (Left shift = En, Right shift = Ru)

15 Jan 2018, 14:59

your class is cool, but I don't want to use it.
No idea what was wrong, but current code works fine. I updated first post.
LogicDaemon
Posts: 21
Joined: 21 Feb 2014, 01:22

Re: Keyboard layout switcher (Left shift = En, Right shift = Ru)

16 Feb 2018, 15:10

first post updated, now script gets layout list from system instead of using hardcoded EN-US (409) layout. Will work with UK layout now :)

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 71 guests