How to send WM_INPUTLANGCHANGEREQUEST to app with modal window?

人走茶凉 提交于 2020-05-13 05:33:46

问题


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:

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

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


回答1:


Use 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


Apparently WM_INPUTLANGCHANGEREQUEST fails if the target itself is a dialog based application (I don't know why!) To solve the problem you can post WM_INPUTLANGCHANGEREQUEST message to dialog's descendants (in addition to WM_INPUTLANGCHANGEREQUEST message to the dialog itself)
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);
    }
}


来源:https://stackoverflow.com/questions/51117874/how-to-send-wm-inputlangchangerequest-to-app-with-modal-window

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!