Can't send WM_INPUTLANGCHANGEREQUEST to some controls

I am working (yet another) keyboard layout switcher and got strange problems with Skype window (ver. 6.22 on win7 x64). Any combinations of GetForegroundWindow () / GetFocus () / GetParentWindow () cannot change the layout just inside the message input and, even weirder , only if more than one character is entered . Other cases work fine except wpf apps which refuse to obey without a Focused Handle stuff.

public static void SetNextKeyboardLayout()
    {
        IntPtr hWnd = GetForegroundWindow();
        uint processId;
        uint activeThreadId = GetWindowThreadProcessId(hWnd, out processId);
        uint currentThreadId = GetCurrentThreadId();

        AttachThreadInput(activeThreadId, currentThreadId, true);
        IntPtr focusedHandle = GetFocus();
        AttachThreadInput(activeThreadId, currentThreadId, false);

        PostMessage(focusedHandle == IntPtr.Zero ? hWnd : focusedHandle, WM_INPUTLANGCHANGEREQUEST, INPUTLANGCHANGE_FORWARD, HKL_NEXT);
    }

      

I'm new to winapi stuff so any help would be kindly appreciated, thanks.

+3


source to share


3 answers


After disassembling some work products, I found out that I was close to the correct algorithm, which looks like this:

public static void SetNextKeyboardLayout()
{
    IntPtr hWnd = IntPtr.Zero;
    var threadId = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
    var currentThreadId = GetCurrentThreadId();

    var info = new GUITHREADINFO();
    info.cbSize = Marshal.SizeOf(info);
    var success = GetGUIThreadInfo(threadId, ref info);

    // target = hwndCaret || hwndFocus || (AttachThreadInput + GetFocus) || hwndActive || GetForegroundWindow
    AttachThreadInput(threadId, currentThreadId, true);
    IntPtr focusedHandle = GetFocus();
    AttachThreadInput(threadId, currentThreadId, false);
    if (success)
    {
        if (info.hwndCaret != IntPtr.Zero) { hWnd = info.hwndCaret; }
        else if (info.hwndFocus != IntPtr.Zero) { hWnd = info.hwndFocus; }
        else if (focusedHandle != IntPtr.Zero) { hWnd = focusedHandle; }
        else if (info.hwndActive != IntPtr.Zero) { hWnd = info.hwndActive; }
    }
    else
    {
        hWnd = focusedHandle;
    }
    if (hWnd == IntPtr.Zero) { hWnd = GetForegroundWindow(); }

    PostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST, INPUTLANGCHANGE_FORWARD, HKL_NEXT);
}

      



But the problem was not the PostMessage target hWnd search, but the skype input handling. I solved this by adding a tiny delay before WM_INPUTLANGCHANGEREQUEST

so that skype can properly handle all the data sent to it. Now I need to get everything to work without this delay, but that's another story.

+2


source


You should try the following: PostMessage(hWnd,WM_INPUTLANGCHANGEREQUEST,0,(LPARAM)HKL_NEXT);



PS .: In Windows 10 any WM_ will INPUTLANGCHANGEREQUEST

disable Skype.

0


source


The best way with Windows 10 is to emulate the keys for the keyboard layout of the keyboard, for example:

keybd_event(VK_LWIN, 0, KEYEVENTF_EXTENDEDKEY, 0);
keybd_event(VK_SPACE,0, KEYEVENTF_EXTENDEDKEY, 0);
Sleep(10);
keybd_event(VK_SPACE,0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
keybd_event(VK_LWIN, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);

      

0


source







All Articles