How to send WM_INPUTLANGCHANGEREQUEST to app with modal window?

Multi tool use
Multi tool use


How to send WM_INPUTLANGCHANGEREQUEST to app with modal window?



I wrote a keyboard switcher, which works well, but fails if current application has modal window opened. On keyboard switch I do the following


hwnd = GetForegroundWindow();
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, handle);



where


[DllImport("User32.dll", EntryPoint = "PostMessage")]
private static extern int PostMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();



but the language does not change.



How would I accomplish this?



Adding get root owner improved situation, but didn't help completely.



Adding call for GetDesktopWindow didn't help:


GetDesktopWindow


hwnd = GetDesktopWindow();
InputLangChangeRequest(hwnd, language);
hwnd = GetRootOwner();
InputLangChangeRequest(hwnd, language);



Code is here https://github.com/dims12/NormalKeyboardSwitcher





Possible duplicate of Can't send WM_INPUTLANGCHANGEREQUEST to some controls
– Remy Lebeau
Jun 30 at 21:24




1 Answer
1



Use GetAncestor


GetAncestor



Retrieves the owned root window by walking the chain of parent and
owner windows returned by GetParent.



This should return the main UI window if there is a modal window, or a chain of modal window.


hwnd = GetForegroundWindow();
hwnd = GetAncestor(hwnd, GA_ROOTOWNER); //#define GA_ROOTOWNER 3




WM_INPUTLANGCHANGEREQUEST


WM_INPUTLANGCHANGEREQUEST


WM_INPUTLANGCHANGEREQUEST


static bool MyEnumProc(IntPtr hwnd, IntPtr lParam)
{
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, lParam);
return true;
}

static void Foo()
{
//Greek input for testing:
var hkl = LoadKeyboardLayout("00000408", KLF_ACTIVATE);
var hwnd = GetForegroundWindow();
if (hwnd != null)
{
hwnd = GetAncestor(hwnd, GA_ROOTOWNER);
PostMessage(hwnd, WM_INPUTLANGCHANGEREQUEST, IntPtr.Zero, (IntPtr)hkl);

StringBuilder buf = new StringBuilder(100);
GetClassName(hwnd, buf, 100);

//if this is a dialog class then post message to all descendants
if (buf.ToString() == "#32770")
EnumChildWindows(hwnd, MyEnumProc, (IntPtr)hkl);
}
}





Doesn't help. May be the task is opposite? Need to find deepest descendant window, not ancestor?
– Dims
Jul 1 at 16:59





I have checked window handle with WinSpy++ and found that: (1) the sequence above finds window incorrectly and (2) if I rely on other process (tracking of foreground window change) and get the same hex of a handle, sending message still doesn't switch the language
– Dims
Jul 1 at 17:15





I was partially wrong: the handle is correct both ways (incorrect hadnler was due to switch to debugger), but the language is still not changed.
– Dims
Jul 1 at 17:21





I thought you said it works when window does not have a modal dialog on top. So it should work if GetAncestor returns the right window handle. I tested this with Notepad. It also works when Notepad's About Dialog is active. Using LoadKeyboardLayout("00000408", KLF_ACTIVATE) for test. Note that this only changes the keyboard language.
– Barmak Shemirani
Jul 1 at 17:51



GetAncestor


LoadKeyboardLayout("00000408", KLF_ACTIVATE)





Yes you are right, I have checked and it works with modal window (File->Open) in Notepad. But it doesn't work if application has only one window and it's modal (Pageant)
– Dims
Jul 1 at 18:21


Notepad


Pageant






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

fkC5dRCHqznDIPX q
E tN0,TzpJ3Y6BYdsdX4hW,KAKB,2cFeFy2ze0mY7

Popular posts from this blog

Rothschild family

Cinema of Italy