Jump to content

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

[Solved] Autohotkey Script Input Language


  • Please log in to reply
10 replies to this topic
stevenp
  • Members
  • 197 posts
  • Last active: Sep 23 2014 05:47 PM
  • Joined: 28 Aug 2006
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.]
"Simplifying complexity is not simple"

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
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.

stevenp
  • Members
  • 197 posts
  • Last active: Sep 23 2014 05:47 PM
  • Joined: 28 Aug 2006
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?
"Simplifying complexity is not simple"

stevenp
  • Members
  • 197 posts
  • Last active: Sep 23 2014 05:47 PM
  • Joined: 28 Aug 2006
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

"Simplifying complexity is not simple"

Hamlet
  • Members
  • 302 posts
  • Last active: Mar 23 2014 03:37 PM
  • Joined: 22 Jan 2009
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
}


stevenp
  • Members
  • 197 posts
  • Last active: Sep 23 2014 05:47 PM
  • Joined: 28 Aug 2006
it returns 0, can you explain how this can function help to resolve the issue?
"Simplifying complexity is not simple"

Hamlet
  • Members
  • 302 posts
  • Last active: Mar 23 2014 03:37 PM
  • Joined: 22 Jan 2009
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 ?

stevenp
  • Members
  • 197 posts
  • Last active: Sep 23 2014 05:47 PM
  • Joined: 28 Aug 2006
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%
} 

"Simplifying complexity is not simple"

stevenp
  • Members
  • 197 posts
  • Last active: Sep 23 2014 05:47 PM
  • Joined: 28 Aug 2006
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)

"Simplifying complexity is not simple"

JSLover
  • Members
  • 920 posts
  • Last active: Nov 02 2012 09:54 PM
  • Joined: 20 Dec 2004
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)...
Useful forum links: New content since: Last visitPast weekPast 2 weeks (links will show YOUR posts, not mine)

OMFG, the AutoHotkey forum is IP.board now (yuck!)...I may not be able to continue coming here (& I love AutoHotkey)...I liked phpBB, but not this...ugh...

Note...
I may not reply to any topics (specifically ones I was previously involved in), mostly cuz I can't find the ones I replied to, to continue helping, but also just cuz I can't stand the new forum...phpBB was soo perfect. This is 100% the opposite of "perfect".

I also semi-plan to start my own, phpBB-based AutoHotkey forum (or take over the old one, if he'll let me)
PM me if you're interested in a new phpBB-based forum (I need to know if anyone would use it)
How (or why) did they create the Neil Armstrong memorial site (neilarmstronginfo.com) BEFORE he died?

stevenp
  • Members
  • 197 posts
  • Last active: Sep 23 2014 05:47 PM
  • Joined: 28 Aug 2006
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
"Simplifying complexity is not simple"