无法将WM_INPUTLANGCHANGEREQUEST发送到某些控件

本文关键字:控件 INPUTLANGCHANGEREQUEST WM | 更新日期: 2023-09-27 18:35:49

我正在研究(另一个)键盘布局切换器,并在使用Skype窗口(win6.22 x62版本)时遇到了奇怪的麻烦。GetForegroundWindow()/GetFocus()/GetParentWindow() 的任何组合都无法成功更改仅在消息输入内部的布局,更奇怪的是,只有在输入多个字符时。其他情况效果很好,除了 wpf 应用程序拒绝服从没有专注处理的东西。

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

无法将WM_INPUTLANGCHANGEREQUEST发送到某些控件

在拆卸了一些工作产品后,我发现我接近正确的算法,如下所示:

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 可以正确处理发送给它的所有输入。现在我必须在没有延迟的情况下让事情顺利进行,但这是另一回事。

你应该试试这个: PostMessage(hWnd,WM_INPUTLANGCHANGEREQUEST,0,(LPARAM)HKL_NEXT);

附言:在Windows 10下,任何WM_ INPUTLANGCHANGEREQUEST都会使Skype崩溃。

Windows 10的最佳方法是模拟切换键盘布局的按键,如下所示:

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