更改键盘挂钩回拨内的键盘布局

时间:2013-05-25 21:17:41

标签: c# .net winapi keyboard-hook input-language

我在更改键盘挂钩内的键盘布局时遇到问题。在这个简单的代码中,当按下“A”键时,需要花费很多时间来更改语言,在更复杂的情况下,应用程序会做错误的事情。

应用程序在托盘中工作,因此我使用了钩子。 我的代码有什么问题? ))或者,也许有不同的方式来改变键盘布局,这适用于钩子?谢谢你的回答。

private static bool nextKey = false;

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
    uint tpid = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
    ushort currentLayout = GetKeyboardLayout(tpid);

    if (nCode >= 0 && wParam == (IntPtr) WM_KEYDOWN) {
        if (nextKey) {
            Console.WriteLine("changing to english...");
            PostMessage(GetForegroundWindow(), 0x0050, 0, (int) LoadKeyboardLayout("00000409", 0x00000001));
            nextKey = false;
        }

        int vkCode = Marshal.ReadInt32(lParam);

        if (vkCode == 0x41 && currentLayout == 0x409) { // if language is rus and 'A' pressed
            Console.WriteLine("changing to russian...");
            PostMessage(GetForegroundWindow(), 0x0050, 0, (int) LoadKeyboardLayout("00000419", 0x00000001));
            nextKey = true;
        }
    }
    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

1 个答案:

答案 0 :(得分:0)

在尝试修复此代码之前,我不得不提出几个愚蠢的问题:

  1. 为什么你需要在钩子内做这个?
  2. 为什么你需要这样做?您可以在键盘控制面板中指定一个热键来选择输入语言(区域和语言→键盘和语言→更改键盘→高级键设置)。每当您启用多种输入语言时,任务栏上都会放置一个图标。您不需要编写自己的应用来执行上述任何一项操作。
  3. 现在,专门查看您的代码,您正在做的是将WM_INPUTLANGCHANGEREQUEST消息发布到前台窗口。但是此消息是通知。它通知程序用户请求更改输入语言。它的目的不是允许程序向其他程序发出更改输入语言的请求。

    如果程序想要更改自己的键盘布局,则会调用ActivateKeyboardLayout函数。但是没有必要从.NET应用程序调用此函数。该框架已经将所有这些内容包含在强烈推荐的InputLanguage类中。

    除此之外,其他问题不可避免地存在于您未展示的代码中,代码属于其他应用程序。发布WM_INPUTLANGCHANGEREQUEST消息的前台窗口可以选择通过将消息传递到DefWindowProc来接受更改,或者通过在响应中返回0来拒绝更改。 If a broken application just返回0 for all those messages it does not explicitly process,它不会做正确的事情。或者,如果某个应用程序已被编写为明确拒绝WM_INPUTLANGCHANGEREQUEST个请求,那么它将无法满足您的期望。等等。你无法控制这些事情。请记住,WM_INPUTLANGCHANGEREQUEST只是一个请求。

    就速度问题而言("需要花费很多时间,更改语言"),首次加载输入语言并不能保证是一个快速的操作。我看到使用普通机制在我的机器上延迟了半秒钟。通常不是一个大瓶颈;大多数人不会多次来回切换。如果您确实需要加快速度,请考虑缓存LoadKeyboardLayout函数的返回值。