Jump to content


Photo

[Solved] Autohotkey Script Input Language


  • Please log in to reply
10 replies to this topic

#1 stevenp

stevenp
  • Members
  • 187 posts

Posted 23 June 2012 - 02:06 PM

Sometimes I need to type text into an editbox or a gui in Russian, and then open a context menu.
All of the items are in English and most items from the context menus are selected with &keys, not mouse, so my aim is to set the Script's AHK Input Language back to English before a script's context menu is opened.
Here's a screen recording with the issue.

Ideas?

[Moderator's note: Moved topic from Issues to Support.]

#2 Lexikos

Lexikos
  • Administrators
  • 8839 posts

Posted 23 June 2012 - 03:01 PM

This behaviour is correct and expected. AutoHotkey is not in control of the input language; you are. You changed the language. If you want it changed back, change it back. There may be a way that your script can do this automatically; if you post in Support, perhaps someone will help you find it.

#3 stevenp

stevenp
  • Members
  • 187 posts

Posted 23 June 2012 - 03:44 PM

I have already researched for changing the language and wrapped it into a function, but it works only for the focused window:
Language(keyboardLayout) { 
   hwnd := ControlGet("HWND", "", ControlGetFocus("A"), "A")
   global WM_INPUTLANGCHANGEREQUEST 

   keyboardLayout := IIf(keyboardLayout="EN", "0x4090409", keyboardLayout) ;EN
   keyboardLayout := IIf(keyboardLayout="UA", "-0xF57FBDE", keyboardLayout) ;UA
   keyboardLayout := IIf(keyboardLayout="RU", "0x4190419", keyboardLayout) ;RU

   PostMessage, WM_INPUTLANGCHANGEREQUEST, 0, %keyboardLayout%, , ahk_id %hwnd%
}

How can I PostMessage directly to the active Script, and will it work?

Here's a test script I wrote to resolve the issue and added there the Language() function, but after the InputBox is closed, the Language switches from RU to EN then back to RU:
^CapsLock::
menu:
menu, 1, add, a, 1
menu, 1, add, b, 2
menu, 1, add, c..., 3
menu, 1, Show
return

1:
MsgBox selected a
goto menu

2:
MsgBox selected b
goto menu

3:
InputBox a, c
Language("EN")
goto menu
return

if this topic belongs to Support section of the Forum, could you move it there?

#4 stevenp

stevenp
  • Members
  • 187 posts

Posted 26 June 2012 - 01:15 PM

Thanks for moving this thread.
Does anyone know how to change Script's Input Language?

Tried this without success:
WM_INPUTLANGCHANGEREQUEST := 0x50
InputBox a, a
PostMessage, WM_INPUTLANGCHANGEREQUEST, 0, 0x4190419,, ahk_id %A_ScriptHwnd% ;Russian
InputBox b, b
PostMessage, WM_INPUTLANGCHANGEREQUEST, 0, 0x4090409,, ahk_id %A_ScriptHwnd% ;English
InputBox c, c


#5 Hamlet

Hamlet
  • Members
  • 195 posts

Posted 26 June 2012 - 03:31 PM

I do not know exactly whose idea is this.
I just copied from someone else and that someone else has copied it from another one...

Most of all I really thank to someone who made this script first. THANK you !!
In my case, it works 100% nicely.

Try it.
Msgbox % IME_Check()

IME_Check( hWnd = "" )
{
	IfEqual, hWnd,, WinGet, hWnd, ID, A
	DefaultIMEWnd := DllCall( "imm32\ImmGetDefaultIMEWnd", "UInt", hWnd)
	DetectSaved = %A_DetectHiddenWindows%
	DetectHiddenWindows, On
	SendMessage, 0x283, 5, 0,, ahk_id %DefaultIMEWnd%
	IfNotEqual, A_DetectHiddenWindows, %DetectSaved%, DetectHiddenWindows, %DetectSaved%
	Return  ErrorLevel
}


#6 stevenp

stevenp
  • Members
  • 187 posts

Posted 26 June 2012 - 06:36 PM

it returns 0, can you explain how this can function help to resolve the issue?

#7 Hamlet

Hamlet
  • Members
  • 195 posts

Posted 26 June 2012 - 11:43 PM

The name IME stands for Input Method Editor.
That is Microsofts's method to input variety of language to computer.
Have you tried the function at your language state ?
In my case, In English it returns Zero, and Not In English it returns One.
What is the your question/problem here ? Why did not you try to change language ?

#8 stevenp

stevenp
  • Members
  • 187 posts

Posted 22 July 2012 - 01:41 PM

Hamlet, the question is "How to change Autohotkey Active Running Script Input Language" and not how to get/check/detect current language
Please try this sample script:
^CapsLock::
menu:
menu, 1, add, a, 1
menu, 1, add, b, 2
menu, 1, add, c..., 3
menu, 1, Show
return

1:
MsgBox selected a
goto menu

2:
MsgBox selected b
goto menu

3:
InputBox a, Change Language to Russian or any other non-English language
Language("EN")
goto menu
return

Language(keyboardLayout) { 
	if keyboardLayout="EN"
		keyboardLayout := 0x4090409
	if keyboardLayout="RU"
		keyboardLayout := 0x4190419

	hwnd := ControlGet("HWND", "", ControlGetFocus("A"), "A")
	WM_INPUTLANGCHANGEREQUEST = 0x50
	PostMessage, WM_INPUTLANGCHANGEREQUEST, 0, %keyboardLayout%, , ahk_id %hwnd%
} 


#9 stevenp

stevenp
  • Members
  • 187 posts

Posted 22 July 2012 - 02:09 PM

Finally I have found a solution. Each ahk script contains at leat 3 windows:
1: D:\Script.ahk - AutoHotkey v1.1.08.00 ahk_class AutoHotkey
2: MSCTFIME UI ahk_class MSCTFIME UI
3: Default IME ahk_class IME

Sending a WM_INPUTLANGCHANGEREQUEST Message to the main AutoHotkey window handle have no effect, but there's a "Default IME" window which handles the input language.
; Define script's hidden "Default IME" window handle
hwndIME := 0
DetectHiddenWindows, On
WinGet, aHwnd, List, % "ahk_pid" DllCall("GetCurrentProcessId")
Loop, %aHwnd%
{
	hwndCurrent := aHwnd%A_Index%
	WinGetClass, sClass, ahk_id %hwndCurrent%
	if (sClass="IME") {
		hwndIME := hwndCurrent
		break
	}
}

another great clean method to get IME window hwnd, suggested by Hamlet:
; Define script's hidden "Default IME" window handle
DetectHiddenWindows, On
hwndScript := WinGet("ID", "ahk_pid" DllCall("GetCurrentProcessId"))
hwndIME := DllCall( "imm32\ImmGetDefaultIMEWnd", "UInt",hwndScript)


#10 JSLover

JSLover
  • Members
  • 920 posts

Posted 22 July 2012 - 02:19 PM

This should work just as well, without Looping...(I wrote this reply before the above edit using ImmGetDefaultIMEWnd() function, if there's a function for it, use that)...

; Define script's hidden "Default IME" window handle
DetectHiddenWindows, On
A_ScriptPID:=DllCall("GetCurrentProcessId")
hwndIME:=WinExist("ahk_class IME ahk_pid " A_ScriptPID)
This may also work...

hwndIME:=DllCall("imm32\ImmGetDefaultIMEWnd", "UInt", A_ScriptHWND)
...(yes, I meant to omit DetectHiddenWindows, On in this case, I don't think it'd be needed)...

#11 stevenp

stevenp
  • Members
  • 187 posts

Posted 22 July 2012 - 02:35 PM

WinExist() method is slower, but the last proposed one-line method is Instant! Amazing JSLover! Here's a benchmark:
SetBatchLines -1
		iTicks := A_TickCount
		DetectHiddenWindows, On
		Loop 1000 {
			A_ScriptPID:=DllCall("GetCurrentProcessId")
			hwndIME:=WinExist("ahk_class IME ahk_pid" A_ScriptPID)
		}
		iTicksWinExist := A_TickCount-iTicks
		iTicks := A_TickCount
		Loop 1000 {		
			hwndScript := WinGet("ID", "ahk_pid" DllCall("GetCurrentProcessId"))
			hwndIME := DllCall( "imm32\ImmGetDefaultIMEWnd", "UInt",hwndScript)
		}
		iTicksImmGetDefaultIMEWnd := A_TickCount-iTicks
		iTicks := A_TickCount
		Loop 1000 {		
			hwndIME:=DllCall("imm32\ImmGetDefaultIMEWnd", "UInt", A_ScriptHWND)
		}
		iTicksImmGetDefaultIMEWnd_A_ScriptHWND := A_TickCount-iTicks
		MsgBox,,Defining IME window handle Benchmark, WinExist():`t`t`t`t`t%iTicksWinExist% ticks`nImmGetDefaultIMEWnd() and WinGet():`t`t%iTicksImmGetDefaultIMEWnd% ticks`nImmGetDefaultIMEWnd() and A_ScriptHWND`t%iTicksImmGetDefaultIMEWnd_A_ScriptHWND% ticks

Benchmark Results (loop 1000):
[*:mo8vxnd5]WinExist(): 2621 ms
[*:mo8vxnd5]ImmGetDefaultIMEWnd() and WinGet(): 2043 ms
[*:mo8vxnd5]ImmGetDefaultIMEWnd() and A_ScriptHWND: 0 ms
However, "DetectHiddenWindows, On" is necessary before the
PostMessage, WM_INPUTLANGCHANGEREQUEST, 0, %keyboardLayout%, , ahk_id %hwndIME%
otherwise, somewhy, it doesn't change the input language even if script's known hwndIME is specified

Furthermore, SendMessage will not work, only PostMessage should be used to change ahk input language