Как отправить WM_INPUTLANGCHANGEREQUEST в приложение с модальным окном? - PullRequest
0 голосов
/ 30 июня 2018

Я написал переключатель клавиатуры, который работает хорошо, но не работает, если в текущем приложении открыто модальное окно. На переключателе клавиатуры я делаю следующее

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

, где

[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();

но язык не меняется.

Как бы мне этого добиться?


Добавление get root улучшило ситуацию, но не помогло полностью.

Добавление вызова для GetDesktopWindow не помогло:

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

Код здесь https://github.com/dims12/NormalKeyboardSwitcher

1 Ответ

0 голосов
/ 01 июля 2018

Использование GetAncestor

Извлекает собственное корневое окно, пройдя по цепочке родительского окна и окна владельца, возвращаемые GetParent.

Это должно вернуть главное окно пользовательского интерфейса, если есть модальное окно или цепочка модального окна.

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);
    }
}
...