无法将WM_INPUTLANGCHANGEREQUEST发送给某些控件 [英] Can't send WM_INPUTLANGCHANGEREQUEST to some controls

查看:46
本文介绍了无法将WM_INPUTLANGCHANGEREQUEST发送给某些控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在(另外)正在研究键盘布局切换器,并在Skype窗口中遇到了奇怪的麻烦(在win7 x64上显示为ver 6.22).GetForegroundWindow()/GetFocus()/GetParentWindow(的任何组合)仅在输入的消息中不能成功更改布局 ,更奇怪的是,只有输入多个字符时才能更改.除wpf应用程序拒绝不使用focusedHandle内容而服从之外,其他情况下效果都很好.

I'm working on (yet another) keyboard layout switcher and got strange troubles with Skype window (ver 6.22 on win7 x64). Any combinations of GetForegroundWindow() / GetFocus() / GetParentWindow() don't succeed to change the layout only inside the message input and, even more strange, only if more than one character is entered. Other cases work perfectly nice except wpf apps which refuse to obey without focusedHandle 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);
    }

我对winapi还是陌生的,所以对您的帮助将不胜感激,谢谢.

I'm new to winapi things, so any help will be kindly appreciated, thank you.

推荐答案

在分解了一些工作产品之后,我发现我已经接近了正确的算法,如下所示:

After disassembling some of working products i've figured out that i was close to the right algorythm 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);
}

但是问题不是在查找PostMessage目标hWnd,而是在Skype的输入处理中.我已通过在 WM_INPUTLANGCHANGEREQUEST 之前添加一个微小的延迟来解决它,以便Skype可以正确处理发送给它的所有输入.现在,我必须让工作正常进行,而不能拖延,但这是另一回事了.

But the problem was not in finding PostMessage target hWnd, but in skype's input handling. I have solved it by adding a tiny delay before WM_INPUTLANGCHANGEREQUEST so skype can properly process all the input sent to it. Now i have to get things working without this delay but this is another story.

这篇关于无法将WM_INPUTLANGCHANGEREQUEST发送给某些控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆