c# - 无法将 WM_INPUTLANGCHANGEREQUEST 发送到某些控件

标签 c# windows winapi

我正在研究(又一个)keyboard layout switcher并在 Skype 窗口(win7 x64 上的 6.22 版)中遇到了奇怪的麻烦。 Any combinations GetForegroundWindow()/GetFocus()/GetParentWindow() 不会成功更改布局仅在消息输入内,更奇怪的是,仅当输入多个字符时。其他情况下工作得非常好,除了 wpf 应用程序拒绝服从没有 focusedHandle 的东西。

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 的新手,所以任何帮助都将不胜感激,谢谢。

最佳答案

在分解了一些工作产品后,我发现我已经接近正确的算法,看起来像这样:

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 就可以正确处理发送给它的所有输入。现在我必须立即开始工作,但这是另一回事了。

关于c# - 无法将 WM_INPUTLANGCHANGEREQUEST 发送到某些控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27720728/

相关文章:

c# - 如何从 Selenium 中的 href 链接获取属性值

子窗口绘画引用

c++ - 生成 WM_NCHITTEST 消息

c++ - 我可以使用 %p 说明符输出 Windows 句柄吗?

c# - 我的页面不会显示我的多 View View

c# - 是否可以通过容器/包装器在 WPF 表单中托管 WinForm 表单?

c# - 使用 LINQ 获取组的平均值

java - Firefox 未在 Windows 机器上的首选项中更新应用程序关联

c++ - 内核态和用户态共享内存。如何共享句柄?

c++ - 有没有办法模拟从右键单击鼠标菜单发送到控制台的调用?